Remove WebHistoryItem child usage

HistoryEntry is now used to store the history tree.

BUG=

Review URL: https://codereview.chromium.org/248013003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267274 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 33c0fdb..994c7be 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -125,17 +125,18 @@
   ProcessPendingMessages();
 }
 
-void RenderViewTest::GoBack(const blink::WebHistoryItem& item) {
-  GoToOffset(-1, item);
+void RenderViewTest::GoBack(const PageState& state) {
+  GoToOffset(-1, state);
 }
 
-void RenderViewTest::GoForward(const blink::WebHistoryItem& item) {
-  GoToOffset(1, item);
+void RenderViewTest::GoForward(const PageState& state) {
+  GoToOffset(1, state);
 }
 
 void RenderViewTest::GoBackToPrevious() {
   RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
-  GoBack(impl->history_controller()->GetPreviousItemForExport());
+  GoBack(HistoryEntryToPageState(
+      impl->history_controller()->GetPreviousEntry()));
 }
 
 void RenderViewTest::SetUp() {
@@ -400,8 +401,7 @@
   return new ContentRendererClient;
 }
 
-void RenderViewTest::GoToOffset(int offset,
-                                const blink::WebHistoryItem& history_item) {
+void RenderViewTest::GoToOffset(int offset, const PageState& state) {
   RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
 
   int history_list_length = impl->historyBackListCount() +
@@ -415,7 +415,7 @@
   navigate_params.current_history_list_offset = impl->history_list_offset();
   navigate_params.pending_history_list_offset = pending_offset;
   navigate_params.page_id = impl->GetPageId() + offset;
-  navigate_params.page_state = HistoryItemToPageState(history_item);
+  navigate_params.page_state = state;
   navigate_params.request_time = base::Time::Now();
 
   FrameMsg_Navigate navigate_message(impl->main_render_frame()->GetRoutingID(),
diff --git a/content/public/test/render_view_test.h b/content/public/test/render_view_test.h
index 8582bb6..5af0f6e 100644
--- a/content/public/test/render_view_test.h
+++ b/content/public/test/render_view_test.h
@@ -19,7 +19,6 @@
 #include "third_party/WebKit/public/web/WebFrame.h"
 
 namespace blink {
-class WebHistoryItem;
 class WebWidget;
 }
 
@@ -32,6 +31,7 @@
 class ContentClient;
 class ContentRendererClient;
 class MockRenderProcess;
+class PageState;
 class RendererMainPlatformDelegate;
 class RendererWebKitPlatformSupportImplNoSandboxImpl;
 class RenderView;
@@ -77,10 +77,9 @@
   void LoadHTML(const char* html);
 
   // Navigates the main frame back or forward in session history and commits.
-  // The caller must capture a WebHistoryItem for the target page. This is
-  // available from the WebFrame.
-  void GoBack(const blink::WebHistoryItem& item);
-  void GoForward(const blink::WebHistoryItem& item);
+  // The caller must capture a PageState for the target page.
+  void GoBack(const PageState& state);
+  void GoForward(const PageState& state);
 
   // Navigates the main frame back to whatever is considered the previous
   // history entry internally.
@@ -159,7 +158,7 @@
 #endif
 
  private:
-  void GoToOffset(int offset, const blink::WebHistoryItem& history_item);
+  void GoToOffset(int offset, const PageState& state);
 };
 
 }  // namespace content
diff --git a/content/renderer/context_menu_params_builder.cc b/content/renderer/context_menu_params_builder.cc
index 0b3af2b1..d56c6ead 100644
--- a/content/renderer/context_menu_params_builder.cc
+++ b/content/renderer/context_menu_params_builder.cc
@@ -49,8 +49,10 @@
   for (size_t i = 0; i < data.customItems.size(); ++i)
     params.custom_items.push_back(MenuItemBuilder::Build(data.customItems[i]));
 
-  if (!data.frameHistoryItem.isNull())
-    params.frame_page_state = HistoryItemToPageState(data.frameHistoryItem);
+  if (!data.frameHistoryItem.isNull()) {
+    params.frame_page_state =
+        SingleHistoryItemToPageState(data.frameHistoryItem);
+  }
 
   if (!params.link_url.is_empty()) {
     blink::WebNode selectedNode = data.node;
diff --git a/content/renderer/history_controller.cc b/content/renderer/history_controller.cc
index b47930e..d3efebea 100644
--- a/content/renderer/history_controller.cc
+++ b/content/renderer/history_controller.cc
@@ -35,18 +35,14 @@
 
 #include "content/renderer/history_controller.h"
 
-#include <deque>
-
 #include "content/renderer/render_frame_impl.h"
 #include "content/renderer/render_view_impl.h"
-#include "third_party/WebKit/public/platform/WebVector.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
 
 using blink::WebFrame;
 using blink::WebHistoryCommitType;
 using blink::WebHistoryItem;
 using blink::WebURLRequest;
-using blink::WebVector;
 
 namespace content {
 
@@ -68,17 +64,24 @@
   if (current_entry_) {
     RecursiveGoToEntry(
         main_frame, same_document_loads, different_document_loads);
-  } else {
-    different_document_loads.push_back(
-        std::make_pair(main_frame, provisional_entry_->root()));
   }
 
   if (same_document_loads.empty() && different_document_loads.empty()) {
-    same_document_loads.push_back(
+    // If we don't have any frames to navigate at this point, either
+    // (1) there is no previous history entry to compare against, or
+    // (2) we were unable to match any frames by name. In the first case,
+    // doing a different document navigation to the root item is the only valid
+    // thing to do. In the second case, we should have been able to find a
+    // frame to navigate based on names if this were a same document
+    // navigation, so we can safely assume this is the different document case.
+    different_document_loads.push_back(
         std::make_pair(main_frame, provisional_entry_->root()));
-  }
-
-  if (different_document_loads.empty()) {
+  } else if (different_document_loads.empty()) {
+    // If we have only same document navigations to perform, immediately
+    // declare the load "committed" by updating the current entry.
+    // TODO(japhet): This is a historical quirk, because same-document
+    // history navigations call UpdateForCommit() with commit type
+    // HistoryInertCommit. If that is fixed, we can remove this block.
     previous_entry_.reset(current_entry_.release());
     current_entry_.reset(provisional_entry_.release());
   }
@@ -131,35 +134,6 @@
   }
 }
 
-void HistoryController::GoToItem(const WebHistoryItem& target_item,
-                                 WebURLRequest::CachePolicy cache_policy) {
-  // We don't have enough information to set a correct frame id here. This
-  // might be a restore from disk, and the frame ids might not match up if the
-  // state was saved from a different process. Ensure the HistoryEntry's main
-  // frame id matches the actual main frame id. Its subframe ids are invalid to
-  // ensure they don't accidentally match a potentially random frame.
-  HistoryEntry* new_entry = new HistoryEntry(
-      target_item, render_view_->main_render_frame()->GetRoutingID());
-  std::deque<HistoryEntry::HistoryNode*> history_nodes;
-  history_nodes.push_back(new_entry->root_history_node());
-  while (!history_nodes.empty()) {
-    // For each item, read the children (if any) off the WebHistoryItem,
-    // create a new HistoryNode for each child and attach it,
-    // then clear the children on the WebHistoryItem.
-    HistoryEntry::HistoryNode* history_node = history_nodes.front();
-    history_nodes.pop_front();
-
-    WebVector<WebHistoryItem> children = history_node->item().children();
-    for (size_t i = 0; i < children.size(); i++) {
-      HistoryEntry::HistoryNode* child_history_node =
-          history_node->AddChild(children[i], kInvalidFrameRoutingID);
-      history_nodes.push_back(child_history_node);
-    }
-    history_node->item().setChildren(WebVector<WebHistoryItem>());
-  }
-  GoToEntry(new_entry, cache_policy);
-}
-
 void HistoryController::UpdateForInitialLoadInChildFrame(
     RenderFrameImpl* frame,
     const WebHistoryItem& item) {
@@ -195,27 +169,12 @@
   }
 }
 
-static WebHistoryItem ItemForExport(HistoryEntry::HistoryNode* history_node) {
-  DCHECK(history_node);
-  WebHistoryItem item = history_node->item();
-  item.setChildren(WebVector<WebHistoryItem>());
-  std::vector<HistoryEntry::HistoryNode*>& child_nodes =
-      history_node->children();
-  for (size_t i = 0; i < child_nodes.size(); i++)
-    item.appendToChildren(ItemForExport(child_nodes.at(i)));
-  return item;
+HistoryEntry* HistoryController::GetCurrentEntry() {
+  return current_entry_.get();
 }
 
-WebHistoryItem HistoryController::GetCurrentItemForExport() {
-  if (!current_entry_)
-    return WebHistoryItem();
-  return ItemForExport(current_entry_->root_history_node());
-}
-
-WebHistoryItem HistoryController::GetPreviousItemForExport() {
-  if (!previous_entry_)
-    return WebHistoryItem();
-  return ItemForExport(previous_entry_->root_history_node());
+HistoryEntry* HistoryController::GetPreviousEntry() {
+  return previous_entry_.get();
 }
 
 WebHistoryItem HistoryController::GetItemForNewChildFrame(
diff --git a/content/renderer/history_controller.h b/content/renderer/history_controller.h
index 0118b0bc..e57bed39 100644
--- a/content/renderer/history_controller.h
+++ b/content/renderer/history_controller.h
@@ -109,23 +109,20 @@
   explicit HistoryController(RenderViewImpl* render_view);
   ~HistoryController();
 
-  void GoToItem(const blink::WebHistoryItem& item,
-                blink::WebURLRequest::CachePolicy cache_policy);
+  void GoToEntry(HistoryEntry* entry,
+                 blink::WebURLRequest::CachePolicy cache_policy);
 
   void UpdateForCommit(RenderFrameImpl* frame,
                        const blink::WebHistoryItem& item,
                        blink::WebHistoryCommitType commit_type,
                        bool navigation_within_page);
 
-  blink::WebHistoryItem GetCurrentItemForExport();
-  blink::WebHistoryItem GetPreviousItemForExport();
+  HistoryEntry* GetCurrentEntry();
+  HistoryEntry* GetPreviousEntry();
   blink::WebHistoryItem GetItemForNewChildFrame(RenderFrameImpl* frame) const;
   void RemoveChildrenForRedirect(RenderFrameImpl* frame);
 
  private:
-  void GoToEntry(HistoryEntry* entry,
-                 blink::WebURLRequest::CachePolicy cache_policy);
-
   typedef std::vector<std::pair<blink::WebFrame*, blink::WebHistoryItem> >
       HistoryFrameLoadVector;
   void RecursiveGoToEntry(blink::WebFrame* frame,
diff --git a/content/renderer/history_entry.cc b/content/renderer/history_entry.cc
index 8d168ee5..63c1ea0 100644
--- a/content/renderer/history_entry.cc
+++ b/content/renderer/history_entry.cc
@@ -35,8 +35,6 @@
 
 #include "content/renderer/history_entry.h"
 
-#include <deque>
-
 #include "content/renderer/render_frame_impl.h"
 #include "content/renderer/render_view_impl.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
@@ -53,6 +51,10 @@
   return children_->back();
 }
 
+HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::AddChild() {
+  return AddChild(WebHistoryItem(), kInvalidFrameRoutingID);
+}
+
 HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::CloneAndReplace(
     HistoryEntry* new_entry,
     const WebHistoryItem& new_item,
@@ -90,13 +92,21 @@
   return new_history_node;
 }
 
+void HistoryEntry::HistoryNode::set_item(const WebHistoryItem& item) {
+  // The previous HistoryItem might not have had a target set, or it might be
+  // different than the current one.
+  entry_->unique_names_to_items_[item.target().utf8()] = this;
+  item_ = item;
+}
+
 HistoryEntry::HistoryNode::HistoryNode(HistoryEntry* entry,
                                        const WebHistoryItem& item,
                                        int64_t frame_id)
     : entry_(entry), item_(item) {
   if (frame_id != kInvalidFrameRoutingID)
     entry_->frames_to_items_[frame_id] = this;
-  entry_->unique_names_to_items_[item.target().utf8()] = this;
+  if (!item.isNull())
+    entry_->unique_names_to_items_[item.target().utf8()] = this;
   children_.reset(new ScopedVector<HistoryNode>);
 }
 
@@ -138,6 +148,7 @@
 }
 
 HistoryEntry::HistoryEntry() {
+  root_.reset(new HistoryNode(this, WebHistoryItem(), kInvalidFrameRoutingID));
 }
 
 HistoryEntry::~HistoryEntry() {
diff --git a/content/renderer/history_entry.h b/content/renderer/history_entry.h
index f8cc14d5..62da86a 100644
--- a/content/renderer/history_entry.h
+++ b/content/renderer/history_entry.h
@@ -38,6 +38,7 @@
 #include "base/containers/hash_tables.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
+#include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
 #include "third_party/WebKit/public/web/WebHistoryItem.h"
 
@@ -51,7 +52,7 @@
 
 const int kInvalidFrameRoutingID = -1;
 
-class HistoryEntry {
+class CONTENT_EXPORT HistoryEntry {
  public:
   class HistoryNode {
    public:
@@ -61,13 +62,14 @@
     ~HistoryNode();
 
     HistoryNode* AddChild(const blink::WebHistoryItem& item, int64_t frame_id);
+    HistoryNode* AddChild();
     HistoryNode* CloneAndReplace(HistoryEntry* new_entry,
                                  const blink::WebHistoryItem& new_item,
                                  bool clone_children_of_target,
                                  RenderFrameImpl* target_frame,
                                  RenderFrameImpl* current_frame);
     blink::WebHistoryItem& item() { return item_; }
-    void set_item(const blink::WebHistoryItem& item) { item_ = item; }
+    void set_item(const blink::WebHistoryItem& item);
     std::vector<HistoryNode*>& children() const { return children_->get(); }
     void RemoveChildren();
 
@@ -78,6 +80,7 @@
   };
 
   HistoryEntry(const blink::WebHistoryItem& root, int64_t frame_id);
+  HistoryEntry();
   ~HistoryEntry();
 
   HistoryEntry* CloneAndReplace(const blink::WebHistoryItem& newItem,
@@ -91,7 +94,6 @@
   HistoryNode* root_history_node() const { return root_.get(); }
 
  private:
-  HistoryEntry();
 
   scoped_ptr<HistoryNode> root_;
 
diff --git a/content/renderer/history_serialization.cc b/content/renderer/history_serialization.cc
index f6a4987c..c007907 100644
--- a/content/renderer/history_serialization.cc
+++ b/content/renderer/history_serialization.cc
@@ -6,6 +6,7 @@
 
 #include "content/common/page_state_serialization.h"
 #include "content/public/common/page_state.h"
+#include "content/renderer/history_entry.h"
 #include "third_party/WebKit/public/platform/WebHTTPBody.h"
 #include "third_party/WebKit/public/platform/WebPoint.h"
 #include "third_party/WebKit/public/platform/WebString.h"
@@ -79,8 +80,8 @@
   }
 }
 
-bool RecursivelyGenerateFrameState(const WebHistoryItem& item,
-                                   ExplodedFrameState* state) {
+void GenerateFrameStateFromItem(const WebHistoryItem& item,
+                                ExplodedFrameState* state) {
   state->url_string = item.urlString();
   state->referrer = item.referrer();
   state->referrer_policy = item.referrerPolicy();
@@ -106,68 +107,64 @@
     }
     state->http_body.contains_passwords = http_body.containsPasswordData();
   }
-
-  const WebVector<WebHistoryItem>& children = item.children();
-  state->children.resize(children.size());
-  for (size_t i = 0; i < children.size(); ++i) {
-    if (!RecursivelyGenerateFrameState(children[i], &state->children[i]))
-      return false;
-  }
-
-  return true;
 }
 
-bool RecursivelyGenerateHistoryItem(const ExplodedFrameState& state,
-                                    WebHistoryItem* item) {
-  item->setURLString(state.url_string);
-  item->setReferrer(state.referrer, state.referrer_policy);
-  item->setTarget(state.target);
+void RecursivelyGenerateFrameState(HistoryEntry::HistoryNode* node,
+                                   ExplodedFrameState* state) {
+  GenerateFrameStateFromItem(node->item(), state);
+
+  std::vector<HistoryEntry::HistoryNode*>& children = node->children();
+  state->children.resize(children.size());
+  for (size_t i = 0; i < children.size(); ++i)
+    RecursivelyGenerateFrameState(children[i], &state->children[i]);
+}
+
+void RecursivelyGenerateHistoryItem(const ExplodedFrameState& state,
+                                    HistoryEntry::HistoryNode* node) {
+  WebHistoryItem item;
+  item.initialize();
+  item.setURLString(state.url_string);
+  item.setReferrer(state.referrer, state.referrer_policy);
+  item.setTarget(state.target);
   if (!state.state_object.is_null()) {
-    item->setStateObject(
+    item.setStateObject(
         WebSerializedScriptValue::fromString(state.state_object));
   }
-  item->setDocumentState(state.document_state);
-  item->setScrollOffset(state.scroll_offset);
-  item->setPageScaleFactor(state.page_scale_factor);
+  item.setDocumentState(state.document_state);
+  item.setScrollOffset(state.scroll_offset);
+  item.setPageScaleFactor(state.page_scale_factor);
 
   // These values are generated at WebHistoryItem construction time, and we
   // only want to override those new values with old values if the old values
   // are defined.  A value of 0 means undefined in this context.
   if (state.item_sequence_number)
-    item->setItemSequenceNumber(state.item_sequence_number);
+    item.setItemSequenceNumber(state.item_sequence_number);
   if (state.document_sequence_number)
-    item->setDocumentSequenceNumber(state.document_sequence_number);
+    item.setDocumentSequenceNumber(state.document_sequence_number);
 
-  item->setHTTPContentType(state.http_body.http_content_type);
+  item.setHTTPContentType(state.http_body.http_content_type);
   if (!state.http_body.is_null) {
     WebHTTPBody http_body;
     http_body.initialize();
     http_body.setIdentifier(state.http_body.identifier);
     for (size_t i = 0; i < state.http_body.elements.size(); ++i)
       AppendHTTPBodyElement(state.http_body.elements[i], &http_body);
-    item->setHTTPBody(http_body);
+    item.setHTTPBody(http_body);
   }
+  node->set_item(item);
 
-  for (size_t i = 0; i < state.children.size(); ++i) {
-    WebHistoryItem child_item;
-    child_item.initialize();
-    if (!RecursivelyGenerateHistoryItem(state.children[i], &child_item))
-      return false;
-    item->appendToChildren(child_item);
-  }
-
-  return true;
+  for (size_t i = 0; i < state.children.size(); ++i)
+    RecursivelyGenerateHistoryItem(state.children[i], node->AddChild());
 }
 
 }  // namespace
 
-PageState HistoryItemToPageState(const WebHistoryItem& item) {
+PageState HistoryEntryToPageState(HistoryEntry* entry) {
   ExplodedPageState state;
-  ToNullableString16Vector(item.getReferencedFilePaths(),
+  ToNullableString16Vector(entry->root().getReferencedFilePaths(),
                            &state.referenced_files);
 
-  if (!RecursivelyGenerateFrameState(item, &state.top))
-    return PageState();
+  RecursivelyGenerateFrameState(entry->root_history_node(), &state.top);
 
   std::string encoded_data;
   if (!EncodePageState(state, &encoded_data))
@@ -176,17 +173,28 @@
   return PageState::CreateFromEncodedData(encoded_data);
 }
 
-WebHistoryItem PageStateToHistoryItem(const PageState& page_state) {
+PageState SingleHistoryItemToPageState(const WebHistoryItem& item) {
+  ExplodedPageState state;
+  ToNullableString16Vector(item.getReferencedFilePaths(),
+                           &state.referenced_files);
+  GenerateFrameStateFromItem(item, &state.top);
+
+  std::string encoded_data;
+  if (!EncodePageState(state, &encoded_data))
+    return PageState();
+
+  return PageState::CreateFromEncodedData(encoded_data);
+}
+
+HistoryEntry* PageStateToHistoryEntry(const PageState& page_state) {
   ExplodedPageState state;
   if (!DecodePageState(page_state.ToEncodedData(), &state))
-    return WebHistoryItem();
+    return NULL;
 
-  WebHistoryItem item;
-  item.initialize();
-  if (!RecursivelyGenerateHistoryItem(state.top, &item))
-    return WebHistoryItem();
+  HistoryEntry* entry = new HistoryEntry();
+  RecursivelyGenerateHistoryItem(state.top, entry->root_history_node());
 
-  return item;
+  return entry;
 }
 
 }  // namespace content
diff --git a/content/renderer/history_serialization.h b/content/renderer/history_serialization.h
index 6160fd3b3..03758ba 100644
--- a/content/renderer/history_serialization.h
+++ b/content/renderer/history_serialization.h
@@ -14,12 +14,13 @@
 }
 
 namespace content {
+class HistoryEntry;
 class PageState;
 
-CONTENT_EXPORT PageState HistoryItemToPageState(
+CONTENT_EXPORT PageState HistoryEntryToPageState(HistoryEntry* entry);
+CONTENT_EXPORT PageState SingleHistoryItemToPageState(
     const blink::WebHistoryItem& item);
-CONTENT_EXPORT blink::WebHistoryItem PageStateToHistoryItem(
-    const PageState& state);
+CONTENT_EXPORT HistoryEntry* PageStateToHistoryEntry(const PageState& state);
 
 }  // namespace content
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 2a9f733..449f5d25 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -701,9 +701,7 @@
     CHECK(frame) << "Invalid frame name passed: " << params.frame_to_navigate;
   }
 
-  WebHistoryItem item =
-      render_view_->history_controller()->GetCurrentItemForExport();
-  if (is_reload && item.isNull()) {
+  if (is_reload && !render_view_->history_controller()->GetCurrentEntry()) {
     // We cannot reload if we do not have any history state.  This happens, for
     // example, when recovering from a crash.
     is_reload = false;
@@ -731,12 +729,12 @@
   } else if (params.page_state.IsValid()) {
     // We must know the page ID of the page we are navigating back to.
     DCHECK_NE(params.page_id, -1);
-    WebHistoryItem item = PageStateToHistoryItem(params.page_state);
-    if (!item.isNull()) {
+    HistoryEntry* entry = PageStateToHistoryEntry(params.page_state);
+    if (entry) {
       // Ensure we didn't save the swapped out URL in UpdateState, since the
       // browser should never be telling us to navigate to swappedout://.
-      CHECK(item.urlString() != WebString::fromUTF8(kSwappedOutURL));
-      render_view_->history_controller()->GoToItem(item, cache_policy);
+      CHECK(entry->root().urlString() != WebString::fromUTF8(kSwappedOutURL));
+      render_view_->history_controller()->GoToEntry(entry, cache_policy);
     }
   } else if (!params.base_url_for_data_url.is_empty()) {
     // A loadData request with a specified base URL.
@@ -2742,13 +2740,11 @@
 
   // Make navigation state a part of the DidCommitProvisionalLoad message so
   // that commited entry has it at all times.
-  WebHistoryItem item =
-      render_view_->history_controller()->GetCurrentItemForExport();
-  if (item.isNull()) {
-    item.initialize();
-    item.setURLString(request.url().spec().utf16());
-  }
-  params.page_state = HistoryItemToPageState(item);
+  HistoryEntry* entry = render_view_->history_controller()->GetCurrentEntry();
+  if (entry)
+    params.page_state = HistoryEntryToPageState(entry);
+  else
+    params.page_state = PageState::CreateFromURL(request.url());
 
   if (!frame->parent()) {
     // Top-level navigation.
@@ -2813,7 +2809,7 @@
     base::string16 method = request.httpMethod();
     if (EqualsASCII(method, "POST")) {
       params.is_post = true;
-      params.post_id = ExtractPostId(item);
+      params.post_id = ExtractPostId(entry->root());
     }
 
     // Send the user agent override back.
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 1f8ce675..0744475 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -333,8 +333,8 @@
 
   // Check post data sent to browser matches
   EXPECT_TRUE(host_nav_params.a.page_state.IsValid());
-  const blink::WebHistoryItem item = PageStateToHistoryItem(
-      host_nav_params.a.page_state);
+  const blink::WebHistoryItem item =
+      PageStateToHistoryEntry(host_nav_params.a.page_state)->root();
   blink::WebHTTPBody body = item.httpBody();
   blink::WebHTTPBody::Element element;
   bool successful = body.elementAt(0, element);
@@ -1792,8 +1792,8 @@
 
 TEST_F(RenderViewImplTest, TestBackForward) {
   LoadHTML("<div id=pagename>Page A</div>");
-  blink::WebHistoryItem page_a_item =
-      view()->history_controller()->GetCurrentItemForExport();
+  PageState page_a_state =
+      HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
   int was_page_a = -1;
   base::string16 check_page_a =
       base::ASCIIToUTF16(
@@ -1817,26 +1817,29 @@
   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c));
   EXPECT_EQ(1, was_page_b);
 
-  blink::WebHistoryItem forward_item =
-      view()->history_controller()->GetCurrentItemForExport();
-  GoBack(view()->history_controller()->GetPreviousItemForExport());
+  PageState forward_state =
+      HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
+  GoBack(HistoryEntryToPageState(
+      view()->history_controller()->GetPreviousEntry()));
   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
   EXPECT_EQ(1, was_page_b);
 
-  GoForward(forward_item);
+  GoForward(forward_state);
   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c));
   EXPECT_EQ(1, was_page_c);
 
-  GoBack(view()->history_controller()->GetPreviousItemForExport());
+  GoBack(HistoryEntryToPageState(
+      view()->history_controller()->GetPreviousEntry()));
   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
   EXPECT_EQ(1, was_page_b);
 
-  forward_item = view()->history_controller()->GetCurrentItemForExport();
-  GoBack(page_a_item);
+  forward_state =
+      HistoryEntryToPageState(view()->history_controller()->GetCurrentEntry());
+  GoBack(page_a_state);
   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
   EXPECT_EQ(1, was_page_a);
 
-  GoForward(forward_item);
+  GoForward(forward_state);
   EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
   EXPECT_EQ(1, was_page_b);
 }
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index d2745eef..1ea27e9 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1385,21 +1385,19 @@
   // there is no past session history to record.
   if (page_id_ == -1)
     return;
-
-  WebHistoryItem item = history_controller_->GetPreviousItemForExport();
-  SendUpdateState(item);
+  SendUpdateState(history_controller_->GetPreviousEntry());
 }
 
-void RenderViewImpl::SendUpdateState(const WebHistoryItem& item) {
-  if (item.isNull())
+void RenderViewImpl::SendUpdateState(HistoryEntry* entry) {
+  if (!entry)
     return;
 
   // Don't send state updates for kSwappedOutURL.
-  if (item.urlString() == WebString::fromUTF8(kSwappedOutURL))
+  if (entry->root().urlString() == WebString::fromUTF8(kSwappedOutURL))
     return;
 
   Send(new ViewHostMsg_UpdateState(
-      routing_id_, page_id_, HistoryItemToPageState(item)));
+      routing_id_, page_id_, HistoryEntryToPageState(entry)));
 }
 
 bool RenderViewImpl::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) {
@@ -2678,9 +2676,7 @@
 void RenderViewImpl::SyncNavigationState() {
   if (!webview())
     return;
-
-  WebHistoryItem item = history_controller_->GetCurrentItemForExport();
-  SendUpdateState(item);
+  SendUpdateState(history_controller_->GetCurrentEntry());
 }
 
 GURL RenderViewImpl::GetLoadingUrl(blink::WebFrame* frame) const {
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 676f12c..d8c7d8f 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -140,6 +140,7 @@
 class FaviconHelper;
 class GeolocationDispatcher;
 class HistoryController;
+class HistoryEntry;
 class ImageResourceFetcher;
 class InputTagSpeechDispatcher;
 class LoadProgressTracker;
@@ -709,7 +710,7 @@
   void UpdateTitle(blink::WebFrame* frame, const base::string16& title,
                    blink::WebTextDirection title_direction);
   void UpdateSessionHistory(blink::WebFrame* frame);
-  void SendUpdateState(const blink::WebHistoryItem& item);
+  void SendUpdateState(HistoryEntry* entry);
 
   // Update current main frame's encoding and send it to browser window.
   // Since we want to let users see the right encoding info from menu
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index 387d75a..eb218ab 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -9,6 +9,7 @@
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/common/gpu/image_transport_surface.h"
 #include "content/public/common/page_state.h"
+#include "content/renderer/history_entry.h"
 #include "content/renderer/history_serialization.h"
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_view_impl.h"
@@ -169,21 +170,22 @@
   base::char16 operator()(base::char16 c) { return tolower(c); }
 };
 
-// Returns True if item1 < item2.
-bool HistoryItemCompareLess(const blink::WebHistoryItem& item1,
-                            const blink::WebHistoryItem& item2) {
-  base::string16 target1 = item1.target();
-  base::string16 target2 = item2.target();
+// Returns True if node1 < node2.
+bool HistoryEntryCompareLess(HistoryEntry::HistoryNode* node1,
+                             HistoryEntry::HistoryNode* node2) {
+  base::string16 target1 = node1->item().target();
+  base::string16 target2 = node2->item().target();
   std::transform(target1.begin(), target1.end(), target1.begin(), ToLower());
   std::transform(target2.begin(), target2.end(), target2.begin(), ToLower());
   return target1 < target2;
 }
 
-std::string DumpHistoryItem(const blink::WebHistoryItem& item,
+std::string DumpHistoryItem(HistoryEntry::HistoryNode* node,
                             int indent,
                             bool is_current_index) {
   std::string result;
 
+  const blink::WebHistoryItem& item = node->item();
   if (is_current_index) {
     result.append("curr->");
     result.append(indent - 6, ' '); // 6 == "curr->".length()
@@ -201,19 +203,11 @@
   }
   result.append("\n");
 
-  const blink::WebVector<blink::WebHistoryItem>& children = item.children();
-  if (!children.isEmpty()) {
-    // Must sort to eliminate arbitrary result ordering which defeats
-    // reproducible testing.
-    // FIXME: WebVector should probably just be a std::vector!!
-    std::vector<blink::WebHistoryItem> sortedChildren;
+  std::vector<HistoryEntry::HistoryNode*> children = node->children();
+  if (!children.empty()) {
+    std::sort(children.begin(), children.end(), HistoryEntryCompareLess);
     for (size_t i = 0; i < children.size(); ++i)
-      sortedChildren.push_back(children[i]);
-    std::sort(sortedChildren.begin(),
-              sortedChildren.end(),
-              HistoryItemCompareLess);
-    for (size_t i = 0; i < sortedChildren.size(); ++i)
-      result += DumpHistoryItem(sortedChildren[i], indent + 4, false);
+      result += DumpHistoryItem(children[i], indent + 4, false);
   }
 
   return result;
@@ -224,8 +218,12 @@
   std::string result;
   result.append("\n============== Back Forward List ==============\n");
   for (size_t index = 0; index < page_state.size(); ++index) {
-    result.append(DumpHistoryItem(
-        PageStateToHistoryItem(page_state[index]), 8, index == current_index));
+    scoped_ptr<HistoryEntry> entry(
+        PageStateToHistoryEntry(page_state[index]));
+    result.append(
+        DumpHistoryItem(entry->root_history_node(),
+                        8,
+                        index == current_index));
   }
   result.append("===============================================\n");
   return result;