diff options
author | japhet@chromium.org <japhet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-15 02:05:55 +0000 |
---|---|---|
committer | japhet@chromium.org <japhet@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-15 02:05:55 +0000 |
commit | d4734984813f030f1d088b359f4baa07000931c3 (patch) | |
tree | 749d909af872f1b23a3dff007dfd5e42dd3e7d34 | |
parent | 15f3aecedf30bf98d55933f0adb8190ae02073c9 (diff) | |
download | chromium_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.txt | 6 | ||||
-rw-r--r-- | chrome/renderer/translate/translate_helper_browsertest.cc | 3 | ||||
-rw-r--r-- | content/content_renderer.gypi | 2 | ||||
-rw-r--r-- | content/public/test/render_view_test.cc | 10 | ||||
-rw-r--r-- | content/public/test/render_view_test.h | 4 | ||||
-rw-r--r-- | content/renderer/history_controller.cc | 375 | ||||
-rw-r--r-- | content/renderer/history_controller.h | 206 | ||||
-rw-r--r-- | content/renderer/render_frame_impl.cc | 49 | ||||
-rw-r--r-- | content/renderer/render_frame_impl.h | 6 | ||||
-rw-r--r-- | content/renderer/render_view_browsertest.cc | 88 | ||||
-rw-r--r-- | content/renderer/render_view_impl.cc | 8 | ||||
-rw-r--r-- | content/renderer/render_view_impl.h | 7 | ||||
-rw-r--r-- | content/shell/renderer/test_runner/WebFrameTestProxy.h | 6 | ||||
-rw-r--r-- | content/shell/renderer/test_runner/WebTestProxy.cpp | 2 | ||||
-rw-r--r-- | content/shell/renderer/test_runner/WebTestProxy.h | 3 |
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*); |