| 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 6de0f24d8ae81b9428617f5287e1fd7fc76a9562..db0cf760cfc4157ccbf39a35869061d2f6cf3c87 100644
|
| --- a/content/browser/frame_host/render_frame_host_manager.cc
|
| +++ b/content/browser/frame_host/render_frame_host_manager.cc
|
| @@ -770,11 +770,15 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
|
| ? speculative_render_frame_host_->GetSiteInstance()
|
| : nullptr;
|
|
|
| + bool was_server_redirect = request.navigation_handle() &&
|
| + request.navigation_handle()->WasServerRedirect();
|
| +
|
| scoped_refptr<SiteInstance> dest_site_instance = GetSiteInstanceForNavigation(
|
| request.common_params().url, request.source_site_instance(),
|
| request.dest_site_instance(), candidate_site_instance,
|
| request.common_params().transition,
|
| - request.restore_type() != RestoreType::NONE, request.is_view_source());
|
| + request.restore_type() != RestoreType::NONE, request.is_view_source(),
|
| + was_server_redirect);
|
|
|
| // The appropriate RenderFrameHost to commit the navigation.
|
| RenderFrameHostImpl* navigation_rfh = nullptr;
|
| @@ -804,9 +808,9 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
|
| } else {
|
| // Subframe navigations will use the current renderer, unless specifically
|
| // allowed to swap processes.
|
| - no_renderer_swap |= !CanSubframeSwapProcess(request.common_params().url,
|
| - request.source_site_instance(),
|
| - request.dest_site_instance());
|
| + no_renderer_swap |= !CanSubframeSwapProcess(
|
| + request.common_params().url, request.source_site_instance(),
|
| + request.dest_site_instance(), was_server_redirect);
|
| }
|
|
|
| if (no_renderer_swap) {
|
| @@ -1217,7 +1221,8 @@ RenderFrameHostManager::GetSiteInstanceForNavigation(
|
| SiteInstance* candidate_instance,
|
| ui::PageTransition transition,
|
| bool dest_is_restore,
|
| - bool dest_is_view_source_mode) {
|
| + bool dest_is_view_source_mode,
|
| + bool was_server_redirect) {
|
| // On renderer-initiated navigations, when the frame initiating the navigation
|
| // and the frame being navigated differ, |source_instance| is set to the
|
| // SiteInstance of the initiating frame. |dest_instance| is present on session
|
| @@ -1257,7 +1262,8 @@ RenderFrameHostManager::GetSiteInstanceForNavigation(
|
| if (ShouldTransitionCrossSite() || force_swap) {
|
| new_instance_descriptor = DetermineSiteInstanceForURL(
|
| dest_url, source_instance, current_instance, dest_instance, transition,
|
| - dest_is_restore, dest_is_view_source_mode, force_swap);
|
| + dest_is_restore, dest_is_view_source_mode, force_swap,
|
| + was_server_redirect);
|
| }
|
|
|
| scoped_refptr<SiteInstance> new_instance =
|
| @@ -1285,7 +1291,8 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
|
| ui::PageTransition transition,
|
| bool dest_is_restore,
|
| bool dest_is_view_source_mode,
|
| - bool force_browsing_instance_swap) {
|
| + bool force_browsing_instance_swap,
|
| + bool was_server_redirect) {
|
| SiteInstanceImpl* current_instance_impl =
|
| static_cast<SiteInstanceImpl*>(current_instance);
|
| NavigationControllerImpl& controller =
|
| @@ -1442,12 +1449,20 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
|
| // Use the source SiteInstance in case of data URLs, about:srcdoc pages and
|
| // about:blank pages because the content is then controlled and/or scriptable
|
| // by the source SiteInstance.
|
| + //
|
| + // One exception to this is when these URLs are
|
| + // reached via a server redirect. Normally, redirects to data: or about:
|
| + // URLs are disallowed as net::ERR_UNSAFE_REDIRECT, but extensions can still
|
| + // redirect arbitary requests to those URLs using webRequest or
|
| + // declarativeWebRequest API. For these cases, the content isn't controlled
|
| + // by the source SiteInstance, so it need not use it.
|
| GURL about_blank(url::kAboutBlankURL);
|
| GURL about_srcdoc(content::kAboutSrcDocURL);
|
| - if (source_instance && (dest_url == about_srcdoc || dest_url == about_blank ||
|
| - dest_url.scheme() == url::kDataScheme)) {
|
| + bool dest_is_data_or_about = dest_url == about_srcdoc ||
|
| + dest_url == about_blank ||
|
| + dest_url.scheme() == url::kDataScheme;
|
| + if (source_instance && dest_is_data_or_about && !was_server_redirect)
|
| return SiteInstanceDescriptor(source_instance);
|
| - }
|
|
|
| // Use the current SiteInstance for same site navigations.
|
| if (IsCurrentlySameSite(render_frame_host_.get(), dest_url))
|
| @@ -2305,17 +2320,12 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
|
| const GlobalRequestID& transferred_request_id,
|
| int bindings,
|
| bool is_reload) {
|
| - if (!frame_tree_node_->IsMainFrame() &&
|
| - !CanSubframeSwapProcess(dest_url, source_instance, dest_instance)) {
|
| - // Note: Do not add code here to determine whether the subframe should swap
|
| - // or not. Add it to CanSubframeSwapProcess instead.
|
| - return render_frame_host_.get();
|
| - }
|
| -
|
| SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
|
| + bool was_server_redirect = transfer_navigation_handle_ &&
|
| + transfer_navigation_handle_->WasServerRedirect();
|
| scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
|
| dest_url, source_instance, dest_instance, nullptr, transition,
|
| - dest_is_restore, dest_is_view_source_mode);
|
| + dest_is_restore, dest_is_view_source_mode, was_server_redirect);
|
|
|
| // Inform the transferring NavigationHandle of a transfer to a different
|
| // SiteInstance. It is important do so now, in order to mark the request as
|
| @@ -2345,7 +2355,14 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
|
| }
|
| }
|
|
|
| - if (new_instance.get() != current_instance) {
|
| + // Note: Do not add code here to determine whether the subframe should swap
|
| + // or not. Add it to CanSubframeSwapProcess instead.
|
| + bool allowed_to_swap_process =
|
| + frame_tree_node_->IsMainFrame() ||
|
| + CanSubframeSwapProcess(dest_url, source_instance, dest_instance,
|
| + was_server_redirect);
|
| +
|
| + if (new_instance.get() != current_instance && allowed_to_swap_process) {
|
| TRACE_EVENT_INSTANT2(
|
| "navigation",
|
| "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance",
|
| @@ -2748,7 +2765,8 @@ void RenderFrameHostManager::SendPageMessage(IPC::Message* msg,
|
| bool RenderFrameHostManager::CanSubframeSwapProcess(
|
| const GURL& dest_url,
|
| SiteInstance* source_instance,
|
| - SiteInstance* dest_instance) {
|
| + SiteInstance* dest_instance,
|
| + bool was_server_redirect) {
|
| // On renderer-initiated navigations, when the frame initiating the navigation
|
| // and the frame being navigated differ, |source_instance| is set to the
|
| // SiteInstance of the initiating frame. |dest_instance| is present on session
|
| @@ -2770,8 +2788,22 @@ bool RenderFrameHostManager::CanSubframeSwapProcess(
|
| resolved_url = dest_instance->GetSiteURL();
|
| } else {
|
| // If there is no SiteInstance this unique origin can be associated with,
|
| - // then we should avoid a process swap.
|
| - return false;
|
| + // there are two cases:
|
| + // (1) If there was a server redirect, allow a process swap. Normally,
|
| + // redirects to data: or about: URLs are disallowed as
|
| + // net::ERR_UNSAFE_REDIRECT. However, extensions can still redirect
|
| + // arbitary requests to those URLs using the chrome.webRequest or
|
| + // chrome.declarativeWebRequest API, which will end up here (for an
|
| + // example, see ExtensionWebRequestApiTest.WebRequestDeclarative1). It's
|
| + // safest to swap processes for those redirects if we are in an
|
| + // appropriate OOPIF-enabled mode.
|
| + //
|
| + // (2) Otherwise, avoid a process swap. We can get here during session
|
| + // restore, and this avoids putting all data: and about:blank subframes
|
| + // in OOPIFs. We can also get here in tests with browser-initiated
|
| + // subframe navigations (NavigateFrameToURL).
|
| + if (!was_server_redirect)
|
| + return false;
|
| }
|
| }
|
|
|
|
|