diff options
author | creis <creis@chromium.org> | 2015-06-19 17:46:30 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-20 00:48:17 +0000 |
commit | 4e2ecb71332584b846862653ac1b8ea2490b29b7 (patch) | |
tree | ddbd0ed22a53497a6053be63e9636f7824e50180 | |
parent | f679b9b026720f58d4e922e911a05506cfa38ee7 (diff) | |
download | chromium_src-4e2ecb71332584b846862653ac1b8ea2490b29b7.zip chromium_src-4e2ecb71332584b846862653ac1b8ea2490b29b7.tar.gz chromium_src-4e2ecb71332584b846862653ac1b8ea2490b29b7.tar.bz2 |
Support simple back/forward in out-of-process iframes.
This moves HistoryController::GoToEntry to the browser process for
--site-per-process mode, allowing NavigationController to identify
all the frames that need to be navigated directly.
So far, this only supports navigating a leaf node and not subframes
with subtrees of their own.
TBR=jam@chromium.org
BUG=236848
TEST=In --site-per-process, go back cross-site in a subframe.
Review URL: https://codereview.chromium.org/1181983009
Cr-Commit-Position: refs/heads/master@{#335404}
25 files changed, 494 insertions, 121 deletions
diff --git a/content/browser/frame_host/navigation_controller_delegate.h b/content/browser/frame_host/navigation_controller_delegate.h index 9789689..2532d25 100644 --- a/content/browser/frame_host/navigation_controller_delegate.h +++ b/content/browser/frame_host/navigation_controller_delegate.h @@ -51,8 +51,6 @@ class NavigationControllerDelegate { virtual void NotifyBeforeFormRepostWarningShow() = 0; virtual void NotifyNavigationEntryCommitted( const LoadCommittedDetails& load_details) = 0; - virtual bool NavigateToPendingEntry( - NavigationController::ReloadType reload_type) = 0; virtual void SetHistoryOffsetAndLength(int history_offset, int history_length) = 0; virtual void CopyMaxPageIDsFrom(WebContents* web_contents) = 0; diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 182e54a..739ca2b 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc @@ -2,6 +2,37 @@ // 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/browser/frame_host/navigation_controller_impl.h" #include "base/bind.h" @@ -24,6 +55,7 @@ #include "content/browser/frame_host/interstitial_page_impl.h" #include "content/browser/frame_host/navigation_entry_impl.h" #include "content/browser/frame_host/navigation_entry_screenshot_manager.h" +#include "content/browser/frame_host/navigator.h" #include "content/browser/renderer_host/render_view_host_impl.h" // Temporary #include "content/browser/site_instance_impl.h" #include "content/common/frame_messages.h" @@ -695,23 +727,41 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) { break; } - NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( - CreateNavigationEntry( - params.url, - params.referrer, - params.transition_type, - params.is_renderer_initiated, - params.extra_headers, - browser_context_)); - if (!params.frame_name.empty()) { - // This is only used for navigating subframes in tests. - FrameTreeNode* named_frame = - delegate_->GetFrameTree()->FindByName(params.frame_name); - if (named_frame) - entry->set_frame_tree_node_id(named_frame->frame_tree_node_id()); - } - if (params.frame_tree_node_id != -1) - entry->set_frame_tree_node_id(params.frame_tree_node_id); + NavigationEntryImpl* entry = nullptr; + + // For subframes, create a pending entry with a corresponding frame entry. + int frame_tree_node_id = params.frame_tree_node_id; + if (frame_tree_node_id != -1 || !params.frame_name.empty()) { + FrameTreeNode* node = + params.frame_tree_node_id != -1 + ? delegate_->GetFrameTree()->FindByID(params.frame_tree_node_id) + : delegate_->GetFrameTree()->FindByName(params.frame_name); + if (node && !node->IsMainFrame()) { + DCHECK(GetLastCommittedEntry()); + + // Update the FTN ID to use below in case we found a named frame. + frame_tree_node_id = node->frame_tree_node_id(); + + // In --site-per-process, create an identical NavigationEntry with a + // new FrameNavigationEntry for the target subframe. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) { + entry = GetLastCommittedEntry()->Clone(); + entry->SetPageID(-1); + entry->AddOrUpdateFrameEntry(node, -1, -1, nullptr, params.url, + params.referrer, PageState()); + } + } + } + + // Otherwise, create a pending entry for the main frame. + if (!entry) { + entry = NavigationEntryImpl::FromNavigationEntry(CreateNavigationEntry( + params.url, params.referrer, params.transition_type, + params.is_renderer_initiated, params.extra_headers, browser_context_)); + } + // Set the FTN ID (only used in non-site-per-process, for tests). + entry->set_frame_tree_node_id(frame_tree_node_id); entry->set_source_site_instance( static_cast<SiteInstanceImpl*>(params.source_site_instance.get())); if (params.redirect_chain.size() > 0) @@ -808,8 +858,9 @@ bool NavigationControllerImpl::RendererDidNavigate( new_type == NAVIGATION_TYPE_AUTO_SUBFRAME; ignore_mismatch |= details->type == NAVIGATION_TYPE_NAV_IGNORE && new_type == NAVIGATION_TYPE_AUTO_SUBFRAME; - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kSitePerProcess)) { + bool is_site_per_process = base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess); + if (is_site_per_process) { // We know that the old classifier is wrong for OOPIFs, so use the new one // in --site-per-process mode. details->type = new_type; @@ -877,9 +928,14 @@ bool NavigationControllerImpl::RendererDidNavigate( NavigationEntryImpl* active_entry = GetLastCommittedEntry(); active_entry->SetTimestamp(timestamp); active_entry->SetHttpStatusCode(params.http_status_code); - // TODO(creis): Do this on the frame entry instead, once we have them for - // manual subframe navigations in --site-per-process. - active_entry->SetPageState(params.page_state); + if (is_site_per_process) { + // Update the frame-specific PageState. + FrameNavigationEntry* frame_entry = + active_entry->GetFrameEntry(rfh->frame_tree_node()); + frame_entry->set_page_state(params.page_state); + } else { + active_entry->SetPageState(params.page_state); + } active_entry->SetRedirectChain(params.redirects); // Use histogram to track memory impact of redirect chain because it's now @@ -1851,7 +1907,7 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) { // This call does not support re-entrancy. See http://crbug.com/347742. CHECK(!in_navigate_to_pending_entry_); in_navigate_to_pending_entry_ = true; - bool success = delegate_->NavigateToPendingEntry(reload_type); + bool success = NavigateToPendingEntryInternal(reload_type); in_navigate_to_pending_entry_ = false; if (!success) @@ -1867,6 +1923,97 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) { } } +bool NavigationControllerImpl::NavigateToPendingEntryInternal( + ReloadType reload_type) { + DCHECK(pending_entry_); + FrameTreeNode* root = delegate_->GetFrameTree()->root(); + + // In default Chrome, there are no subframe FrameNavigationEntries. Either + // navigate the main frame or use the main frame's FrameNavigationEntry to + // tell the indicated frame where to go. + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) { + FrameNavigationEntry* frame_entry = GetPendingEntry()->GetFrameEntry(root); + FrameTreeNode* frame = root; + int ftn_id = GetPendingEntry()->frame_tree_node_id(); + if (ftn_id != -1) { + frame = delegate_->GetFrameTree()->FindByID(ftn_id); + DCHECK(frame); + } + return frame->navigator()->NavigateToPendingEntry(frame, *frame_entry, + reload_type, false); + } + + // In --site-per-process, we compare FrameNavigationEntries to see which + // frames in the tree need to be navigated. + FrameLoadVector same_document_loads; + FrameLoadVector different_document_loads; + if (GetLastCommittedEntry()) { + FindFramesToNavigate(root, &same_document_loads, &different_document_loads); + } + + if (same_document_loads.empty() && different_document_loads.empty()) { + // If we don't have any frames to navigate at this point, either + // (1) there is no previous history entry to compare against, or + // (2) we were unable to match any frames by name. In the first case, + // doing a different document navigation to the root item is the only valid + // thing to do. In the second case, we should have been able to find a + // frame to navigate based on names if this were a same document + // navigation, so we can safely assume this is the different document case. + different_document_loads.push_back( + std::make_pair(root, pending_entry_->GetFrameEntry(root))); + } + + // If all the frame loads fail, we will discard the pending entry. + bool success = false; + + // Send all the same document frame loads before the different document loads. + for (const auto& item : same_document_loads) { + FrameTreeNode* frame = item.first; + success |= frame->navigator()->NavigateToPendingEntry(frame, *item.second, + reload_type, true); + } + for (const auto& item : different_document_loads) { + FrameTreeNode* frame = item.first; + success |= frame->navigator()->NavigateToPendingEntry(frame, *item.second, + reload_type, false); + } + return success; +} + +void NavigationControllerImpl::FindFramesToNavigate( + FrameTreeNode* frame, + FrameLoadVector* same_document_loads, + FrameLoadVector* different_document_loads) { + DCHECK(pending_entry_); + DCHECK_GE(last_committed_entry_index_, 0); + FrameNavigationEntry* new_item = pending_entry_->GetFrameEntry(frame); + FrameNavigationEntry* old_item = + GetLastCommittedEntry()->GetFrameEntry(frame); + if (!new_item) + return; + + // Schedule a load in this frame if the new item isn't for the same item + // sequence number in the same SiteInstance. + if (!old_item || + new_item->item_sequence_number() != old_item->item_sequence_number() || + new_item->site_instance() != old_item->site_instance()) { + if (old_item && + new_item->document_sequence_number() == + old_item->document_sequence_number()) { + 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 (size_t i = 0; i < frame->child_count(); i++) { + FindFramesToNavigate(frame->child_at(i), same_document_loads, + different_document_loads); + } +} + void NavigationControllerImpl::NotifyNavigationEntryCommitted( LoadCommittedDetails* details) { details->entry = GetLastCommittedEntry(); diff --git a/content/browser/frame_host/navigation_controller_impl.h b/content/browser/frame_host/navigation_controller_impl.h index 91fb27d..d1f6760 100644 --- a/content/browser/frame_host/navigation_controller_impl.h +++ b/content/browser/frame_host/navigation_controller_impl.h @@ -221,6 +221,10 @@ class CONTENT_EXPORT NavigationControllerImpl FRIEND_TEST_ALL_PREFIXES(TimeSmoother, ManyDuplicates); FRIEND_TEST_ALL_PREFIXES(TimeSmoother, ClockBackwardsJump); + // Used for identifying which frames need to navigate. + using FrameLoadVector = + std::vector<std::pair<FrameTreeNode*, FrameNavigationEntry*>>; + // Helper class to smooth out runs of duplicate timestamps while still // allowing time to jump backwards. class CONTENT_EXPORT TimeSmoother { @@ -235,6 +239,23 @@ class CONTENT_EXPORT NavigationControllerImpl base::Time high_water_mark_; }; + // Causes the controller to load the specified entry. The function assumes + // ownership of the pointer since it is put in the navigation list. + // NOTE: Do not pass an entry that the controller already owns! + void LoadEntry(NavigationEntryImpl* entry); + + // Identifies which frames need to be navigated for the pending + // NavigationEntry and instructs their Navigator to navigate them. Returns + // whether any frame successfully started a navigation. + bool NavigateToPendingEntryInternal(ReloadType reload_type); + + // Recursively identifies which frames need to be navigated for the pending + // NavigationEntry, starting at |frame| and exploring its children. Only used + // in --site-per-process. + void FindFramesToNavigate(FrameTreeNode* frame, + FrameLoadVector* sameDocumentLoads, + FrameLoadVector* differentDocumentLoads); + // Classifies the given renderer navigation (see the NavigationType enum). NavigationType ClassifyNavigation( RenderFrameHostImpl* rfh, @@ -246,11 +267,6 @@ class CONTENT_EXPORT NavigationControllerImpl RenderFrameHostImpl* rfh, const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const; - // Causes the controller to load the specified entry. The function assumes - // ownership of the pointer since it is put in the navigation list. - // NOTE: Do not pass an entry that the controller already owns! - void LoadEntry(NavigationEntryImpl* entry); - // Handlers for the different types of navigation types. They will actually // handle the navigations corresponding to the different NavClasses above. // They will NOT broadcast the commit notification, that should be handled by diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc index 96fc602..f589ece 100644 --- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc @@ -1547,6 +1547,150 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, } } +// Verify the tree of FrameNavigationEntries after back/forward navigations in a +// cross-site subframe. +IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, + FrameNavigationEntry_SubframeBackForward) { + GURL main_url(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_1.html")); + NavigateToURL(shell(), main_url); + const NavigationControllerImpl& controller = + static_cast<const NavigationControllerImpl&>( + shell()->web_contents()->GetController()); + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + + // 1. Create a same-site iframe. + GURL frame_url(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_2.html")); + { + LoadCommittedCapturer capturer(shell()->web_contents()); + std::string script = "var iframe = document.createElement('iframe');" + "iframe.src = '" + frame_url.spec() + "';" + "document.body.appendChild(iframe);"; + EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script)); + capturer.Wait(); + } + NavigationEntryImpl* entry1 = controller.GetLastCommittedEntry(); + + // 2. Navigate in the subframe cross-site. + GURL frame_url2(embedded_test_server()->GetURL( + "foo.com", "/navigation_controller/page_with_links.html")); + { + FrameNavigateParamsCapturer capturer(root->child_at(0)); + NavigateFrameToURL(root->child_at(0), frame_url2); + capturer.Wait(); + } + EXPECT_EQ(2, controller.GetEntryCount()); + EXPECT_EQ(1, controller.GetLastCommittedEntryIndex()); + NavigationEntryImpl* entry2 = controller.GetLastCommittedEntry(); + + // 3. Navigate in the subframe cross-site again. + GURL frame_url3(embedded_test_server()->GetURL( + "bar.com", "/navigation_controller/page_with_links.html")); + { + FrameNavigateParamsCapturer capturer(root->child_at(0)); + NavigateFrameToURL(root->child_at(0), frame_url3); + capturer.Wait(); + } + EXPECT_EQ(3, controller.GetEntryCount()); + EXPECT_EQ(2, controller.GetLastCommittedEntryIndex()); + NavigationEntryImpl* entry3 = controller.GetLastCommittedEntry(); + + // 4. Go back in the subframe. + { + FrameNavigateParamsCapturer capturer(root->child_at(0)); + shell()->web_contents()->GetController().GoBack(); + capturer.Wait(); + EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition); + EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type); + } + EXPECT_EQ(3, controller.GetEntryCount()); + EXPECT_EQ(1, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(entry2, controller.GetLastCommittedEntry()); + + // Verify subframe entries if we're in --site-per-process mode. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) { + // The entry should have a new FrameNavigationEntries for the subframe. + ASSERT_EQ(1U, entry2->root_node()->children.size()); + EXPECT_EQ(frame_url2, entry2->root_node()->children[0]->frame_entry->url()); + } else { + // There are no subframe FrameNavigationEntries by default. + EXPECT_EQ(0U, entry2->root_node()->children.size()); + } + + // 5. Go back in the subframe again to the parent page's site. + { + FrameNavigateParamsCapturer capturer(root->child_at(0)); + shell()->web_contents()->GetController().GoBack(); + capturer.Wait(); + EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition); + EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type); + } + EXPECT_EQ(3, controller.GetEntryCount()); + EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(entry1, controller.GetLastCommittedEntry()); + + // Verify subframe entries if we're in --site-per-process mode. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) { + // The entry should have a new FrameNavigationEntries for the subframe. + ASSERT_EQ(1U, entry1->root_node()->children.size()); + EXPECT_EQ(frame_url, entry1->root_node()->children[0]->frame_entry->url()); + } else { + // There are no subframe FrameNavigationEntries by default. + EXPECT_EQ(0U, entry1->root_node()->children.size()); + } + + // 6. Go forward in the subframe cross-site. + { + FrameNavigateParamsCapturer capturer(root->child_at(0)); + shell()->web_contents()->GetController().GoForward(); + capturer.Wait(); + EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition); + EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type); + } + EXPECT_EQ(3, controller.GetEntryCount()); + EXPECT_EQ(1, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(entry2, controller.GetLastCommittedEntry()); + + // Verify subframe entries if we're in --site-per-process mode. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) { + // The entry should have a new FrameNavigationEntries for the subframe. + ASSERT_EQ(1U, entry2->root_node()->children.size()); + EXPECT_EQ(frame_url2, entry2->root_node()->children[0]->frame_entry->url()); + } else { + // There are no subframe FrameNavigationEntries by default. + EXPECT_EQ(0U, entry2->root_node()->children.size()); + } + + // 7. Go forward in the subframe again, cross-site. + { + FrameNavigateParamsCapturer capturer(root->child_at(0)); + shell()->web_contents()->GetController().GoForward(); + capturer.Wait(); + EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition); + EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type); + } + EXPECT_EQ(3, controller.GetEntryCount()); + EXPECT_EQ(2, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(entry3, controller.GetLastCommittedEntry()); + + // Verify subframe entries if we're in --site-per-process mode. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) { + // The entry should have a new FrameNavigationEntries for the subframe. + ASSERT_EQ(1U, entry3->root_node()->children.size()); + EXPECT_EQ(frame_url3, entry3->root_node()->children[0]->frame_entry->url()); + } else { + // There are no subframe FrameNavigationEntries by default. + EXPECT_EQ(0U, entry3->root_node()->children.size()); + } +} + // Verifies that item sequence numbers and document sequence numbers update // properly for main frames and subframes. IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, @@ -1736,6 +1880,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, // Ensure the renderer process does not get confused about the current entry // due to subframes and replaced entries. See https://crbug.com/480201. +// TODO(creis): Re-enable for Site Isolation FYI bots: https://crbug.com/502317. IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, PreventSpoofFromSubframeAndReplace) { // Start at an initial URL. diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index dd9a97d..e62903a 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc @@ -417,6 +417,7 @@ NavigationEntryImpl* NavigationEntryImpl::CloneAndReplace( } CommonNavigationParams NavigationEntryImpl::ConstructCommonNavigationParams( + const FrameNavigationEntry& frame_entry, FrameMsg_Navigate_Type::Value navigation_type) const { FrameMsg_UILoadMetricsReportType::Value report_type = FrameMsg_UILoadMetricsReportType::NO_REPORT; @@ -428,9 +429,9 @@ CommonNavigationParams NavigationEntryImpl::ConstructCommonNavigationParams( #endif return CommonNavigationParams( - GetURL(), GetReferrer(), GetTransitionType(), navigation_type, - !IsViewSourceMode(), ui_timestamp, report_type, GetBaseURLForDataURL(), - GetHistoryURLForDataURL()); + frame_entry.url(), frame_entry.referrer(), GetTransitionType(), + navigation_type, !IsViewSourceMode(), ui_timestamp, report_type, + GetBaseURLForDataURL(), GetHistoryURLForDataURL()); } StartNavigationParams NavigationEntryImpl::ConstructStartNavigationParams() @@ -450,7 +451,9 @@ StartNavigationParams NavigationEntryImpl::ConstructStartNavigationParams() } RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams( + const FrameNavigationEntry& frame_entry, base::TimeTicks navigation_start, + bool is_same_document_history_load, bool has_committed_real_load, bool intended_as_new_entry, int pending_history_list_offset, @@ -476,10 +479,11 @@ RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams( } return RequestNavigationParams( GetIsOverridingUserAgent(), navigation_start, redirects, - GetCanLoadLocalResources(), base::Time::Now(), GetPageState(), - GetPageID(), GetUniqueID(), has_committed_real_load, - intended_as_new_entry, pending_offset_to_send, current_offset_to_send, - current_length_to_send, should_clear_history_list()); + GetCanLoadLocalResources(), base::Time::Now(), frame_entry.page_state(), + GetPageID(), GetUniqueID(), is_same_document_history_load, + has_committed_real_load, intended_as_new_entry, pending_offset_to_send, + current_offset_to_send, current_length_to_send, + should_clear_history_list()); } void NavigationEntryImpl::ResetForCommit() { diff --git a/content/browser/frame_host/navigation_entry_impl.h b/content/browser/frame_host/navigation_entry_impl.h index 63fa5e0..816a2e5 100644 --- a/content/browser/frame_host/navigation_entry_impl.h +++ b/content/browser/frame_host/navigation_entry_impl.h @@ -142,10 +142,13 @@ class CONTENT_EXPORT NavigationEntryImpl // Helper functions to construct NavigationParameters for a navigation to this // NavigationEntry. CommonNavigationParams ConstructCommonNavigationParams( + const FrameNavigationEntry& frame_entry, FrameMsg_Navigate_Type::Value navigation_type) const; StartNavigationParams ConstructStartNavigationParams() const; RequestNavigationParams ConstructRequestNavigationParams( + const FrameNavigationEntry& frame_entry, base::TimeTicks navigation_start, + bool is_same_document_history_load, bool has_committed_real_load, bool intended_as_new_entry, int pending_offset_to_send, diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 8d9a206..c78a995 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc @@ -61,8 +61,10 @@ bool NavigationRequest::ShouldMakeNetworkRequest(const GURL& url) { // static scoped_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated( FrameTreeNode* frame_tree_node, + const FrameNavigationEntry& frame_entry, const NavigationEntryImpl& entry, FrameMsg_Navigate_Type::Value navigation_type, + bool is_same_document_history_load, base::TimeTicks navigation_start, NavigationControllerImpl* controller) { std::string method = entry.GetHasPostData() ? "POST" : "GET"; @@ -87,11 +89,13 @@ scoped_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated( } scoped_ptr<NavigationRequest> navigation_request(new NavigationRequest( - frame_tree_node, entry.ConstructCommonNavigationParams(navigation_type), + frame_tree_node, + entry.ConstructCommonNavigationParams(frame_entry, navigation_type), BeginNavigationParams(method, headers.ToString(), LoadFlagFromNavigationType(navigation_type), false), entry.ConstructRequestNavigationParams( - navigation_start, controller->HasCommittedRealLoad(frame_tree_node), + frame_entry, navigation_start, is_same_document_history_load, + controller->HasCommittedRealLoad(frame_tree_node), controller->GetPendingEntryIndex() == -1, controller->GetIndexOfEntry(&entry), controller->GetLastCommittedEntryIndex(), diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index 6cc7dc8..e6f1191 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h @@ -16,6 +16,7 @@ namespace content { +class FrameNavigationEntry; class FrameTreeNode; class NavigationControllerImpl; class NavigationURLLoader; @@ -61,8 +62,10 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate { // Creates a request for a browser-intiated navigation. static scoped_ptr<NavigationRequest> CreateBrowserInitiated( FrameTreeNode* frame_tree_node, + const FrameNavigationEntry& frame_entry, const NavigationEntryImpl& entry, FrameMsg_Navigate_Type::Value navigation_type, + bool is_same_document_history_load, base::TimeTicks navigation_start, NavigationControllerImpl* controller); diff --git a/content/browser/frame_host/navigator.cc b/content/browser/frame_host/navigator.cc index 1ca9dfc..de1e0c7 100644 --- a/content/browser/frame_host/navigator.cc +++ b/content/browser/frame_host/navigator.cc @@ -20,7 +20,9 @@ NavigationController* Navigator::GetController() { bool Navigator::NavigateToPendingEntry( FrameTreeNode* frame_tree_node, - NavigationController::ReloadType reload_type) { + const FrameNavigationEntry& frame_entry, + NavigationController::ReloadType reload_type, + bool is_same_document_history_load) { return false; } diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h index 986f731..2fbbf11 100644 --- a/content/browser/frame_host/navigator.h +++ b/content/browser/frame_host/navigator.h @@ -23,6 +23,7 @@ class TimeTicks; namespace content { +class FrameNavigationEntry; class FrameTreeNode; class NavigationControllerImpl; class NavigationEntryImpl; @@ -88,7 +89,9 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> { // initialization of Navigator and NavigationController is properly done. virtual bool NavigateToPendingEntry( FrameTreeNode* frame_tree_node, - NavigationController::ReloadType reload_type); + const FrameNavigationEntry& frame_entry, + NavigationController::ReloadType reload_type, + bool is_same_document_history_load); // Navigation requests ------------------------------------------------------- diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index 4b3143d..e5e70ad 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc @@ -224,13 +224,15 @@ void NavigatorImpl::DidFailLoadWithError( bool NavigatorImpl::NavigateToEntry( FrameTreeNode* frame_tree_node, + const FrameNavigationEntry& frame_entry, const NavigationEntryImpl& entry, - NavigationController::ReloadType reload_type) { + NavigationController::ReloadType reload_type, + bool is_same_document_history_load) { TRACE_EVENT0("browser,navigation", "NavigatorImpl::NavigateToEntry"); // The renderer will reject IPC messages with URLs longer than // this limit, so don't attempt to navigate with a longer URL. - if (entry.GetURL().spec().size() > GetMaxURLChars()) { + if (frame_entry.url().spec().size() > GetMaxURLChars()) { LOG(WARNING) << "Refusing to load URL as it exceeds " << GetMaxURLChars() << " characters."; return false; @@ -248,17 +250,21 @@ bool NavigatorImpl::NavigateToEntry( if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableBrowserSideNavigation)) { navigation_data_.reset(new NavigationMetricsData( - navigation_start, entry.GetURL(), entry.restore_type())); - RequestNavigation(frame_tree_node, entry, reload_type, navigation_start); + navigation_start, frame_entry.url(), entry.restore_type())); + RequestNavigation(frame_tree_node, frame_entry, entry, reload_type, + is_same_document_history_load, navigation_start); // Notify observers about navigation. - if (delegate_) - delegate_->DidStartNavigationToPendingEntry(entry.GetURL(), reload_type); + if (delegate_) { + delegate_->DidStartNavigationToPendingEntry(frame_entry.url(), + reload_type); + } return true; } - RenderFrameHostImpl* dest_render_frame_host = manager->Navigate(entry); + RenderFrameHostImpl* dest_render_frame_host = + manager->Navigate(frame_entry, entry); if (!dest_render_frame_host) return false; // Unable to create the desired RenderFrameHost. @@ -267,8 +273,8 @@ bool NavigatorImpl::NavigateToEntry( // For security, we should never send non-Web-UI URLs to a Web UI renderer. // Double check that here. - CheckWebUIRendererDoesNotDisplayNormalURL( - dest_render_frame_host, entry.GetURL()); + CheckWebUIRendererDoesNotDisplayNormalURL(dest_render_frame_host, + frame_entry.url()); // Notify observers that we will navigate in this RenderFrame. if (delegate_) { @@ -286,17 +292,17 @@ bool NavigatorImpl::NavigateToEntry( dest_render_frame_host->GetProcess()->GetID(); if (!is_transfer_to_same) { navigation_data_.reset(new NavigationMetricsData( - navigation_start, entry.GetURL(), entry.restore_type())); + navigation_start, frame_entry.url(), entry.restore_type())); // Create the navigation parameters. // TODO(vitalybuka): Move this before AboutToNavigateRenderFrame once // http://crbug.com/408684 is fixed. FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); dest_render_frame_host->Navigate( - entry.ConstructCommonNavigationParams(navigation_type), + entry.ConstructCommonNavigationParams(frame_entry, navigation_type), entry.ConstructStartNavigationParams(), entry.ConstructRequestNavigationParams( - navigation_start, + frame_entry, navigation_start, is_same_document_history_load, controller_->HasCommittedRealLoad(frame_tree_node), controller_->GetPendingEntryIndex() == -1, controller_->GetIndexOfEntry(&entry), @@ -317,22 +323,26 @@ bool NavigatorImpl::NavigateToEntry( // do not generate content. What we really need is a message from the // renderer telling us that a new page was not created. The same message // could be used for mailto: URLs and the like. - if (entry.GetURL().SchemeIs(url::kJavaScriptScheme)) + if (frame_entry.url().SchemeIs(url::kJavaScriptScheme)) return false; } // Notify observers about navigation. - if (delegate_) - delegate_->DidStartNavigationToPendingEntry(entry.GetURL(), reload_type); + if (delegate_) { + delegate_->DidStartNavigationToPendingEntry(frame_entry.url(), reload_type); + } return true; } bool NavigatorImpl::NavigateToPendingEntry( FrameTreeNode* frame_tree_node, - NavigationController::ReloadType reload_type) { - return NavigateToEntry(frame_tree_node, *controller_->GetPendingEntry(), - reload_type); + const FrameNavigationEntry& frame_entry, + NavigationController::ReloadType reload_type, + bool is_same_document_history_load) { + return NavigateToEntry(frame_tree_node, frame_entry, + *controller_->GetPendingEntry(), reload_type, + is_same_document_history_load); } void NavigatorImpl::DidNavigate( @@ -798,8 +808,10 @@ void NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL( // PlzNavigate void NavigatorImpl::RequestNavigation( FrameTreeNode* frame_tree_node, + const FrameNavigationEntry& frame_entry, const NavigationEntryImpl& entry, NavigationController::ReloadType reload_type, + bool is_same_document_history_load, base::TimeTicks navigation_start) { CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableBrowserSideNavigation)); @@ -812,9 +824,9 @@ void NavigatorImpl::RequestNavigation( FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); frame_tree_node->CreatedNavigationRequest( - NavigationRequest::CreateBrowserInitiated(frame_tree_node, entry, - navigation_type, - navigation_start, controller_)); + NavigationRequest::CreateBrowserInitiated( + frame_tree_node, frame_entry, entry, navigation_type, + is_same_document_history_load, navigation_start, controller_)); NavigationRequest* navigation_request = frame_tree_node->navigation_request(); // Have the current renderer execute its beforeunload event if needed. If it diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h index 05573a4..6402a55 100644 --- a/content/browser/frame_host/navigator_impl.h +++ b/content/browser/frame_host/navigator_impl.h @@ -49,9 +49,10 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator { void DidNavigate(RenderFrameHostImpl* render_frame_host, const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params) override; - bool NavigateToPendingEntry( - FrameTreeNode* frame_tree_node, - NavigationController::ReloadType reload_type) override; + bool NavigateToPendingEntry(FrameTreeNode* frame_tree_node, + const FrameNavigationEntry& frame_entry, + NavigationController::ReloadType reload_type, + bool is_same_document_history_load) override; void RequestOpenURL(RenderFrameHostImpl* render_frame_host, const GURL& url, SiteInstance* source_site_instance, @@ -97,10 +98,11 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator { // Navigates to the given entry, which must be the pending entry. Private // because all callers should use NavigateToPendingEntry. - bool NavigateToEntry( - FrameTreeNode* frame_tree_node, - const NavigationEntryImpl& entry, - NavigationController::ReloadType reload_type); + bool NavigateToEntry(FrameTreeNode* frame_tree_node, + const FrameNavigationEntry& frame_entry, + const NavigationEntryImpl& entry, + NavigationController::ReloadType reload_type, + bool is_same_document_history_load); bool ShouldAssignSiteForURL(const GURL& url); @@ -112,8 +114,10 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator { // to execute the beforeUnload event. Otherwise, the navigation request will // be started. void RequestNavigation(FrameTreeNode* frame_tree_node, + const FrameNavigationEntry& frame_entry, const NavigationEntryImpl& entry, NavigationController::ReloadType reload_type, + bool is_same_document_history_load, base::TimeTicks navigation_start); void RecordNavigationMetrics( diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index 6489f69..7bf1733 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc @@ -14,6 +14,7 @@ #include "content/browser/devtools/render_frame_devtools_agent_host.h" #include "content/browser/frame_host/cross_site_transferring_request.h" #include "content/browser/frame_host/debug_urls.h" +#include "content/browser/frame_host/frame_navigation_entry.h" #include "content/browser/frame_host/interstitial_page_impl.h" #include "content/browser/frame_host/navigation_controller_impl.h" #include "content/browser/frame_host/navigation_entry_impl.h" @@ -182,12 +183,15 @@ scoped_ptr<WebUIImpl> RenderFrameHostManager::CreateWebUI(const GURL& url, } RenderFrameHostImpl* RenderFrameHostManager::Navigate( + const FrameNavigationEntry& frame_entry, const NavigationEntryImpl& entry) { TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate", "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); // Create a pending RenderFrameHost to use for the navigation. RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate( - entry.GetURL(), entry.source_site_instance(), entry.site_instance(), + frame_entry.url(), + // TODO(creis): Move source_site_instance to FNE. + entry.source_site_instance(), frame_entry.site_instance(), entry.GetTransitionType(), entry.restore_type() != NavigationEntryImpl::RESTORE_NONE, entry.IsViewSourceMode(), entry.transferred_global_request_id(), diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h index fd65394..6a5bc8b 100644 --- a/content/browser/frame_host/render_frame_host_manager.h +++ b/content/browser/frame_host/render_frame_host_manager.h @@ -25,6 +25,7 @@ namespace content { class BrowserContext; class CrossProcessFrameConnector; class CrossSiteTransferringRequest; +class FrameNavigationEntry; class FrameTreeNode; class InterstitialPageImpl; class NavigationControllerImpl; @@ -251,7 +252,8 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver { // navigation entry. It may create a new RenderFrameHost or re-use an existing // one. The RenderFrameHost to navigate will be returned. Returns NULL if one // could not be created. - RenderFrameHostImpl* Navigate(const NavigationEntryImpl& entry); + RenderFrameHostImpl* Navigate(const FrameNavigationEntry& frame_entry, + const NavigationEntryImpl& entry); // Instructs the various live views to stop. Called when the user directed the // page to stop loading. diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc index 6bf1476..41d4716 100644 --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc @@ -419,12 +419,14 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness { RenderFrameHostImpl* NavigateToEntry( RenderFrameHostManager* manager, const NavigationEntryImpl& entry) { + // Tests currently only navigate using main frame FrameNavigationEntries. + FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get(); if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableBrowserSideNavigation)) { scoped_ptr<NavigationRequest> navigation_request = NavigationRequest::CreateBrowserInitiated( - manager->frame_tree_node_, entry, FrameMsg_Navigate_Type::NORMAL, - base::TimeTicks::Now(), + manager->frame_tree_node_, *frame_entry, entry, + FrameMsg_Navigate_Type::NORMAL, false, base::TimeTicks::Now(), static_cast<NavigationControllerImpl*>(&controller())); TestRenderFrameHost* frame_host = static_cast<TestRenderFrameHost*>( manager->GetFrameHostForNavigation(*navigation_request)); @@ -432,7 +434,8 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness { frame_host->set_pending_commit(true); return frame_host; } - return manager->Navigate(entry); + + return manager->Navigate(*frame_entry, entry); } // Returns the pending RenderFrameHost. diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 59a443a..390121b 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -1991,27 +1991,6 @@ bool WebContentsImpl::Send(IPC::Message* message) { return GetRenderViewHost()->Send(message); } -bool WebContentsImpl::NavigateToPendingEntry( - NavigationController::ReloadType reload_type) { - FrameTreeNode* node = frame_tree_.root(); - - // Navigate in the FrameTreeNode specified in the pending entry, if any. This - // is currently only used in --site-per-process and tests - // (e.g., NavigateFrameToURL). - // TODO(creis): Remove this method and NavigationEntryImpl::frame_tree_node_id - // by using FrameNavigationEntries instead. See https://crbug.com/236848. - NavigationEntryImpl* pending_entry = controller_.GetPendingEntry(); - if (pending_entry->frame_tree_node_id() != -1) { - FrameTreeNode* subframe = - frame_tree_.FindByID(pending_entry->frame_tree_node_id()); - DCHECK(subframe); - if (subframe) - node = subframe; - } - - return node->navigator()->NavigateToPendingEntry(node, reload_type); -} - void WebContentsImpl::RenderFrameForInterstitialPageCreated( RenderFrameHost* render_frame_host) { FOR_EACH_OBSERVER(WebContentsObserver, observers_, diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 75f3e63..eb2cb6e 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h @@ -631,19 +631,6 @@ class CONTENT_EXPORT WebContentsImpl // |web_contents|. void CopyMaxPageIDsFrom(WebContents* web_contents) override; - // Called by the NavigationController to cause the WebContentsImpl to navigate - // to the current pending entry. The NavigationController should be called - // back with RendererDidNavigate on success or DiscardPendingEntry on failure. - // The callbacks can be inside of this function, or at some future time. - // - // The entry has a PageID of -1 if newly created (corresponding to navigation - // to a new URL). - // - // If this method returns false, then the navigation is discarded (equivalent - // to calling DiscardPendingEntry on the NavigationController). - bool NavigateToPendingEntry( - NavigationController::ReloadType reload_type) override; - // Sets the history for this WebContentsImpl to |history_length| entries, with // an offset of |history_offset|. void SetHistoryOffsetAndLength(int history_offset, diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 1db78bf..999c3e5 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h @@ -290,6 +290,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::RequestNavigationParams) IPC_STRUCT_TRAITS_MEMBER(page_state) IPC_STRUCT_TRAITS_MEMBER(page_id) IPC_STRUCT_TRAITS_MEMBER(nav_entry_id) + IPC_STRUCT_TRAITS_MEMBER(is_same_document_history_load) IPC_STRUCT_TRAITS_MEMBER(has_committed_real_load) IPC_STRUCT_TRAITS_MEMBER(intended_as_new_entry) IPC_STRUCT_TRAITS_MEMBER(pending_history_list_offset) diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc index 33d1c8e..8b70c8f 100644 --- a/content/common/navigation_params.cc +++ b/content/common/navigation_params.cc @@ -85,6 +85,7 @@ RequestNavigationParams::RequestNavigationParams() request_time(base::Time::Now()), page_id(-1), nav_entry_id(0), + is_same_document_history_load(false), has_committed_real_load(false), intended_as_new_entry(false), pending_history_list_offset(-1), @@ -102,6 +103,7 @@ RequestNavigationParams::RequestNavigationParams( const PageState& page_state, int32 page_id, int nav_entry_id, + bool is_same_document_history_load, bool has_committed_real_load, bool intended_as_new_entry, int pending_history_list_offset, @@ -116,6 +118,7 @@ RequestNavigationParams::RequestNavigationParams( page_state(page_state), page_id(page_id), nav_entry_id(nav_entry_id), + is_same_document_history_load(is_same_document_history_load), has_committed_real_load(has_committed_real_load), intended_as_new_entry(intended_as_new_entry), pending_history_list_offset(pending_history_list_offset), diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h index 8059471..86e5e06 100644 --- a/content/common/navigation_params.h +++ b/content/common/navigation_params.h @@ -170,6 +170,7 @@ struct CONTENT_EXPORT RequestNavigationParams { const PageState& page_state, int32 page_id, int nav_entry_id, + bool is_same_document_history_load, bool has_committed_real_load, bool intended_as_new_entry, int pending_history_list_offset, @@ -212,6 +213,10 @@ struct CONTENT_EXPORT RequestNavigationParams { // the resulting FrameHostMsg_DidCommitProvisionalLoad message. int nav_entry_id; + // For history navigations, this indicates whether the load will stay within + // the same document. Defaults to false. + bool is_same_document_history_load; + // Whether the frame being navigated has already committed a real page, which // affects how new navigations are classified in the renderer process. // This currently is only ever set to true in --site-per-process mode. diff --git a/content/renderer/history_controller.cc b/content/renderer/history_controller.cc index fd56623..0eb220b 100644 --- a/content/renderer/history_controller.cc +++ b/content/renderer/history_controller.cc @@ -62,7 +62,7 @@ void HistoryController::GoToEntry( HistoryFrameLoadVector same_document_loads; HistoryFrameLoadVector different_document_loads; - provisional_entry_ = target_entry.Pass(); + set_provisional_entry(target_entry.Pass()); navigation_params_ = navigation_params.Pass(); WebFrame* main_frame = render_view_->GetMainRenderFrame()->GetWebFrame(); diff --git a/content/renderer/history_controller.h b/content/renderer/history_controller.h index 0a46eef..095836c 100644 --- a/content/renderer/history_controller.h +++ b/content/renderer/history_controller.h @@ -110,6 +110,10 @@ class CONTENT_EXPORT HistoryController { explicit HistoryController(RenderViewImpl* render_view); ~HistoryController(); + void set_provisional_entry(scoped_ptr<HistoryEntry> entry) { + provisional_entry_ = entry.Pass(); + } + void GoToEntry(scoped_ptr<HistoryEntry> entry, scoped_ptr<NavigationParams> navigation_params, blink::WebURLRequest::CachePolicy cache_policy); diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 36ed29a..f43d444 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -3868,10 +3868,18 @@ void RenderFrameImpl::SendDidCommitProvisionalLoad( // Make navigation state a part of the DidCommitProvisionalLoad message so // that committed entry has it at all times. HistoryEntry* entry = render_view_->history_controller()->GetCurrentEntry(); - if (entry) - params.page_state = HistoryEntryToPageState(entry); - else - params.page_state = PageState::CreateFromURL(request.url()); + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) { + if (entry) + params.page_state = HistoryEntryToPageState(entry); + else + params.page_state = PageState::CreateFromURL(request.url()); + } else { + // In --site-per-process, just send a single HistoryItem for this frame, + // rather than the whole tree. It will be stored in the corresponding + // FrameNavigationEntry. + params.page_state = SingleHistoryItemToPageState(item); + } params.item_sequence_number = item.itemSequenceNumber(); params.document_sequence_number = item.documentSequenceNumber(); @@ -4424,8 +4432,39 @@ void RenderFrameImpl::NavigateInternal( if (!browser_side_navigation) { scoped_ptr<NavigationParams> navigation_params( new NavigationParams(*pending_navigation_params_.get())); - render_view_->history_controller()->GoToEntry( - entry.Pass(), navigation_params.Pass(), cache_policy); + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) { + // By default, tell the HistoryController to go the deserialized + // HistoryEntry. This only works if all frames are in the same + // process. + DCHECK(!frame_->parent()); + render_view_->history_controller()->GoToEntry( + entry.Pass(), navigation_params.Pass(), cache_policy); + } else { + // In --site-per-process, the browser process sends a single + // WebHistoryItem destined for this frame. + // TODO(creis): Change PageState to FrameState. In the meantime, we + // store the relevant frame's WebHistoryItem in the root of the + // PageState. + SetPendingNavigationParams(navigation_params.Pass()); + blink::WebHistoryItem history_item = entry->root(); + blink::WebHistoryLoadType load_type = + request_params.is_same_document_history_load + ? blink::WebHistorySameDocumentLoad + : blink::WebHistoryDifferentDocumentLoad; + + // Let the history controller know the provisional entry, since it is + // used at commit time. Otherwise skip GoToEntry and navigate the + // frame directly. + // TODO(creis): Consider cloning the current entry to handle subframe + // cases. Changes to SendUpdateState might affect this. + render_view_->history_controller()->set_provisional_entry( + entry.Pass()); + WebURLRequest request = + frame_->requestFromHistoryItem(history_item, cache_policy); + frame_->load(request, blink::WebFrameLoadType::BackForward, + history_item, load_type); + } } else { // TODO(clamy): this should be set to the HistoryItem sent by the // browser once the HistoryController has moved to the browser. diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 4991552..9cb0b24 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json @@ -3454,20 +3454,21 @@ { "args": [ "--site-per-process", - "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExtensionApiTest.ActiveTab:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionViewTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:*PDFExtensionTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewCommonTest.*:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs" + "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExtensionApiTest.ActiveTab:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionViewTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:*PDFExtensionTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:*.RestoreCrossSiteWithExistingSiteInstance:*.RestoreTabWithSpecialURLOnBack:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewCommonTest.*:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs" ], "test": "browser_tests" }, { "args": [ "--site-per-process", - "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.DisownOpener:*.SupportCrossProcessPostMessageWithMessagePort" + "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.DisownOpener:*.PreventSpoofFromSubframeAndReplace:SessionHistoryTest.CrossFrameFormBackForward:SessionHistoryTest.FrameBackForward:*.SupportCrossProcessPostMessageWithMessagePort" ], "test": "content_browsertests" }, { "args": [ - "--site-per-process" + "--site-per-process", + "--gtest_filter=-NavigatorTestWithBrowserSideNavigation.BeginNavigation" ], "test": "content_unittests" }, @@ -3484,20 +3485,21 @@ { "args": [ "--site-per-process", - "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExtensionApiTest.ActiveTab:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionViewTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:*PDFExtensionTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewCommonTest.*:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs" + "--gtest_filter=-AppApiTest.*:BlockedAppApiTest.*:BrowserTest.ClearPendingOnFailUnlessNTP:BrowserTest.OtherRedirectsDontForkProcess:BrowserTest.WindowOpenClose:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExtensionApiTest.ActiveTab:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.Tabs2:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionViewTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:*.NewAvatarMenuEnabledInGuestMode:OptionsUIBrowserTest.*:*PDFExtensionTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:RedirectTest.*:ReferrerPolicyTest.*:*.RestoreCrossSiteWithExistingSiteInstance:*.RestoreTabWithSpecialURLOnBack:SSLUITest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewCommonTest.*:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest*:WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabs" ], "test": "browser_tests" }, { "args": [ "--site-per-process", - "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.DisownOpener:*.SupportCrossProcessPostMessageWithMessagePort" + "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.DisownOpener:*.PreventSpoofFromSubframeAndReplace:SessionHistoryTest.CrossFrameFormBackForward:SessionHistoryTest.FrameBackForward:*.SupportCrossProcessPostMessageWithMessagePort" ], "test": "content_browsertests" }, { "args": [ - "--site-per-process" + "--site-per-process", + "--gtest_filter=-NavigatorTestWithBrowserSideNavigation.BeginNavigation" ], "test": "content_unittests" }, diff --git a/tools/copyright_scanner/third_party_files_whitelist.txt b/tools/copyright_scanner/third_party_files_whitelist.txt index 16037eb..cfd438a 100644 --- a/tools/copyright_scanner/third_party_files_whitelist.txt +++ b/tools/copyright_scanner/third_party_files_whitelist.txt @@ -53,6 +53,9 @@ chrome/utility/importer/nss_decryptor_system_nss.cc chrome/utility/importer/nss_decryptor_win.h # Copyright Google Inc; BSD license. Test code only. chrome/tools/test/generate_mime_tests.pl +# Copyright Apple Inc, Nokia Corporation and Torch Mobile Inc; BSD license. +# Contains code moved from third_party/WebKit/. +content/browser/frame_host/navigation_controller_impl.cc # Copyright Alf Watt; BSD license. Not used on Android. content/browser/geolocation/osx_wifi.h # Copyright Apple Inc and Torch Mobile Inc; BSD license. Moved from |