Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/frame_host/render_frame_host_manager.h" | 5 #include "content/browser/frame_host/render_frame_host_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 797 render_frame_host_->IsRenderFrameLive() && | 797 render_frame_host_->IsRenderFrameLive() && |
| 798 ShouldMakeNetworkRequestForURL(request.common_params().url) && | 798 ShouldMakeNetworkRequestForURL(request.common_params().url) && |
| 799 IsRendererTransferNeededForNavigation(render_frame_host_.get(), | 799 IsRendererTransferNeededForNavigation(render_frame_host_.get(), |
| 800 request.common_params().url); | 800 request.common_params().url); |
| 801 | 801 |
| 802 no_renderer_swap |= | 802 no_renderer_swap |= |
| 803 !request.may_transfer() && !can_renderer_initiate_transfer; | 803 !request.may_transfer() && !can_renderer_initiate_transfer; |
| 804 } else { | 804 } else { |
| 805 // Subframe navigations will use the current renderer, unless specifically | 805 // Subframe navigations will use the current renderer, unless specifically |
| 806 // allowed to swap processes. | 806 // allowed to swap processes. |
| 807 no_renderer_swap |= !CanSubframeSwapProcess(request.common_params().url, | 807 no_renderer_swap |= !CanSubframeSwapProcess( |
| 808 request.source_site_instance(), | 808 request.common_params().url, request.source_site_instance(), |
| 809 request.dest_site_instance()); | 809 request.dest_site_instance(), false); |
|
Charlie Reis
2017/02/02 22:40:46
I think we might have a problem here for PlzNaviga
alexmos
2017/02/14 21:16:06
Yes, getting this working with PlzNavigate needed
Charlie Reis
2017/02/28 00:57:52
Yes, that sounds like the right thing to do. Than
| |
| 810 } | 810 } |
| 811 | 811 |
| 812 if (no_renderer_swap) { | 812 if (no_renderer_swap) { |
| 813 // GetFrameHostForNavigation will be called more than once during a | 813 // GetFrameHostForNavigation will be called more than once during a |
| 814 // navigation (currently twice, on request and when it's about to commit in | 814 // navigation (currently twice, on request and when it's about to commit in |
| 815 // the renderer). In the follow up calls an existing pending WebUI should | 815 // the renderer). In the follow up calls an existing pending WebUI should |
| 816 // not be recreated if the URL didn't change. So instead of calling | 816 // not be recreated if the URL didn't change. So instead of calling |
| 817 // CleanUpNavigation just discard the speculative RenderFrameHost if one | 817 // CleanUpNavigation just discard the speculative RenderFrameHost if one |
| 818 // exists. | 818 // exists. |
| 819 if (speculative_render_frame_host_) | 819 if (speculative_render_frame_host_) |
| (...skipping 1459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2279 RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate( | 2279 RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate( |
| 2280 const GURL& dest_url, | 2280 const GURL& dest_url, |
| 2281 SiteInstance* source_instance, | 2281 SiteInstance* source_instance, |
| 2282 SiteInstance* dest_instance, | 2282 SiteInstance* dest_instance, |
| 2283 ui::PageTransition transition, | 2283 ui::PageTransition transition, |
| 2284 bool dest_is_restore, | 2284 bool dest_is_restore, |
| 2285 bool dest_is_view_source_mode, | 2285 bool dest_is_view_source_mode, |
| 2286 const GlobalRequestID& transferred_request_id, | 2286 const GlobalRequestID& transferred_request_id, |
| 2287 int bindings, | 2287 int bindings, |
| 2288 bool is_reload) { | 2288 bool is_reload) { |
| 2289 if (!frame_tree_node_->IsMainFrame() && | |
| 2290 !CanSubframeSwapProcess(dest_url, source_instance, dest_instance)) { | |
| 2291 // Note: Do not add code here to determine whether the subframe should swap | |
| 2292 // or not. Add it to CanSubframeSwapProcess instead. | |
| 2293 return render_frame_host_.get(); | |
| 2294 } | |
| 2295 | |
| 2296 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); | 2289 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
| 2297 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( | 2290 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( |
| 2298 dest_url, source_instance, dest_instance, nullptr, transition, | 2291 dest_url, source_instance, dest_instance, nullptr, transition, |
| 2299 dest_is_restore, dest_is_view_source_mode); | 2292 dest_is_restore, dest_is_view_source_mode); |
| 2300 | 2293 |
| 2301 // Inform the transferring NavigationHandle of a transfer to a different | 2294 // Inform the transferring NavigationHandle of a transfer to a different |
| 2302 // SiteInstance. It is important do so now, in order to mark the request as | 2295 // SiteInstance. It is important do so now, in order to mark the request as |
| 2303 // transferring on the IO thread before attempting to destroy the pending RFH. | 2296 // transferring on the IO thread before attempting to destroy the pending RFH. |
| 2304 // This ensures the network request will not be destroyed along the pending | 2297 // This ensures the network request will not be destroyed along the pending |
| 2305 // RFH but will persist until it is picked up by the new RFH. | 2298 // RFH but will persist until it is picked up by the new RFH. |
| 2306 if (transfer_navigation_handle_.get() && | 2299 bool dest_is_transfer = transfer_navigation_handle_.get() && |
| 2307 transfer_navigation_handle_->GetGlobalRequestID() == | 2300 transfer_navigation_handle_->GetGlobalRequestID() == |
| 2308 transferred_request_id && | 2301 transferred_request_id; |
| 2302 if (dest_is_transfer && | |
| 2309 new_instance.get() != | 2303 new_instance.get() != |
| 2310 transfer_navigation_handle_->GetRenderFrameHost() | 2304 transfer_navigation_handle_->GetRenderFrameHost() |
| 2311 ->GetSiteInstance()) { | 2305 ->GetSiteInstance()) { |
| 2312 transfer_navigation_handle_->Transfer(); | 2306 transfer_navigation_handle_->Transfer(); |
| 2313 } | 2307 } |
| 2314 | 2308 |
| 2315 // If we are currently navigating cross-process to a pending RFH for a | 2309 // If we are currently navigating cross-process to a pending RFH for a |
| 2316 // different SiteInstance, we want to get back to normal and then navigate as | 2310 // different SiteInstance, we want to get back to normal and then navigate as |
| 2317 // usual. We will reuse the pending RFH below if it matches the destination | 2311 // usual. We will reuse the pending RFH below if it matches the destination |
| 2318 // SiteInstance. | 2312 // SiteInstance. |
| 2319 if (pending_render_frame_host_) { | 2313 if (pending_render_frame_host_) { |
| 2320 if (pending_render_frame_host_->GetSiteInstance() != new_instance) { | 2314 if (pending_render_frame_host_->GetSiteInstance() != new_instance) { |
| 2321 CancelPending(); | 2315 CancelPending(); |
| 2322 } else { | 2316 } else { |
| 2323 // When a pending RFH is reused, it should always be live, since it is | 2317 // When a pending RFH is reused, it should always be live, since it is |
| 2324 // cleared whenever a process dies. | 2318 // cleared whenever a process dies. |
| 2325 CHECK(pending_render_frame_host_->IsRenderFrameLive()); | 2319 CHECK(pending_render_frame_host_->IsRenderFrameLive()); |
| 2326 } | 2320 } |
| 2327 } | 2321 } |
| 2328 | 2322 |
| 2329 if (new_instance.get() != current_instance) { | 2323 // Note: Do not add code here to determine whether the subframe should swap |
| 2324 // or not. Add it to CanSubframeSwapProcess instead. | |
| 2325 bool allowed_to_swap_process = | |
|
alexmos
2017/01/25 22:30:55
I turned this into a flag so that there's just one
Charlie Reis
2017/02/02 22:40:46
Acknowledged.
| |
| 2326 frame_tree_node_->IsMainFrame() || | |
| 2327 CanSubframeSwapProcess(dest_url, source_instance, dest_instance, | |
| 2328 dest_is_transfer); | |
| 2329 | |
| 2330 if (new_instance.get() != current_instance && allowed_to_swap_process) { | |
| 2330 TRACE_EVENT_INSTANT2( | 2331 TRACE_EVENT_INSTANT2( |
| 2331 "navigation", | 2332 "navigation", |
| 2332 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", | 2333 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", |
| 2333 TRACE_EVENT_SCOPE_THREAD, | 2334 TRACE_EVENT_SCOPE_THREAD, |
| 2334 "current_instance id", current_instance->GetId(), | 2335 "current_instance id", current_instance->GetId(), |
| 2335 "new_instance id", new_instance->GetId()); | 2336 "new_instance id", new_instance->GetId()); |
| 2336 | 2337 |
| 2337 // New SiteInstance: create a pending RFH to navigate. | 2338 // New SiteInstance: create a pending RFH to navigate. |
| 2338 | 2339 |
| 2339 if (!pending_render_frame_host_) | 2340 if (!pending_render_frame_host_) |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2396 // | 2397 // |
| 2397 // Also make sure the old RenderFrame stops, in case a load is in | 2398 // Also make sure the old RenderFrame stops, in case a load is in |
| 2398 // progress. (We don't want to do this for transfers, since it will | 2399 // progress. (We don't want to do this for transfers, since it will |
| 2399 // interrupt the transfer with an unexpected DidStopLoading.) | 2400 // interrupt the transfer with an unexpected DidStopLoading.) |
| 2400 render_frame_host_->Send(new FrameMsg_Stop( | 2401 render_frame_host_->Send(new FrameMsg_Stop( |
| 2401 render_frame_host_->GetRoutingID())); | 2402 render_frame_host_->GetRoutingID())); |
| 2402 pending_render_frame_host_->SetNavigationsSuspended(true, | 2403 pending_render_frame_host_->SetNavigationsSuspended(true, |
| 2403 base::TimeTicks()); | 2404 base::TimeTicks()); |
| 2404 render_frame_host_->DispatchBeforeUnload(true, is_reload); | 2405 render_frame_host_->DispatchBeforeUnload(true, is_reload); |
| 2405 } | 2406 } |
| 2406 | |
|
Charlie Reis
2017/02/02 22:40:46
nit: Let's avoid this churn.
alexmos
2017/02/14 21:16:06
Done.
| |
| 2407 return pending_render_frame_host_.get(); | 2407 return pending_render_frame_host_.get(); |
| 2408 } | 2408 } |
| 2409 | 2409 |
| 2410 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_. | 2410 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_. |
| 2411 | 2411 |
| 2412 // It's possible to swap out the current RFH and then decide to navigate in it | 2412 // It's possible to swap out the current RFH and then decide to navigate in it |
| 2413 // anyway (e.g., a cross-process navigation that redirects back to the | 2413 // anyway (e.g., a cross-process navigation that redirects back to the |
| 2414 // original site). In that case, we have a proxy for the current RFH but | 2414 // original site). In that case, we have a proxy for the current RFH but |
| 2415 // haven't deleted it yet. The new navigation will swap it back in, so we can | 2415 // haven't deleted it yet. The new navigation will swap it back in, so we can |
| 2416 // delete the proxy. | 2416 // delete the proxy. |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2722 msg->set_routing_id(render_frame_host_->GetRoutingID()); | 2722 msg->set_routing_id(render_frame_host_->GetRoutingID()); |
| 2723 render_frame_host_->Send(msg); | 2723 render_frame_host_->Send(msg); |
| 2724 } else { | 2724 } else { |
| 2725 delete msg; | 2725 delete msg; |
| 2726 } | 2726 } |
| 2727 } | 2727 } |
| 2728 | 2728 |
| 2729 bool RenderFrameHostManager::CanSubframeSwapProcess( | 2729 bool RenderFrameHostManager::CanSubframeSwapProcess( |
| 2730 const GURL& dest_url, | 2730 const GURL& dest_url, |
| 2731 SiteInstance* source_instance, | 2731 SiteInstance* source_instance, |
| 2732 SiteInstance* dest_instance) { | 2732 SiteInstance* dest_instance, |
| 2733 bool for_transfer) { | |
| 2733 // On renderer-initiated navigations, when the frame initiating the navigation | 2734 // On renderer-initiated navigations, when the frame initiating the navigation |
| 2734 // and the frame being navigated differ, |source_instance| is set to the | 2735 // and the frame being navigated differ, |source_instance| is set to the |
| 2735 // SiteInstance of the initiating frame. |dest_instance| is present on session | 2736 // SiteInstance of the initiating frame. |dest_instance| is present on session |
| 2736 // history navigations. The two cannot be set simultaneously. | 2737 // history navigations. The two cannot be set simultaneously. |
| 2737 DCHECK(!source_instance || !dest_instance); | 2738 DCHECK(!source_instance || !dest_instance); |
| 2738 | 2739 |
| 2739 // Don't swap for subframes unless we are in an OOPIF-enabled mode. We can | 2740 // Don't swap for subframes unless we are in an OOPIF-enabled mode. We can |
| 2740 // get here in tests for subframes (e.g., NavigateFrameToURL). | 2741 // get here in tests for subframes (e.g., NavigateFrameToURL). |
| 2741 if (!SiteIsolationPolicy::AreCrossProcessFramesPossible()) | 2742 if (!SiteIsolationPolicy::AreCrossProcessFramesPossible()) |
| 2742 return false; | 2743 return false; |
| 2743 | 2744 |
| 2744 // If dest_url is a unique origin like about:blank, then the need for a swap | 2745 // If dest_url is a unique origin like about:blank, then the need for a swap |
| 2745 // is determined by the source_instance or dest_instance. | 2746 // is determined by the source_instance or dest_instance. |
| 2746 GURL resolved_url = dest_url; | 2747 GURL resolved_url = dest_url; |
| 2747 if (url::Origin(resolved_url).unique()) { | 2748 if (url::Origin(resolved_url).unique()) { |
| 2748 if (source_instance) { | 2749 if (source_instance) { |
| 2749 resolved_url = source_instance->GetSiteURL(); | 2750 resolved_url = source_instance->GetSiteURL(); |
| 2750 } else if (dest_instance) { | 2751 } else if (dest_instance) { |
| 2751 resolved_url = dest_instance->GetSiteURL(); | 2752 resolved_url = dest_instance->GetSiteURL(); |
| 2752 } else { | 2753 } else { |
| 2753 // If there is no SiteInstance this unique origin can be associated with, | 2754 // If there is no SiteInstance this unique origin can be associated with, |
| 2754 // then we should avoid a process swap. | 2755 // there are two cases: |
| 2755 return false; | 2756 // |
| 2757 // (1) If we are in a transfer, allow a process swap. Normally, | |
| 2758 // redirects to data: or about: URLs are disallowed as | |
| 2759 // net::ERR_UNSAFE_REDIRECT. However, extensions can still redirect | |
| 2760 // arbitary requests to those URLs using the chrome.declarativeWebRequest | |
| 2761 // API, which will end up here (for an example, see | |
| 2762 // ExtensionWebRequestApiTest.WebRequestDeclarative1). It's safest to | |
|
alexmos
2017/01/25 22:30:55
For reference, here's where these redirects are pe
Charlie Reis
2017/02/02 22:40:46
Interesting! I did just hear Devlin mention that
alexmos
2017/02/14 21:16:06
Unfortunately, this is a problem for regular webRe
| |
| 2763 // swap processes for those redirects if we are in an appropriate | |
| 2764 // OOPIF-enabled mode. | |
|
Charlie Reis
2017/02/02 22:40:46
Sounds like we want this to return true for these
alexmos
2017/02/14 21:16:06
Yes, for instance we don't want to return true her
| |
| 2765 // | |
| 2766 // (2) If we are not in a transfer, avoid a process swap. We can get | |
| 2767 // here during session restore, and this avoids putting all data: and | |
| 2768 // about:blank subframes in OOPIFs. We can also get here in tests with | |
| 2769 // browser-initiated subframe navigations (NavigateFrameToURL). | |
| 2770 if (!for_transfer) | |
|
alexmos
2017/01/25 22:30:55
I don't know if passing in this as a flag is stric
Charlie Reis
2017/02/02 22:40:46
(See my earlier question about PlzNavigate.)
| |
| 2771 return false; | |
| 2756 } | 2772 } |
| 2757 } | 2773 } |
| 2758 | 2774 |
| 2759 // If we are in an OOPIF mode that only applies to some sites, only swap if | 2775 // If we are in an OOPIF mode that only applies to some sites, only swap if |
| 2760 // the policy determines that a transfer would have been needed. We can get | 2776 // the policy determines that a transfer would have been needed. We can get |
| 2761 // here for session restore. | 2777 // here for session restore. |
| 2762 if (!IsRendererTransferNeededForNavigation(render_frame_host_.get(), | 2778 if (!IsRendererTransferNeededForNavigation(render_frame_host_.get(), |
| 2763 resolved_url)) { | 2779 resolved_url)) { |
| 2764 DCHECK(!dest_instance || | 2780 DCHECK(!dest_instance || |
| 2765 dest_instance == render_frame_host_->GetSiteInstance()); | 2781 dest_instance == render_frame_host_->GetSiteInstance()); |
| 2766 return false; | 2782 return false; |
| 2767 } | 2783 } |
| 2768 | 2784 |
| 2769 return true; | 2785 return true; |
| 2770 } | 2786 } |
| 2771 | 2787 |
| 2772 } // namespace content | 2788 } // namespace content |
| OLD | NEW |