Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(204)

Side by Side Diff: content/browser/frame_host/render_frame_host_manager.cc

Issue 2636193003: Fix cross-site subframe navigations that transfer back to original RFH. (Closed)
Patch Set: Try #3 Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/frame_host/render_frame_host_manager.h ('k') | content/browser/site_per_process_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698