| Index: content/browser/frame_host/render_frame_host_manager.cc
|
| diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
|
| index 9da1897e6b79dc7b4235671343335310a3d8a159..ef2fa0114a36baeefc984419891870da87633311 100644
|
| --- a/content/browser/frame_host/render_frame_host_manager.cc
|
| +++ b/content/browser/frame_host/render_frame_host_manager.cc
|
| @@ -15,6 +15,7 @@
|
| #include "content/browser/frame_host/cross_site_transferring_request.h"
|
| #include "content/browser/frame_host/debug_urls.h"
|
| #include "content/browser/frame_host/interstitial_page_impl.h"
|
| +#include "content/browser/frame_host/navigation_before_commit_info.h"
|
| #include "content/browser/frame_host/navigation_controller_impl.h"
|
| #include "content/browser/frame_host/navigation_entry_impl.h"
|
| #include "content/browser/frame_host/navigation_request.h"
|
| @@ -38,10 +39,42 @@
|
| #include "content/public/browser/user_metrics.h"
|
| #include "content/public/browser/web_ui_controller.h"
|
| #include "content/public/common/content_switches.h"
|
| +#include "content/public/common/referrer.h"
|
| #include "content/public/common/url_constants.h"
|
| +#include "net/base/load_flags.h"
|
|
|
| namespace content {
|
|
|
| +namespace {
|
| +
|
| +// PlzNavigate
|
| +// Simulates a renderer response to a navigation request when there is no live
|
| +// renderer.
|
| +FrameHostMsg_BeginNavigation_Params BeginNavigationFromNavigate(
|
| + const FrameMsg_Navigate_Params& navigate_params) {
|
| + FrameHostMsg_BeginNavigation_Params begin_navigation_params;
|
| + begin_navigation_params.method = navigate_params.is_post ? "POST" : "GET";
|
| + begin_navigation_params.url = navigate_params.url;
|
| + begin_navigation_params.referrer =
|
| + Referrer(navigate_params.referrer.url, navigate_params.referrer.policy);
|
| +
|
| + // TODO(clamy): This should be modified to take into account caching policy
|
| + // requirements (eg for POST reloads).
|
| + begin_navigation_params.load_flags = net::LOAD_NORMAL;
|
| +
|
| + // TODO(clamy): Post data from the browser should be put in the request body.
|
| +
|
| + begin_navigation_params.has_user_gesture = false;
|
| + begin_navigation_params.transition_type = navigate_params.transition;
|
| + begin_navigation_params.should_replace_current_entry =
|
| + navigate_params.should_replace_current_entry;
|
| + begin_navigation_params.allow_download =
|
| + navigate_params.allow_download;
|
| + return begin_navigation_params;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams(
|
| const GlobalRequestID& global_request_id,
|
| scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request,
|
| @@ -563,8 +596,28 @@ void RenderFrameHostManager::ResetProxyHosts() {
|
| STLDeleteValues(&proxy_hosts_);
|
| }
|
|
|
| +// PlzNavigate
|
| +bool RenderFrameHostManager::RequestNavigation(
|
| + const NavigationEntryImpl& entry,
|
| + const FrameMsg_Navigate_Params& navigate_params) {
|
| + CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kEnableBrowserSideNavigation));
|
| + // TODO(clamy): replace RenderViewHost::IsRenderViewLive by
|
| + // RenderFrameHost::IsLive.
|
| + if (render_frame_host_->render_view_host()->IsRenderViewLive())
|
| + // TODO(clamy): send a RequestNavigation IPC.
|
| + return true;
|
| +
|
| + // The navigation request is sent directly to the IO thread.
|
| + OnBeginNavigation(BeginNavigationFromNavigate(navigate_params));
|
| + return true;
|
| +}
|
| +
|
| +// PlzNavigate
|
| void RenderFrameHostManager::OnBeginNavigation(
|
| const FrameHostMsg_BeginNavigation_Params& params) {
|
| + CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kEnableBrowserSideNavigation));
|
| // TODO(clamy): Check if navigations are blocked and if so, return
|
| // immediately.
|
| NavigationRequestInfo info(params);
|
| @@ -576,11 +629,47 @@ void RenderFrameHostManager::OnBeginNavigation(
|
| false : frame_tree_node_->parent()->IsMainFrame();
|
| info.is_showing = GetRenderWidgetHostView()->IsShowing();
|
|
|
| - navigation_request_.reset(
|
| - new NavigationRequest(info, frame_tree_node_->frame_tree_node_id()));
|
| + // TODO(clamy): Check if the current RFH should be initialized (in case it has
|
| + // crashed) not to display a sad tab while navigating.
|
| + // TODO(clamy): Spawn a speculative renderer process if we do not have one to
|
| + // use for the navigation.
|
| + navigation_request_.reset(new NavigationRequest(
|
| + info, frame_tree_node_->frame_tree_node_id()));
|
| navigation_request_->BeginNavigation(params.request_body);
|
| - // TODO(clamy): If we have no live RenderFrameHost to handle the request (eg
|
| - // cross-site navigation) spawn one speculatively here and keep track of it.
|
| +}
|
| +
|
| +// PlzNavigate
|
| +void RenderFrameHostManager::CommitNavigation(
|
| + const NavigationBeforeCommitInfo& info) {
|
| + CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kEnableBrowserSideNavigation));
|
| + // Pick the right RenderFrameHost to commit the navigation.
|
| + SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
|
| + // TODO(clamy): Replace the default values by the right ones. This may require
|
| + // some storing in RequestNavigation.
|
| + SiteInstance* new_instance = GetSiteInstanceForNavigation(
|
| + info.navigation_url,
|
| + NULL,
|
| + navigation_request_->info().navigation_params.transition_type,
|
| + false,
|
| + false);
|
| + DCHECK(!pending_render_frame_host_.get());
|
| +
|
| + // TODO(clamy): Update how pending WebUI objects are handled.
|
| + if (current_instance != new_instance) {
|
| + CreateRenderFrameHostForNewSiteInstance(
|
| + current_instance, new_instance, frame_tree_node_->IsMainFrame());
|
| + DCHECK(pending_render_frame_host_.get());
|
| + // TODO(clamy): Wait until the navigation has committed before swapping
|
| + // renderers.
|
| + scoped_ptr<RenderFrameHostImpl> old_render_frame_host =
|
| + SetRenderFrameHost(pending_render_frame_host_.Pass());
|
| + if (frame_tree_node_->IsMainFrame())
|
| + render_frame_host_->render_view_host()->AttachToFrameTree();
|
| + }
|
| +
|
| + frame_tree_node_->navigator()->CommitNavigation(
|
| + render_frame_host_.get(), info);
|
| }
|
|
|
| void RenderFrameHostManager::Observe(
|
| @@ -717,6 +806,60 @@ bool RenderFrameHostManager::ShouldReuseWebUI(
|
| controller.GetBrowserContext(), new_entry->GetURL()));
|
| }
|
|
|
| +SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
|
| + const GURL& dest_url,
|
| + SiteInstance* dest_instance,
|
| + PageTransition dest_transition,
|
| + bool dest_is_restore,
|
| + bool dest_is_view_source_mode) {
|
| + SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
|
| + SiteInstance* new_instance = current_instance;
|
| +
|
| + // We do not currently swap processes for navigations in webview tag guests.
|
| + bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme);
|
| +
|
| + // Determine if we need a new BrowsingInstance for this entry. If true, this
|
| + // implies that it will get a new SiteInstance (and likely process), and that
|
| + // other tabs in the current BrowsingInstance will be unable to script it.
|
| + // This is used for cases that require a process swap even in the
|
| + // process-per-tab model, such as WebUI pages.
|
| + // TODO(clamy): Remove the dependency on the current entry.
|
| + const NavigationEntry* current_entry =
|
| + delegate_->GetLastCommittedNavigationEntryForRenderManager();
|
| + BrowserContext* browser_context =
|
| + delegate_->GetControllerForRenderManager().GetBrowserContext();
|
| + const GURL& current_effective_url = current_entry ?
|
| + SiteInstanceImpl::GetEffectiveURL(browser_context,
|
| + current_entry->GetURL()) :
|
| + render_frame_host_->GetSiteInstance()->GetSiteURL();
|
| + bool current_is_view_source_mode = current_entry ?
|
| + current_entry->IsViewSourceMode() : dest_is_view_source_mode;
|
| + bool force_swap = !is_guest_scheme &&
|
| + ShouldSwapBrowsingInstancesForNavigation(
|
| + current_effective_url,
|
| + current_is_view_source_mode,
|
| + dest_instance,
|
| + SiteInstanceImpl::GetEffectiveURL(browser_context, dest_url),
|
| + dest_is_view_source_mode);
|
| + if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) {
|
| + new_instance = GetSiteInstanceForURL(
|
| + dest_url,
|
| + dest_instance,
|
| + dest_transition,
|
| + dest_is_restore,
|
| + dest_is_view_source_mode,
|
| + current_instance,
|
| + force_swap);
|
| + }
|
| +
|
| + // If force_swap is true, we must use a different SiteInstance. If we didn't,
|
| + // we would have two RenderFrameHosts in the same SiteInstance and the same
|
| + // frame, resulting in page_id conflicts for their NavigationEntries.
|
| + if (force_swap)
|
| + CHECK_NE(new_instance, current_instance);
|
| + return new_instance;
|
| +}
|
| +
|
| SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
|
| const GURL& dest_url,
|
| SiteInstance* dest_instance,
|
| @@ -885,6 +1028,36 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
|
| return current_instance->GetRelatedSiteInstance(dest_url);
|
| }
|
|
|
| +void RenderFrameHostManager::CreateRenderFrameHostForNewSiteInstance(
|
| + SiteInstance* old_instance,
|
| + SiteInstance* new_instance,
|
| + bool is_main_frame) {
|
| + // Ensure that we have created RFHs for the new RFH's opener chain if
|
| + // we are staying in the same BrowsingInstance. This allows the new RFH
|
| + // to send cross-process script calls to its opener(s).
|
| + int opener_route_id = MSG_ROUTING_NONE;
|
| + if (new_instance->IsRelatedSiteInstance(old_instance)) {
|
| + opener_route_id =
|
| + delegate_->CreateOpenerRenderViewsForRenderManager(new_instance);
|
| + if (CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kSitePerProcess)) {
|
| + // Ensure that the frame tree has RenderFrameProxyHosts for the new
|
| + // SiteInstance in all nodes except the current one.
|
| + frame_tree_node_->frame_tree()->CreateProxiesForSiteInstance(
|
| + frame_tree_node_, new_instance);
|
| + }
|
| + }
|
| +
|
| + // Create a non-swapped-out RFH with the given opener.
|
| + int route_id = CreateRenderFrame(
|
| + new_instance, opener_route_id, false, is_main_frame,
|
| + delegate_->IsHidden());
|
| + if (route_id == MSG_ROUTING_NONE) {
|
| + pending_render_frame_host_.reset();
|
| + return;
|
| + }
|
| +}
|
| +
|
| scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
|
| SiteInstance* site_instance,
|
| int view_routing_id,
|
| @@ -1311,49 +1484,16 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
|
| }
|
|
|
| SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
|
| - scoped_refptr<SiteInstance> new_instance = current_instance;
|
| -
|
| - // We do not currently swap processes for navigations in webview tag guests.
|
| - bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme);
|
| -
|
| - // Determine if we need a new BrowsingInstance for this entry. If true, this
|
| - // implies that it will get a new SiteInstance (and likely process), and that
|
| - // other tabs in the current BrowsingInstance will be unable to script it.
|
| - // This is used for cases that require a process swap even in the
|
| - // process-per-tab model, such as WebUI pages.
|
| - const NavigationEntry* current_entry =
|
| - delegate_->GetLastCommittedNavigationEntryForRenderManager();
|
| - BrowserContext* browser_context =
|
| - delegate_->GetControllerForRenderManager().GetBrowserContext();
|
| - const GURL& current_effective_url = current_entry ?
|
| - SiteInstanceImpl::GetEffectiveURL(browser_context,
|
| - current_entry->GetURL()) :
|
| - render_frame_host_->GetSiteInstance()->GetSiteURL();
|
| - bool current_is_view_source_mode = current_entry ?
|
| - current_entry->IsViewSourceMode() : entry.IsViewSourceMode();
|
| - bool force_swap = !is_guest_scheme &&
|
| - ShouldSwapBrowsingInstancesForNavigation(
|
| - current_effective_url,
|
| - current_is_view_source_mode,
|
| + scoped_refptr<SiteInstance> new_instance =
|
| + GetSiteInstanceForNavigation(
|
| + entry.GetURL(),
|
| entry.site_instance(),
|
| - SiteInstanceImpl::GetEffectiveURL(browser_context, entry.GetURL()),
|
| + entry.GetTransitionType(),
|
| + entry.restore_type() != NavigationEntryImpl::RESTORE_NONE,
|
| entry.IsViewSourceMode());
|
| - if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) {
|
| - new_instance = GetSiteInstanceForURL(
|
| - entry.GetURL(),
|
| - entry.site_instance(),
|
| - entry.GetTransitionType(),
|
| - entry.restore_type() != NavigationEntryImpl::RESTORE_NONE,
|
| - entry.IsViewSourceMode(),
|
| - current_instance,
|
| - force_swap);
|
| - }
|
|
|
| - // If force_swap is true, we must use a different SiteInstance. If we didn't,
|
| - // we would have two RenderFrameHosts in the same SiteInstance and the same
|
| - // frame, resulting in page_id conflicts for their NavigationEntries.
|
| - if (force_swap)
|
| - CHECK_NE(new_instance, current_instance);
|
| + const NavigationEntry* current_entry =
|
| + delegate_->GetLastCommittedNavigationEntryForRenderManager();
|
|
|
| if (new_instance != current_instance) {
|
| // New SiteInstance: create a pending RFH to navigate.
|
| @@ -1366,33 +1506,11 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
|
| // otherwise CancelPending may clear the pending_web_ui_ and the page will
|
| // not have its bindings set appropriately.
|
| SetPendingWebUI(entry);
|
| -
|
| - // Ensure that we have created RFHs for the new RFH's opener chain if
|
| - // we are staying in the same BrowsingInstance. This allows the pending RFH
|
| - // to send cross-process script calls to its opener(s).
|
| - int opener_route_id = MSG_ROUTING_NONE;
|
| - if (new_instance->IsRelatedSiteInstance(current_instance)) {
|
| - opener_route_id =
|
| - delegate_->CreateOpenerRenderViewsForRenderManager(new_instance);
|
| -
|
| - if (CommandLine::ForCurrentProcess()->HasSwitch(
|
| - switches::kSitePerProcess)) {
|
| - // Ensure that the frame tree has RenderFrameProxyHosts for the new
|
| - // SiteInstance in all nodes except the current one.
|
| - frame_tree_node_->frame_tree()->CreateProxiesForSiteInstance(
|
| - frame_tree_node_, new_instance);
|
| - }
|
| - }
|
| -
|
| - // Create a non-swapped-out pending RFH with the given opener and navigate
|
| - // it.
|
| - int route_id = CreateRenderFrame(new_instance,
|
| - opener_route_id,
|
| - false,
|
| - frame_tree_node_->IsMainFrame(),
|
| - delegate_->IsHidden());
|
| - if (route_id == MSG_ROUTING_NONE)
|
| + CreateRenderFrameHostForNewSiteInstance(
|
| + current_instance, new_instance, frame_tree_node_->IsMainFrame());
|
| + if (!pending_render_frame_host_.get()) {
|
| return NULL;
|
| + }
|
|
|
| // Check if our current RFH is live before we set up a transition.
|
| if (!render_frame_host_->render_view_host()->IsRenderViewLive()) {
|
|
|