Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1230)

Unified Diff: content/browser/frame_host/render_frame_host_manager.cc

Issue 379143002: PlzNavigate: implement RequestNavigation in the no live renderer case (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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()) {

Powered by Google App Engine
This is Rietveld 408576698