Index: content/browser/frame_host/navigator_impl.cc |
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc |
index a7341f830e7dd58836f324b0d402bbe3b9675050..e4afbe62a6628ddf93e7e7c52ef6c120d1189dc8 100644 |
--- a/content/browser/frame_host/navigator_impl.cc |
+++ b/content/browser/frame_host/navigator_impl.cc |
@@ -19,6 +19,7 @@ |
#include "content/browser/site_instance_impl.h" |
#include "content/browser/webui/web_ui_controller_factory_registry.h" |
#include "content/browser/webui/web_ui_impl.h" |
+#include "content/common/frame_messages.h" |
#include "content/common/navigation_params.h" |
#include "content/common/view_messages.h" |
#include "content/public/browser/browser_context.h" |
@@ -37,8 +38,6 @@ |
#include "content/public/common/resource_response.h" |
#include "content/public/common/url_constants.h" |
#include "content/public/common/url_utils.h" |
-#include "net/base/load_flags.h" |
-#include "net/http/http_request_headers.h" |
namespace content { |
@@ -70,65 +69,6 @@ FrameMsg_Navigate_Type::Value GetNavigationType( |
return FrameMsg_Navigate_Type::NORMAL; |
} |
-// PlzNavigate |
-// Returns the net load flags to use based on the navigation type. |
-// TODO(clamy): unify the code with what is happening on the renderer side. |
-int LoadFlagFromNavigationType(FrameMsg_Navigate_Type::Value navigation_type) { |
- int load_flags = net::LOAD_NORMAL; |
- switch (navigation_type) { |
- case FrameMsg_Navigate_Type::RELOAD: |
- case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL: |
- load_flags |= net::LOAD_VALIDATE_CACHE; |
- break; |
- case FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE: |
- load_flags |= net::LOAD_BYPASS_CACHE; |
- break; |
- case FrameMsg_Navigate_Type::RESTORE: |
- load_flags |= net::LOAD_PREFERRING_CACHE; |
- break; |
- case FrameMsg_Navigate_Type::RESTORE_WITH_POST: |
- load_flags |= net::LOAD_ONLY_FROM_CACHE; |
- break; |
- case FrameMsg_Navigate_Type::NORMAL: |
- default: |
- break; |
- } |
- return load_flags; |
-} |
- |
-// PlzNavigate |
-// Generates a default FrameHostMsg_BeginNavigation_Params to be used when there |
-// is no live renderer. |
-FrameHostMsg_BeginNavigation_Params MakeDefaultBeginNavigation( |
- const RequestNavigationParams& request_params, |
- FrameMsg_Navigate_Type::Value navigation_type) { |
- FrameHostMsg_BeginNavigation_Params begin_navigation_params; |
- begin_navigation_params.method = request_params.is_post ? "POST" : "GET"; |
- begin_navigation_params.load_flags = |
- LoadFlagFromNavigationType(navigation_type); |
- |
- // Copy existing headers and add necessary headers that may not be present |
- // in the RequestNavigationParams. |
- net::HttpRequestHeaders headers; |
- headers.AddHeadersFromString(request_params.extra_headers); |
- headers.SetHeaderIfMissing(net::HttpRequestHeaders::kUserAgent, |
- GetContentClient()->GetUserAgent()); |
- headers.SetHeaderIfMissing("Accept", "*/*"); |
- begin_navigation_params.headers = headers.ToString(); |
- |
- // Fill POST data from the browser in the request body. |
- if (request_params.is_post) { |
- begin_navigation_params.request_body = new ResourceRequestBody(); |
- begin_navigation_params.request_body->AppendBytes( |
- reinterpret_cast<const char *>( |
- &request_params.browser_initiated_post_data.front()), |
- request_params.browser_initiated_post_data.size()); |
- } |
- |
- begin_navigation_params.has_user_gesture = false; |
- return begin_navigation_params; |
-} |
- |
RenderFrameHostManager* GetRenderManager(RenderFrameHostImpl* rfh) { |
if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
switches::kSitePerProcess)) |
@@ -155,12 +95,17 @@ void MakeNavigateParams(const NavigationEntryImpl& entry, |
entry.GetURL(), entry.GetReferrer(), entry.GetTransitionType(), |
GetNavigationType(controller->GetBrowserContext(), entry, reload_type), |
!entry.IsViewSourceMode(), ui_timestamp, report_type); |
- params->request_params = RequestNavigationParams( |
- entry.GetHasPostData(), |
- entry.extra_headers(), |
- entry.GetBrowserInitiatedPostData()); |
params->commit_params = CommitNavigationParams( |
entry.GetPageState(), entry.GetIsOverridingUserAgent(), navigation_start); |
+ params->is_post = entry.GetHasPostData(); |
+ params->extra_headers = entry.extra_headers(); |
+ if (entry.GetBrowserInitiatedPostData()) { |
+ params->browser_initiated_post_data.assign( |
+ entry.GetBrowserInitiatedPostData()->front(), |
+ entry.GetBrowserInitiatedPostData()->front() + |
+ entry.GetBrowserInitiatedPostData()->size()); |
+ } |
+ |
if (!entry.GetBaseURLForDataURL().is_empty()) { |
params->base_url_for_data_url = entry.GetBaseURLForDataURL(); |
params->history_url_for_data_url = entry.GetVirtualURL(); |
@@ -403,10 +348,11 @@ bool NavigatorImpl::NavigateToEntry( |
switches::kEnableBrowserSideNavigation)) { |
navigation_data_.reset(new NavigationMetricsData( |
navigation_start, entry.GetURL(), entry.restore_type())); |
- return RequestNavigation(render_frame_host->frame_tree_node(), |
- entry, |
- reload_type, |
- navigation_start); |
+ RequestNavigation(render_frame_host->frame_tree_node(), |
+ entry, |
+ reload_type, |
+ navigation_start); |
+ return true; |
} |
RenderFrameHostImpl* dest_render_frame_host = manager->Navigate(entry); |
@@ -728,10 +674,8 @@ void NavigatorImpl::RequestTransferURL( |
} |
// PlzNavigate |
-void NavigatorImpl::OnBeginNavigation( |
- FrameTreeNode* frame_tree_node, |
- const FrameHostMsg_BeginNavigation_Params& params, |
- const CommonNavigationParams& common_params) { |
+void NavigatorImpl::OnBeforeUnloadACK(FrameTreeNode* frame_tree_node, |
+ bool proceed) { |
CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
switches::kEnableBrowserSideNavigation)); |
DCHECK(frame_tree_node); |
@@ -739,46 +683,44 @@ void NavigatorImpl::OnBeginNavigation( |
NavigationRequest* navigation_request = |
navigation_request_map_.get(frame_tree_node->frame_tree_node_id()); |
- if (!navigation_request) { |
- // This is a renderer initiated navigation, so generate a new |
- // NavigationRequest and store it in the map. |
- // TODO(clamy): Check if some PageState should be provided here. |
- // TODO(clamy): See how we should handle override of the user agent when the |
- // navigation may start in a renderer and commit in another one. |
- // TODO(clamy): See if the navigation start time should be measured in the |
- // renderer and sent to the browser instead of being measured here. |
- scoped_ptr<NavigationRequest> scoped_request(new NavigationRequest( |
- frame_tree_node, common_params, |
- CommitNavigationParams(PageState(), false, base::TimeTicks::Now()), |
- nullptr)); |
- navigation_request = scoped_request.get(); |
- navigation_request_map_.set( |
- frame_tree_node->frame_tree_node_id(), scoped_request.Pass()); |
- |
- if (frame_tree_node->IsMainFrame()) |
- navigation_data_.reset(); |
- } |
- DCHECK(navigation_request); |
+ // The NavigationRequest may have been canceled while the renderer was |
+ // executing the BeforeUnload event. |
+ if (!navigation_request) |
+ return; |
- // Update the referrer with the one received from the renderer. |
- navigation_request->common_params().referrer = common_params.referrer; |
+ DCHECK_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE, |
+ navigation_request->state()); |
- scoped_ptr<NavigationRequestInfo> info(new NavigationRequestInfo(params)); |
+ if (proceed) |
+ BeginNavigation(frame_tree_node); |
+ else |
+ CancelNavigation(frame_tree_node); |
+} |
- info->first_party_for_cookies = |
- frame_tree_node->IsMainFrame() |
- ? navigation_request->common_params().url |
- : frame_tree_node->frame_tree()->root()->current_url(); |
- info->is_main_frame = frame_tree_node->IsMainFrame(); |
- info->parent_is_main_frame = !frame_tree_node->parent() ? |
- false : frame_tree_node->parent()->IsMainFrame(); |
+// PlzNavigate |
+void NavigatorImpl::OnBeginNavigation( |
+ FrameTreeNode* frame_tree_node, |
+ const CommonNavigationParams& common_params, |
+ const BeginNavigationParams& begin_params, |
+ scoped_refptr<ResourceRequestBody> body) { |
+ CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kEnableBrowserSideNavigation)); |
+ DCHECK(frame_tree_node); |
- // First start the request on the IO thread. |
- navigation_request->BeginNavigation(info.Pass(), params.request_body); |
+ // This is a renderer-initiated navigation, so generate a new |
+ // NavigationRequest and store it in the map. |
+ // TODO(clamy): Renderer-initiated navigations should not always cancel the |
+ // current one. |
+ scoped_ptr<NavigationRequest> navigation_request = |
+ NavigationRequest::CreateRendererInitiated( |
+ frame_tree_node, common_params, begin_params, body); |
+ navigation_request_map_.set( |
+ frame_tree_node->frame_tree_node_id(), navigation_request.Pass()); |
- // Then notify the RenderFrameHostManager so it can speculatively create a |
- // RenderFrameHost (and potentially a new renderer process) in parallel. |
- frame_tree_node->render_manager()->BeginNavigation(*navigation_request); |
+ if (frame_tree_node->IsMainFrame()) |
+ navigation_data_.reset(); |
+ |
+ BeginNavigation(frame_tree_node); |
} |
// PlzNavigate |
@@ -881,7 +823,7 @@ void NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL( |
} |
// PlzNavigate |
-bool NavigatorImpl::RequestNavigation( |
+void NavigatorImpl::RequestNavigation( |
FrameTreeNode* frame_tree_node, |
const NavigationEntryImpl& entry, |
NavigationController::ReloadType reload_type, |
@@ -892,33 +834,39 @@ bool NavigatorImpl::RequestNavigation( |
int64 frame_tree_node_id = frame_tree_node->frame_tree_node_id(); |
FrameMsg_Navigate_Type::Value navigation_type = |
GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); |
- scoped_ptr<NavigationRequest> navigation_request = NavigationRequest::Create( |
- frame_tree_node, entry, navigation_type, navigation_start); |
- RequestNavigationParams request_params(entry.GetHasPostData(), |
- entry.extra_headers(), |
- entry.GetBrowserInitiatedPostData()); |
+ scoped_ptr<NavigationRequest> navigation_request = |
+ NavigationRequest::CreateBrowserInitiated( |
+ frame_tree_node, entry, navigation_type, navigation_start); |
// TODO(clamy): Check if navigations are blocked and if so store the |
// parameters. |
// If there is an ongoing request, replace it. |
navigation_request_map_.set(frame_tree_node_id, navigation_request.Pass()); |
- if (frame_tree_node->current_frame_host()->IsRenderFrameLive()) { |
- NavigationRequest* request_to_send = |
- navigation_request_map_.get(frame_tree_node_id); |
- frame_tree_node->current_frame_host()->Send(new FrameMsg_RequestNavigation( |
- frame_tree_node->current_frame_host()->GetRoutingID(), |
- request_to_send->common_params(), request_params)); |
- request_to_send->SetWaitingForRendererResponse(); |
- return true; |
- } |
+ // Have the current renderer execute its beforeUnload event if needed. If it |
+ // is not needed (eg. the renderer is not live), BeginNavigation should get |
+ // called. |
+ NavigationRequest* request_to_send = |
+ navigation_request_map_.get(frame_tree_node_id); |
+ request_to_send->SetWaitingForRendererResponse(); |
+ frame_tree_node->current_frame_host()->DispatchBeforeUnload(true); |
+} |
- // The navigation request is sent directly to the IO thread. |
- OnBeginNavigation( |
- frame_tree_node, |
- MakeDefaultBeginNavigation(request_params, navigation_type), |
- navigation_request_map_.get(frame_tree_node_id)->common_params()); |
- return true; |
+void NavigatorImpl::BeginNavigation(FrameTreeNode* frame_tree_node) { |
+ NavigationRequest* navigation_request = |
+ navigation_request_map_.get(frame_tree_node->frame_tree_node_id()); |
+ |
+ // A browser-initiated navigation could have been cancelled while it was |
+ // waiting for the BeforeUnload event to execute. |
+ if (!navigation_request) |
+ return; |
+ |
+ // First start the request on the IO thread. |
+ navigation_request->BeginNavigation(); |
+ |
+ // Then notify the RenderFrameHostManager so it can speculatively create a |
+ // RenderFrameHost (and potentially a new renderer process) in parallel. |
+ frame_tree_node->render_manager()->BeginNavigation(*navigation_request); |
} |
void NavigatorImpl::RecordNavigationMetrics( |