Chromium Code Reviews| 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) |
|
alexmos
2017/02/14 21:16:07
Note that I fall through instead of returning a ne
Charlie Reis
2017/02/28 00:57:53
Acknowledged.
|
| 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; |
| } |
| } |