summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjaphet@chromium.org <japhet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-15 02:05:55 +0000
committerjaphet@chromium.org <japhet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-15 02:05:55 +0000
commitd4734984813f030f1d088b359f4baa07000931c3 (patch)
tree749d909af872f1b23a3dff007dfd5e42dd3e7d34
parent15f3aecedf30bf98d55933f0adb8190ae02073c9 (diff)
downloadchromium_src-d4734984813f030f1d088b359f4baa07000931c3.zip
chromium_src-d4734984813f030f1d088b359f4baa07000931c3.tar.gz
chromium_src-d4734984813f030f1d088b359f4baa07000931c3.tar.bz2
Move HistoryController to content/renderer/
Currently, all history state updates are initiated from content/renderer, but are implemented in blink's Source/core/page. This moves the HistoryController class to content/renderer/, hangs it off of RenderViewImpl, and updates it to use chromium types. I tried to change as little as possible in the logic of the code compared to src.chromium.org/viewvc/blink/trunk/Source/core/page/HistoryController.cpp. This is step 4 of 5 in http://crbug.com/357327 BUG=357327 Review URL: https://codereview.chromium.org/229283002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@263767 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--android_webview/tools/third_party_files_whitelist.txt6
-rw-r--r--chrome/renderer/translate/translate_helper_browsertest.cc3
-rw-r--r--content/content_renderer.gypi2
-rw-r--r--content/public/test/render_view_test.cc10
-rw-r--r--content/public/test/render_view_test.h4
-rw-r--r--content/renderer/history_controller.cc375
-rw-r--r--content/renderer/history_controller.h206
-rw-r--r--content/renderer/render_frame_impl.cc49
-rw-r--r--content/renderer/render_frame_impl.h6
-rw-r--r--content/renderer/render_view_browsertest.cc88
-rw-r--r--content/renderer/render_view_impl.cc8
-rw-r--r--content/renderer/render_view_impl.h7
-rw-r--r--content/shell/renderer/test_runner/WebFrameTestProxy.h6
-rw-r--r--content/shell/renderer/test_runner/WebTestProxy.cpp2
-rw-r--r--content/shell/renderer/test_runner/WebTestProxy.h3
15 files changed, 700 insertions, 75 deletions
diff --git a/android_webview/tools/third_party_files_whitelist.txt b/android_webview/tools/third_party_files_whitelist.txt
index 2f7dd29..d07e4da 100644
--- a/android_webview/tools/third_party_files_whitelist.txt
+++ b/android_webview/tools/third_party_files_whitelist.txt
@@ -66,6 +66,12 @@ content/browser/renderer_host/render_widget_host_view_mac.mm
# Copyright The Chromium Authors and Google Inc; BSD license. Not used on
# Android.
content/browser/renderer_host/web_input_event_aurax11.cc
+# Copyright Apple Inc and Torch Mobile Inc; BSD license. Moved from
+# third_party/WebKit/.
+content/renderer/history_controller.h
+# Copyright Apple Inc, Nokia Corporation and Torch Mobile Inc; BSD license.
+# Moved from third_party/WebKit/.
+content/renderer/history_controller.cc
# Copyright Google Inc, no license. Not used on Android.
google_update/google_update_idl.idl
# Native client not used in Android. Contains the word "Copyright"
diff --git a/chrome/renderer/translate/translate_helper_browsertest.cc b/chrome/renderer/translate/translate_helper_browsertest.cc
index e6dbda7..61c5756 100644
--- a/chrome/renderer/translate/translate_helper_browsertest.cc
+++ b/chrome/renderer/translate/translate_helper_browsertest.cc
@@ -10,7 +10,6 @@
#include "content/public/renderer/render_view.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebHistoryItem.h"
using testing::AtLeast;
using testing::Return;
@@ -470,7 +469,7 @@ TEST_F(ChromeRenderViewTest, BackToTranslatablePage) {
EXPECT_EQ("fr", params.a.adopted_language);
render_thread_->sink().ClearMessages();
- GoBack(GetMainFrame()->previousHistoryItem());
+ GoBackToPrevious();
message = render_thread_->sink().GetUniqueMessageMatching(
ChromeViewHostMsg_TranslateLanguageDetermined::ID);
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 7aef2b4..1ba054e 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -162,6 +162,8 @@
'renderer/gpu/render_widget_compositor.h',
'renderer/gpu/stream_texture_host_android.cc',
'renderer/gpu/stream_texture_host_android.h',
+ 'renderer/history_controller.cc',
+ 'renderer/history_controller.h',
'renderer/idle_user_detector.cc',
'renderer/idle_user_detector.h',
'renderer/image_loading_helper.cc',
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 28401a64..d507dff 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -15,6 +15,7 @@
#include "content/public/common/renderer_preferences.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/history_item_serialization.h"
+#include "content/renderer/history_controller.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/renderer_main_platform_delegate.h"
@@ -132,6 +133,11 @@ void RenderViewTest::GoForward(const blink::WebHistoryItem& item) {
GoToOffset(1, item);
}
+void RenderViewTest::GoBackToPrevious() {
+ RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
+ GoBack(impl->history_controller()->GetPreviousItemForExport());
+}
+
void RenderViewTest::SetUp() {
content_client_.reset(CreateContentClient());
content_browser_client_.reset(CreateContentBrowserClient());
@@ -360,9 +366,11 @@ bool RenderViewTest::OnMessageReceived(const IPC::Message& msg) {
void RenderViewTest::DidNavigateWithinPage(blink::WebLocalFrame* frame,
bool is_new_navigation) {
RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
+ blink::WebHistoryItem item;
+ item.initialize();
impl->main_render_frame()->didNavigateWithinPage(
frame,
- blink::WebHistoryItem(),
+ item,
is_new_navigation ? blink::WebStandardCommit
: blink::WebHistoryInertCommit);
}
diff --git a/content/public/test/render_view_test.h b/content/public/test/render_view_test.h
index f75bef5..8582bb6 100644
--- a/content/public/test/render_view_test.h
+++ b/content/public/test/render_view_test.h
@@ -82,6 +82,10 @@ class RenderViewTest : public testing::Test {
void GoBack(const blink::WebHistoryItem& item);
void GoForward(const blink::WebHistoryItem& item);
+ // Navigates the main frame back to whatever is considered the previous
+ // history entry internally.
+ void GoBackToPrevious();
+
// Sends one native key event over IPC.
void SendNativeKeyEvent(const NativeWebKeyboardEvent& key_event);
diff --git a/content/renderer/history_controller.cc b/content/renderer/history_controller.cc
new file mode 100644
index 0000000..23e74de
--- /dev/null
+++ b/content/renderer/history_controller.cc
@@ -0,0 +1,375 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
+ * (http://www.torchmobile.com/)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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 {
+
+const int kInvalidFrameRoutingID = -1;
+
+HistoryNode* HistoryNode::AddChild(const WebHistoryItem& item,
+ int64_t frame_id) {
+ children_->push_back(new HistoryNode(entry_, item, frame_id));
+ return children_->back();
+}
+
+HistoryNode* HistoryNode::CloneAndReplace(HistoryEntry* new_entry,
+ const WebHistoryItem& new_item,
+ bool clone_children_of_target,
+ RenderFrameImpl* target_frame,
+ RenderFrameImpl* current_frame) {
+ bool is_target_frame = target_frame == current_frame;
+ const WebHistoryItem& item_for_create = is_target_frame ? new_item : item_;
+ HistoryNode* new_history_node = new HistoryNode(
+ new_entry, item_for_create, current_frame->GetRoutingID());
+
+ if (is_target_frame && clone_children_of_target && !item_.isNull()) {
+ new_history_node->item().setDocumentSequenceNumber(
+ item_.documentSequenceNumber());
+ }
+
+ if (clone_children_of_target || !is_target_frame) {
+ for (WebFrame* child = current_frame->GetWebFrame()->firstChild(); child;
+ child = child->nextSibling()) {
+ RenderFrameImpl* child_render_frame =
+ RenderFrameImpl::FromWebFrame(child);
+ HistoryNode* child_history_node =
+ entry_->GetHistoryNodeForFrame(child_render_frame);
+ if (!child_history_node)
+ continue;
+ HistoryNode* new_child_node =
+ child_history_node->CloneAndReplace(new_entry,
+ new_item,
+ clone_children_of_target,
+ target_frame,
+ child_render_frame);
+ new_history_node->children_->push_back(new_child_node);
+ }
+ }
+ return new_history_node;
+}
+
+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;
+ children_.reset(new ScopedVector<HistoryNode>);
+}
+
+HistoryNode::~HistoryNode() {
+}
+
+void HistoryNode::RemoveChildren() {
+ // TODO(japhet): This is inefficient. Figure out a cleaner way to ensure
+ // this HistoryNode isn't cached anywhere.
+ std::vector<uint64_t> frames_to_remove;
+ std::vector<std::string> unique_names_to_remove;
+ for (size_t i = 0; i < children().size(); i++) {
+ children().at(i)->RemoveChildren();
+
+ HistoryEntry::FramesToItems::iterator frames_end =
+ entry_->frames_to_items_.end();
+ HistoryEntry::UniqueNamesToItems::iterator unique_names_end =
+ entry_->unique_names_to_items_.end();
+ for (HistoryEntry::FramesToItems::iterator it =
+ entry_->frames_to_items_.begin();
+ it != frames_end;
+ ++it) {
+ if (it->second == children().at(i))
+ frames_to_remove.push_back(it->first);
+ }
+ for (HistoryEntry::UniqueNamesToItems::iterator it =
+ entry_->unique_names_to_items_.begin();
+ it != unique_names_end;
+ ++it) {
+ if (it->second == children().at(i))
+ unique_names_to_remove.push_back(it->first);
+ }
+ }
+ for (unsigned i = 0; i < frames_to_remove.size(); i++)
+ entry_->frames_to_items_.erase(frames_to_remove[i]);
+ for (unsigned i = 0; i < unique_names_to_remove.size(); i++)
+ entry_->unique_names_to_items_.erase(unique_names_to_remove[i]);
+ children_.reset(new ScopedVector<HistoryNode>);
+}
+
+HistoryEntry::HistoryEntry() {
+}
+
+HistoryEntry::~HistoryEntry() {
+}
+
+HistoryEntry::HistoryEntry(const WebHistoryItem& root, int64_t frame_id) {
+ root_.reset(new HistoryNode(this, root, frame_id));
+}
+
+HistoryEntry* HistoryEntry::CloneAndReplace(const WebHistoryItem& new_item,
+ bool clone_children_of_target,
+ RenderFrameImpl* target_frame,
+ RenderViewImpl* render_view) {
+ HistoryEntry* new_entry = new HistoryEntry();
+ new_entry->root_.reset(
+ root_->CloneAndReplace(new_entry,
+ new_item,
+ clone_children_of_target,
+ target_frame,
+ render_view->main_render_frame()));
+ return new_entry;
+}
+
+HistoryNode* HistoryEntry::GetHistoryNodeForFrame(RenderFrameImpl* frame) {
+ if (HistoryNode* history_node = frames_to_items_[frame->GetRoutingID()])
+ return history_node;
+ return unique_names_to_items_[frame->GetWebFrame()->uniqueName().utf8()];
+}
+
+WebHistoryItem HistoryEntry::GetItemForFrame(RenderFrameImpl* frame) {
+ if (HistoryNode* history_node = GetHistoryNodeForFrame(frame))
+ return history_node->item();
+ return WebHistoryItem();
+}
+
+HistoryController::HistoryController(RenderViewImpl* render_view)
+ : render_view_(render_view) {
+}
+
+HistoryController::~HistoryController() {
+}
+
+void HistoryController::GoToEntry(HistoryEntry* target_entry,
+ WebURLRequest::CachePolicy cache_policy) {
+ HistoryFrameLoadVector same_document_loads;
+ HistoryFrameLoadVector different_document_loads;
+
+ provisional_entry_.reset(target_entry);
+
+ WebFrame* main_frame = render_view_->main_render_frame()->GetWebFrame();
+ 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(
+ std::make_pair(main_frame, provisional_entry_->root()));
+ }
+
+ if (different_document_loads.empty()) {
+ previous_entry_.reset(current_entry_.release());
+ current_entry_.reset(provisional_entry_.release());
+ }
+
+ for (size_t i = 0; i < same_document_loads.size(); ++i) {
+ WebFrame* frame = same_document_loads[i].first;
+ if (!RenderFrameImpl::FromWebFrame(frame))
+ continue;
+ frame->loadHistoryItem(same_document_loads[i].second,
+ blink::WebHistorySameDocumentLoad,
+ cache_policy);
+ }
+ for (size_t i = 0; i < different_document_loads.size(); ++i) {
+ WebFrame* frame = different_document_loads[i].first;
+ if (!RenderFrameImpl::FromWebFrame(frame))
+ continue;
+ frame->loadHistoryItem(different_document_loads[i].second,
+ blink::WebHistoryDifferentDocumentLoad,
+ cache_policy);
+ }
+}
+
+void HistoryController::RecursiveGoToEntry(
+ WebFrame* frame,
+ HistoryFrameLoadVector& same_document_loads,
+ HistoryFrameLoadVector& different_document_loads) {
+ DCHECK(provisional_entry_);
+ DCHECK(current_entry_);
+ RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame);
+ const WebHistoryItem& new_item =
+ provisional_entry_->GetItemForFrame(render_frame);
+ const WebHistoryItem& old_item =
+ current_entry_->GetItemForFrame(render_frame);
+ if (new_item.isNull())
+ return;
+
+ if (old_item.isNull() ||
+ new_item.itemSequenceNumber() != old_item.itemSequenceNumber()) {
+ if (!old_item.isNull() &&
+ new_item.documentSequenceNumber() == old_item.documentSequenceNumber())
+ same_document_loads.push_back(std::make_pair(frame, new_item));
+ else
+ different_document_loads.push_back(std::make_pair(frame, new_item));
+ return;
+ }
+
+ for (WebFrame* child = frame->firstChild(); child;
+ child = child->nextSibling()) {
+ RecursiveGoToEntry(child, same_document_loads, different_document_loads);
+ }
+}
+
+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<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.
+ 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++) {
+ 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) {
+ DCHECK_NE(frame->GetWebFrame()->top(), frame->GetWebFrame());
+ if (!current_entry_)
+ return;
+ if (HistoryNode* existing_node =
+ current_entry_->GetHistoryNodeForFrame(frame)) {
+ existing_node->set_item(item);
+ return;
+ }
+ RenderFrameImpl* parent =
+ RenderFrameImpl::FromWebFrame(frame->GetWebFrame()->parent());
+ if (HistoryNode* parent_history_node =
+ current_entry_->GetHistoryNodeForFrame(parent)) {
+ parent_history_node->AddChild(item, frame->GetRoutingID());
+ }
+}
+
+void HistoryController::UpdateForCommit(RenderFrameImpl* frame,
+ const WebHistoryItem& item,
+ WebHistoryCommitType commit_type,
+ bool navigation_within_page) {
+ if (commit_type == blink::WebBackForwardCommit) {
+ if (!provisional_entry_)
+ return;
+ previous_entry_.reset(current_entry_.release());
+ current_entry_.reset(provisional_entry_.release());
+ } else if (commit_type == blink::WebStandardCommit) {
+ CreateNewBackForwardItem(frame, item, navigation_within_page);
+ } else if (commit_type == blink::WebInitialCommitInChildFrame) {
+ UpdateForInitialLoadInChildFrame(frame, item);
+ }
+}
+
+static WebHistoryItem ItemForExport(HistoryNode* history_node) {
+ DCHECK(history_node);
+ WebHistoryItem item = history_node->item();
+ item.setChildren(WebVector<WebHistoryItem>());
+ std::vector<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;
+}
+
+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());
+}
+
+WebHistoryItem HistoryController::GetItemForNewChildFrame(
+ RenderFrameImpl* frame) const {
+ if (!current_entry_)
+ return WebHistoryItem();
+ return current_entry_->GetItemForFrame(frame);
+}
+
+void HistoryController::RemoveChildrenForRedirect(RenderFrameImpl* frame) {
+ if (!provisional_entry_)
+ return;
+ if (HistoryNode* node = provisional_entry_->GetHistoryNodeForFrame(frame))
+ node->RemoveChildren();
+}
+
+void HistoryController::CreateNewBackForwardItem(
+ RenderFrameImpl* target_frame,
+ const WebHistoryItem& new_item,
+ bool clone_children_of_target) {
+ if (!current_entry_) {
+ current_entry_.reset(
+ new HistoryEntry(new_item, target_frame->GetRoutingID()));
+ } else {
+ previous_entry_.reset(current_entry_.release());
+ current_entry_.reset(previous_entry_->CloneAndReplace(
+ new_item, clone_children_of_target, target_frame, render_view_));
+ }
+}
+
+} // namespace content
diff --git a/content/renderer/history_controller.h b/content/renderer/history_controller.h
new file mode 100644
index 0000000..8b1ba9f
--- /dev/null
+++ b/content/renderer/history_controller.h
@@ -0,0 +1,206 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
+ * (http://www.torchmobile.com/)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CONTENT_RENDERER_HISTORY_CONTROLLER_H_
+#define CONTENT_RENDERER_HISTORY_CONTROLLER_H_
+
+#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/WebHistoryCommitType.h"
+#include "third_party/WebKit/public/web/WebHistoryItem.h"
+
+namespace blink {
+class WebFrame;
+}
+
+namespace content {
+class HistoryEntry;
+class RenderFrameImpl;
+class RenderViewImpl;
+
+// A guide to history state in the renderer:
+//
+// HistoryController: Owned by RenderView, is the entry point for interacting
+// with history. Handles most of the operations to modify history state,
+// navigate to an existing back/forward entry, etc.
+//
+// HistoryEntry: Represents a single entry in the back/forward list,
+// encapsulating all frames in the page it represents. It provides access
+// to each frame's state via lookups by frame id or frame name.
+// HistoryNode: Represents a single frame in a HistoryEntry. Owned by a
+// HistoryEntry. HistoryNodes form a tree that mirrors the frame tree in
+// the corresponding page.
+// HistoryNodes represent the structure of the page, but don't hold any
+// per-frame state except a list of child frames.
+// WebHistoryItem (lives in blink): The state for a given frame. Can persist
+// across navigations. WebHistoryItem is reference counted, and each
+// HistoryNode holds a reference to its single corresponding
+// WebHistoryItem. Can be referenced by multiple HistoryNodes and can
+// therefore exist in multiple HistoryEntry instances.
+//
+// Suppose we have the following page, foo.com, which embeds foo.com/a in an
+// iframe:
+//
+// HistoryEntry 0:
+// HistoryNode 0_0 (WebHistoryItem A (url: foo.com))
+// HistoryNode 0_1: (WebHistoryItem B (url: foo.com/a))
+//
+// Now we navigate the top frame to bar.com, which embeds bar.com/b and
+// bar.com/c in iframes, and bar.com/b in turn embeds bar.com/d. We will
+// create a new HistoryEntry with a tree containing 4 new HistoryNodes. The
+// state will be:
+//
+// HistoryEntry 1:
+// HistoryNode 1_0 (WebHistoryItem C (url: bar.com))
+// HistoryNode 1_1: (WebHistoryItem D (url: bar.com/b))
+// HistoryNode 1_3: (WebHistoryItem F (url: bar.com/d))
+// HistoryNode 1_2: (WebHistoryItem E (url: bar.com/c))
+//
+//
+// Finally, we navigate the first subframe from bar.com/b to bar.com/e, which
+// embeds bar.com/f. We will create a new HistoryEntry and new HistoryNode for
+// each frame. Any frame that navigates (bar.com/e and its child, bar.com/f)
+// will receive a new WebHistoryItem. However, 2 frames were not navigated
+// (bar.com and bar.com/c), so those two frames will reuse the existing
+// WebHistoryItem:
+//
+// HistoryEntry 2:
+// HistoryNode 2_0 (WebHistoryItem C (url: bar.com)) *REUSED*
+// HistoryNode 2_1: (WebHistoryItem G (url: bar.com/e))
+// HistoryNode 2_3: (WebHistoryItem H (url: bar.com/f))
+// HistoryNode 2_2: (WebHistoryItem E (url: bar.com/c)) *REUSED*
+//
+
+class HistoryNode {
+ public:
+ HistoryNode(HistoryEntry* entry,
+ const blink::WebHistoryItem& item,
+ int64_t frame_id);
+ ~HistoryNode();
+
+ HistoryNode* AddChild(const blink::WebHistoryItem& item, int64_t frame_id);
+ 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; }
+ std::vector<HistoryNode*>& children() const { return children_->get(); }
+ void RemoveChildren();
+
+ private:
+ HistoryEntry* entry_;
+ scoped_ptr<ScopedVector<HistoryNode> > children_;
+ blink::WebHistoryItem item_;
+};
+
+class HistoryEntry {
+ public:
+ HistoryEntry(const blink::WebHistoryItem& root, int64_t frame_id);
+ ~HistoryEntry();
+
+ HistoryEntry* CloneAndReplace(const blink::WebHistoryItem& newItem,
+ bool clone_children_of_target,
+ RenderFrameImpl* target_frame,
+ RenderViewImpl* render_view);
+
+ HistoryNode* GetHistoryNodeForFrame(RenderFrameImpl* frame);
+ blink::WebHistoryItem GetItemForFrame(RenderFrameImpl* frame);
+ const blink::WebHistoryItem& root() const { return root_->item(); }
+ HistoryNode* root_history_node() const { return root_.get(); }
+
+ private:
+ friend class HistoryNode;
+
+ HistoryEntry();
+
+ scoped_ptr<HistoryNode> root_;
+
+ typedef base::hash_map<uint64_t, HistoryNode*> FramesToItems;
+ FramesToItems frames_to_items_;
+
+ typedef base::hash_map<std::string, HistoryNode*> UniqueNamesToItems;
+ UniqueNamesToItems unique_names_to_items_;
+};
+
+class CONTENT_EXPORT HistoryController {
+ public:
+ explicit HistoryController(RenderViewImpl* render_view);
+ ~HistoryController();
+
+ void GoToItem(const blink::WebHistoryItem& item,
+ 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();
+ 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,
+ HistoryFrameLoadVector& sameDocumentLoads,
+ HistoryFrameLoadVector& differentDocumentLoads);
+
+ void UpdateForInitialLoadInChildFrame(RenderFrameImpl* frame,
+ const blink::WebHistoryItem& item);
+ void CreateNewBackForwardItem(RenderFrameImpl* frame,
+ const blink::WebHistoryItem& item,
+ bool clone_children_of_target);
+
+ RenderViewImpl* render_view_;
+
+ scoped_ptr<HistoryEntry> current_entry_;
+ scoped_ptr<HistoryEntry> previous_entry_;
+ scoped_ptr<HistoryEntry> provisional_entry_;
+
+ DISALLOW_COPY_AND_ASSIGN(HistoryController);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_HISTORY_CONTROLLER_H_
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index aeb6204..9286bf4 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -50,6 +50,7 @@
#include "content/renderer/child_frame_compositing_helper.h"
#include "content/renderer/context_menu_params_builder.h"
#include "content/renderer/dom_automation_controller.h"
+#include "content/renderer/history_controller.h"
#include "content/renderer/image_loading_helper.h"
#include "content/renderer/ime_event_guard.h"
#include "content/renderer/internal_document_state_data.h"
@@ -675,7 +676,9 @@ void RenderFrameImpl::OnNavigate(const FrameMsg_Navigate_Params& params) {
CHECK(frame) << "Invalid frame name passed: " << params.frame_to_navigate;
}
- if (is_reload && frame->currentHistoryItem().isNull()) {
+ WebHistoryItem item =
+ render_view_->history_controller()->GetCurrentItemForExport();
+ if (is_reload && item.isNull()) {
// We cannot reload if we do not have any history state. This happens, for
// example, when recovering from a crash.
is_reload = false;
@@ -708,7 +711,7 @@ void RenderFrameImpl::OnNavigate(const FrameMsg_Navigate_Params& params) {
// 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));
- frame->loadHistoryItem(item, cache_policy);
+ render_view_->history_controller()->GoToItem(item, cache_policy);
}
} else if (!params.base_url_for_data_url.is_empty()) {
// A loadData request with a specified base URL.
@@ -1520,7 +1523,8 @@ blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
blink::WebHistoryItem RenderFrameImpl::historyItemForNewChildFrame(
blink::WebFrame* frame) {
- return render_view_->webview()->itemForNewChildFrame(frame);
+ DCHECK(!frame_ || frame_ == frame);
+ return render_view_->history_controller()->GetItemForNewChildFrame(this);
}
void RenderFrameImpl::willSendSubmitEvent(blink::WebLocalFrame* frame,
@@ -1633,7 +1637,7 @@ void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame) {
void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
blink::WebLocalFrame* frame) {
DCHECK(!frame_ || frame_ == frame);
- render_view_->webview()->removeChildrenForRedirect(frame);
+ render_view_->history_controller()->RemoveChildrenForRedirect(this);
if (frame->parent())
return;
// Received a redirect on the main frame.
@@ -1758,20 +1762,13 @@ void RenderFrameImpl::didCommitProvisionalLoad(
blink::WebLocalFrame* frame,
const blink::WebHistoryItem& item,
blink::WebHistoryCommitType commit_type) {
- DocumentState* document_state =
- DocumentState::FromDataSource(frame->dataSource());
- render_view_->webview()->updateForCommit(frame, item, commit_type,
- document_state->navigation_state()->was_within_same_page());
-
- didCommitProvisionalLoad(frame, commit_type == blink::WebStandardCommit);
-}
-
-void RenderFrameImpl::didCommitProvisionalLoad(blink::WebLocalFrame* frame,
- bool is_new_navigation) {
DCHECK(!frame_ || frame_ == frame);
DocumentState* document_state =
DocumentState::FromDataSource(frame->dataSource());
NavigationState* navigation_state = document_state->navigation_state();
+ render_view_->history_controller()->UpdateForCommit(this, item, commit_type,
+ navigation_state->was_within_same_page());
+
InternalDocumentStateData* internal_data =
InternalDocumentStateData::FromDocumentState(document_state);
@@ -1784,6 +1781,7 @@ void RenderFrameImpl::didCommitProvisionalLoad(blink::WebLocalFrame* frame,
}
internal_data->set_use_error_page(false);
+ bool is_new_navigation = commit_type == blink::WebStandardCommit;
if (is_new_navigation) {
// When we perform a new navigation, we need to update the last committed
// session history entry with state for the page we are leaving.
@@ -2007,26 +2005,6 @@ void RenderFrameImpl::didNavigateWithinPage(blink::WebLocalFrame* frame,
didCommitProvisionalLoad(frame, item, commit_type);
}
-void RenderFrameImpl::didNavigateWithinPage(blink::WebLocalFrame* frame,
- bool is_new_navigation) {
- DCHECK(!frame_ || frame_ == frame);
- // If this was a reference fragment navigation that we initiated, then we
- // could end up having a non-null pending navigation params. We just need to
- // update the ExtraData on the datasource so that others who read the
- // ExtraData will get the new NavigationState. Similarly, if we did not
- // initiate this navigation, then we need to take care to reset any pre-
- // existing navigation state to a content-initiated navigation state.
- // DidCreateDataSource conveniently takes care of this for us.
- didCreateDataSource(frame, frame->dataSource());
-
- DocumentState* document_state =
- DocumentState::FromDataSource(frame->dataSource());
- NavigationState* new_state = document_state->navigation_state();
- new_state->set_was_within_same_page(true);
-
- didCommitProvisionalLoad(frame, is_new_navigation);
-}
-
void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebLocalFrame* frame) {
DCHECK(!frame_ || frame_ == frame);
// TODO(nasko): Move implementation here. Needed methods:
@@ -2705,7 +2683,8 @@ void RenderFrameImpl::UpdateURL(blink::WebFrame* frame) {
// Make navigation state a part of the DidCommitProvisionalLoad message so
// that commited entry has it at all times.
- WebHistoryItem item = frame->currentHistoryItem();
+ WebHistoryItem item =
+ render_view_->history_controller()->GetCurrentItemForExport();
if (item.isNull()) {
item.initialize();
item.setURLString(request.url().spec().utf16());
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 4465069..50ad7bd 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -266,9 +266,6 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebLocalFrame* frame,
const blink::WebHistoryItem& item,
blink::WebHistoryCommitType commit_type);
- // DEPRECATED
- virtual void didCommitProvisionalLoad(blink::WebLocalFrame* frame,
- bool is_new_navigation);
virtual void didClearWindowObject(blink::WebLocalFrame* frame, int world_id);
virtual void didCreateDocumentElement(blink::WebLocalFrame* frame);
virtual void didReceiveTitle(blink::WebLocalFrame* frame,
@@ -284,9 +281,6 @@ class CONTENT_EXPORT RenderFrameImpl
virtual void didNavigateWithinPage(blink::WebLocalFrame* frame,
const blink::WebHistoryItem& item,
blink::WebHistoryCommitType commit_type);
- // DEPRECATED
- virtual void didNavigateWithinPage(blink::WebLocalFrame* frame,
- bool is_new_navigation);
virtual void didUpdateCurrentHistoryItem(blink::WebLocalFrame* frame);
virtual blink::WebNotificationPresenter* notificationPresenter();
virtual void didChangeSelection(bool is_empty_selection);
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 856194e..147382d 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -31,6 +31,7 @@
#include "content/renderer/accessibility/renderer_accessibility.h"
#include "content/renderer/accessibility/renderer_accessibility_complete.h"
#include "content/renderer/accessibility/renderer_accessibility_focus_only.h"
+#include "content/renderer/history_controller.h"
#include "content/renderer/render_view_impl.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
@@ -1585,8 +1586,13 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
EXPECT_EQ(-1, view()->history_page_ids_[1]);
ClearHistory();
+ blink::WebHistoryItem item;
+ item.initialize();
+
// No history to merge and a committed page to be kept.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
view()->OnSetHistoryLengthAndPrune(0, expected_page_id);
EXPECT_EQ(1, view()->history_list_length_);
@@ -1595,7 +1601,9 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
ClearHistory();
// No history to merge and a committed page to be pruned.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
view()->OnSetHistoryLengthAndPrune(0, expected_page_id + 1);
EXPECT_EQ(0, view()->history_list_length_);
@@ -1603,7 +1611,9 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
ClearHistory();
// No history to merge and a committed page that the browser was unaware of.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
view()->OnSetHistoryLengthAndPrune(0, -1);
EXPECT_EQ(1, view()->history_list_length_);
@@ -1612,7 +1622,9 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
ClearHistory();
// History to merge and a committed page to be kept.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
view()->OnSetHistoryLengthAndPrune(2, expected_page_id);
EXPECT_EQ(3, view()->history_list_length_);
@@ -1623,7 +1635,9 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
ClearHistory();
// History to merge and a committed page to be pruned.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
view()->OnSetHistoryLengthAndPrune(2, expected_page_id + 1);
EXPECT_EQ(2, view()->history_list_length_);
@@ -1633,7 +1647,9 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
ClearHistory();
// History to merge and a committed page that the browser was unaware of.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
view()->OnSetHistoryLengthAndPrune(2, -1);
EXPECT_EQ(3, view()->history_list_length_);
@@ -1646,9 +1662,13 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
int expected_page_id_2 = -1;
// No history to merge and two committed pages, both to be kept.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id_2 = view()->page_id_;
EXPECT_GT(expected_page_id_2, expected_page_id);
view()->OnSetHistoryLengthAndPrune(0, expected_page_id);
@@ -1659,9 +1679,13 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
ClearHistory();
// No history to merge and two committed pages, and only the second is kept.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id_2 = view()->page_id_;
EXPECT_GT(expected_page_id_2, expected_page_id);
view()->OnSetHistoryLengthAndPrune(0, expected_page_id_2);
@@ -1672,9 +1696,13 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
// No history to merge and two committed pages, both of which the browser was
// unaware of.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id_2 = view()->page_id_;
EXPECT_GT(expected_page_id_2, expected_page_id);
view()->OnSetHistoryLengthAndPrune(0, -1);
@@ -1685,9 +1713,13 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
ClearHistory();
// History to merge and two committed pages, both to be kept.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id_2 = view()->page_id_;
EXPECT_GT(expected_page_id_2, expected_page_id);
view()->OnSetHistoryLengthAndPrune(2, expected_page_id);
@@ -1700,9 +1732,13 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
ClearHistory();
// History to merge and two committed pages, and only the second is kept.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id_2 = view()->page_id_;
EXPECT_GT(expected_page_id_2, expected_page_id);
view()->OnSetHistoryLengthAndPrune(2, expected_page_id_2);
@@ -1715,9 +1751,13 @@ TEST_F(RenderViewImplTest, SetHistoryLengthAndPrune) {
// History to merge and two committed pages, both of which the browser was
// unaware of.
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id = view()->page_id_;
- frame()->didCommitProvisionalLoad(GetMainFrame(), true);
+ frame()->didCommitProvisionalLoad(GetMainFrame(),
+ item,
+ blink::WebStandardCommit);
expected_page_id_2 = view()->page_id_;
EXPECT_GT(expected_page_id_2, expected_page_id);
view()->OnSetHistoryLengthAndPrune(2, -1);
@@ -1754,7 +1794,8 @@ TEST_F(RenderViewImplTest, ContextMenu) {
TEST_F(RenderViewImplTest, TestBackForward) {
LoadHTML("<div id=pagename>Page A</div>");
- blink::WebHistoryItem page_a_item = GetMainFrame()->currentHistoryItem();
+ blink::WebHistoryItem page_a_item =
+ view()->history_controller()->GetCurrentItemForExport();
int was_page_a = -1;
base::string16 check_page_a =
base::ASCIIToUTF16(
@@ -1778,8 +1819,9 @@ TEST_F(RenderViewImplTest, TestBackForward) {
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c));
EXPECT_EQ(1, was_page_b);
- blink::WebHistoryItem forward_item = GetMainFrame()->currentHistoryItem();
- GoBack(GetMainFrame()->previousHistoryItem());
+ blink::WebHistoryItem forward_item =
+ view()->history_controller()->GetCurrentItemForExport();
+ GoBack(view()->history_controller()->GetPreviousItemForExport());
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
EXPECT_EQ(1, was_page_b);
@@ -1787,11 +1829,11 @@ TEST_F(RenderViewImplTest, TestBackForward) {
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c));
EXPECT_EQ(1, was_page_c);
- GoBack(GetMainFrame()->previousHistoryItem());
+ GoBack(view()->history_controller()->GetPreviousItemForExport());
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
EXPECT_EQ(1, was_page_b);
- forward_item = GetMainFrame()->currentHistoryItem();
+ forward_item = view()->history_controller()->GetCurrentItemForExport();
GoBack(page_a_item);
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
EXPECT_EQ(1, was_page_a);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 4dfcd4f8..8cb6d43 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -80,6 +80,7 @@
#include "content/renderer/external_popup_menu.h"
#include "content/renderer/geolocation_dispatcher.h"
#include "content/renderer/gpu/render_widget_compositor.h"
+#include "content/renderer/history_controller.h"
#include "content/renderer/idle_user_detector.h"
#include "content/renderer/ime_event_guard.h"
#include "content/renderer/input/input_handler_manager.h"
@@ -815,6 +816,8 @@ void RenderViewImpl::Initialize(
}
mouse_lock_dispatcher_ = new RenderViewMouseLockDispatcher(this);
+ history_controller_.reset(new HistoryController(this));
+
// Create renderer_accessibility_ if needed.
OnSetAccessibilityMode(params->accessibility_mode);
@@ -1374,8 +1377,7 @@ void RenderViewImpl::UpdateSessionHistory(WebFrame* frame) {
if (page_id_ == -1)
return;
- const WebHistoryItem& item =
- webview()->mainFrame()->previousHistoryItem();
+ WebHistoryItem item = history_controller_->GetPreviousItemForExport();
SendUpdateState(item);
}
@@ -2809,7 +2811,7 @@ void RenderViewImpl::SyncNavigationState() {
if (!webview())
return;
- const WebHistoryItem& item = webview()->mainFrame()->currentHistoryItem();
+ WebHistoryItem item = history_controller_->GetCurrentItemForExport();
SendUpdateState(item);
}
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 6276d92..167a243 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -139,6 +139,7 @@ class DocumentState;
class ExternalPopupMenu;
class FaviconHelper;
class GeolocationDispatcher;
+class HistoryController;
class ImageResourceFetcher;
class InputTagSpeechDispatcher;
class LoadProgressTracker;
@@ -243,6 +244,10 @@ class CONTENT_EXPORT RenderViewImpl
return mouse_lock_dispatcher_;
}
+ HistoryController* history_controller() {
+ return history_controller_.get();
+ }
+
// Lazily initialize this view's BrowserPluginManager and return it.
BrowserPluginManager* GetBrowserPluginManager();
@@ -1206,6 +1211,8 @@ class CONTENT_EXPORT RenderViewImpl
// Mouse Lock dispatcher attached to this view.
MouseLockDispatcher* mouse_lock_dispatcher_;
+ scoped_ptr<HistoryController> history_controller_;
+
#if defined(OS_ANDROID)
// Android Specific ---------------------------------------------------------
diff --git a/content/shell/renderer/test_runner/WebFrameTestProxy.h b/content/shell/renderer/test_runner/WebFrameTestProxy.h
index 46927e5..00bf5de 100644
--- a/content/shell/renderer/test_runner/WebFrameTestProxy.h
+++ b/content/shell/renderer/test_runner/WebFrameTestProxy.h
@@ -65,10 +65,10 @@ public:
{
Base::didFailProvisionalLoad(frame, error);
}
- virtual void didCommitProvisionalLoad(blink::WebLocalFrame* frame, bool isNewNavigation)
+ virtual void didCommitProvisionalLoad(blink::WebLocalFrame* frame, const blink::WebHistoryItem& item, blink::WebHistoryCommitType commit_type)
{
- m_baseProxy->didCommitProvisionalLoad(frame, isNewNavigation);
- Base::didCommitProvisionalLoad(frame, isNewNavigation);
+ m_baseProxy->didCommitProvisionalLoad(frame, item, commit_type);
+ Base::didCommitProvisionalLoad(frame, item, commit_type);
}
virtual void didReceiveTitle(blink::WebLocalFrame* frame, const blink::WebString& title, blink::WebTextDirection direction)
{
diff --git a/content/shell/renderer/test_runner/WebTestProxy.cpp b/content/shell/renderer/test_runner/WebTestProxy.cpp
index 81c885a..9838f35 100644
--- a/content/shell/renderer/test_runner/WebTestProxy.cpp
+++ b/content/shell/renderer/test_runner/WebTestProxy.cpp
@@ -1060,7 +1060,7 @@ bool WebTestProxyBase::didFailProvisionalLoad(WebLocalFrame* frame, const WebURL
return !frame->provisionalDataSource();
}
-void WebTestProxyBase::didCommitProvisionalLoad(WebLocalFrame* frame, bool)
+void WebTestProxyBase::didCommitProvisionalLoad(WebLocalFrame* frame, const WebHistoryItem&, blink::WebHistoryCommitType)
{
if (m_testInterfaces->testRunner()->shouldDumpFrameLoadCallbacks()) {
printFrameDescription(m_delegate, frame);
diff --git a/content/shell/renderer/test_runner/WebTestProxy.h b/content/shell/renderer/test_runner/WebTestProxy.h
index a2197d5..4dea29f 100644
--- a/content/shell/renderer/test_runner/WebTestProxy.h
+++ b/content/shell/renderer/test_runner/WebTestProxy.h
@@ -20,6 +20,7 @@
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebHistoryCommitType.h"
#include "third_party/WebKit/public/web/WebIconURL.h"
// TODO(dcheng): Temporary. Delete once forward declarable.
#include "third_party/WebKit/public/web/WebLocalFrame.h"
@@ -169,7 +170,7 @@ protected:
void didStartProvisionalLoad(blink::WebLocalFrame*);
void didReceiveServerRedirectForProvisionalLoad(blink::WebLocalFrame*);
bool didFailProvisionalLoad(blink::WebLocalFrame*, const blink::WebURLError&);
- void didCommitProvisionalLoad(blink::WebLocalFrame*, bool isNewNavigation);
+ void didCommitProvisionalLoad(blink::WebLocalFrame*, const blink::WebHistoryItem&, blink::WebHistoryCommitType);
void didReceiveTitle(blink::WebLocalFrame*, const blink::WebString& title, blink::WebTextDirection);
void didChangeIcon(blink::WebLocalFrame*, blink::WebIconURL::Type);
void didFinishDocumentLoad(blink::WebLocalFrame*);