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 618391f77aba683d86a33bfc7d871a01c09d80f2..2ad4b1d5df036384e9f5e983f4140fdf944cb8a9 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,44 @@ |
#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"; |
nasko
2014/08/13 00:08:00
nit: these should fit in the previous line
clamy
2014/08/13 13:27:24
Done.
|
+ 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 | net::LOAD_ENABLE_LOAD_TIMING; |
+ |
+ // 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, |
@@ -230,6 +265,24 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate( |
return dest_render_frame_host; |
} |
+// 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), |
+ entry); |
+ return true; |
+} |
+ |
void RenderFrameHostManager::Stop() { |
render_frame_host_->render_view_host()->Stop(); |
@@ -567,8 +620,12 @@ void RenderFrameHostManager::ResetProxyHosts() { |
STLDeleteValues(&proxy_hosts_); |
} |
+// PlzNavigate |
void RenderFrameHostManager::OnBeginNavigation( |
- const FrameHostMsg_BeginNavigation_Params& params) { |
+ const FrameHostMsg_BeginNavigation_Params& params, |
+ const NavigationEntryImpl& entry) { |
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kEnableBrowserSideNavigation)); |
// TODO(clamy): Check if navigations are blocked and if so, return |
// immediately. |
NavigationRequestInfo info(params); |
@@ -580,11 +637,46 @@ 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, entry, 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)); |
+ // Update the stored NavigationEntry for commit. |
+ // TODO(clamy): Check if some more state should be updated at that point. |
+ navigation_request_->UpdateEntryForCommit(info.navigation_url); |
+ |
+ // Pick the right RenderFrameHost to commit the navigation. |
+ SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
+ SiteInstance* new_instance = GetSiteInstanceForNavigation( |
+ navigation_request_->entry()); |
+ DCHECK(!pending_render_frame_host_.get()); |
+ |
+ // TODO(clamy): Update how pending WebUI objects rae handled. |
Charlie Reis
2014/08/12 19:04:50
nit: are
clamy
2014/08/13 13:27:24
Done.
|
+ 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); |
+ navigation_request_.reset(); |
} |
void RenderFrameHostManager::Observe( |
@@ -731,6 +823,35 @@ bool RenderFrameHostManager::ShouldReuseWebUI( |
controller.GetBrowserContext(), new_entry->GetURL())); |
} |
+SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation( |
+ const NavigationEntryImpl& entry) { |
+ 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. |
+ const NavigationEntry* current_entry = |
+ delegate_->GetLastCommittedNavigationEntryForRenderManager(); |
+ bool force_swap = !is_guest_scheme && |
+ ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry); |
+ if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) |
+ new_instance = GetSiteInstanceForEntry(entry, 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::GetSiteInstanceForEntry( |
const NavigationEntryImpl& entry, |
SiteInstance* current_instance, |
@@ -898,6 +1019,36 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry( |
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, |
@@ -1324,28 +1475,11 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate( |
} |
SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
- scoped_refptr<SiteInstance> new_instance = current_instance; |
+ scoped_refptr<SiteInstance> new_instance = |
+ GetSiteInstanceForNavigation(entry); |
- // 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(); |
- bool force_swap = !is_guest_scheme && |
- ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry); |
- if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) |
- new_instance = GetSiteInstanceForEntry(entry, 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); |
if (new_instance != current_instance) { |
// New SiteInstance: create a pending RFH to navigate. |
@@ -1358,33 +1492,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()) { |