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

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

Issue 701953006: PlzNavigate: Speculatively spawns a renderer process for navigations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed CR comments. Created 5 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 <utility> 7 #include <utility>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 RenderFrameHostDelegate* render_frame_delegate, 53 RenderFrameHostDelegate* render_frame_delegate,
54 RenderViewHostDelegate* render_view_delegate, 54 RenderViewHostDelegate* render_view_delegate,
55 RenderWidgetHostDelegate* render_widget_delegate, 55 RenderWidgetHostDelegate* render_widget_delegate,
56 Delegate* delegate) 56 Delegate* delegate)
57 : frame_tree_node_(frame_tree_node), 57 : frame_tree_node_(frame_tree_node),
58 delegate_(delegate), 58 delegate_(delegate),
59 cross_navigation_pending_(false), 59 cross_navigation_pending_(false),
60 render_frame_delegate_(render_frame_delegate), 60 render_frame_delegate_(render_frame_delegate),
61 render_view_delegate_(render_view_delegate), 61 render_view_delegate_(render_view_delegate),
62 render_widget_delegate_(render_widget_delegate), 62 render_widget_delegate_(render_widget_delegate),
63 interstitial_page_(NULL), 63 interstitial_page_(nullptr),
64 should_reuse_web_ui_(false),
64 weak_factory_(this) { 65 weak_factory_(this) {
65 DCHECK(frame_tree_node_); 66 DCHECK(frame_tree_node_);
66 } 67 }
67 68
68 RenderFrameHostManager::~RenderFrameHostManager() { 69 RenderFrameHostManager::~RenderFrameHostManager() {
69 if (pending_render_frame_host_) 70 if (pending_render_frame_host_)
70 UnsetPendingRenderFrameHost(); 71 UnsetPendingRenderFrameHost();
71 72
73 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
74 switches::kEnableBrowserSideNavigation)) {
75 UnsetSpeculativeRenderFrameHost();
76 }
77
72 if (render_frame_host_ && 78 if (render_frame_host_ &&
73 render_frame_host_->GetSiteInstance()->active_frame_count() <= 1U) { 79 render_frame_host_->GetSiteInstance()->active_frame_count() <= 1U) {
74 ShutdownRenderFrameProxyHostsInSiteInstance( 80 ShutdownRenderFrameProxyHostsInSiteInstance(
75 render_frame_host_->GetSiteInstance()->GetId()); 81 render_frame_host_->GetSiteInstance()->GetId());
76 } 82 }
77 83
78 // We should always have a current RenderFrameHost except in some tests. 84 // We should always have a current RenderFrameHost except in some tests.
79 SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>()); 85 SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>());
80 86
81 // Delete any swapped out RenderFrameHosts. 87 // Delete any swapped out RenderFrameHosts.
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 } 291 }
286 } 292 }
287 return false; 293 return false;
288 } 294 }
289 295
290 void RenderFrameHostManager::OnBeforeUnloadACK( 296 void RenderFrameHostManager::OnBeforeUnloadACK(
291 bool for_cross_site_transition, 297 bool for_cross_site_transition,
292 bool proceed, 298 bool proceed,
293 const base::TimeTicks& proceed_time) { 299 const base::TimeTicks& proceed_time) {
294 if (for_cross_site_transition) { 300 if (for_cross_site_transition) {
301 DCHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
302 switches::kEnableBrowserSideNavigation));
295 // Ignore if we're not in a cross-site navigation. 303 // Ignore if we're not in a cross-site navigation.
296 if (!cross_navigation_pending_) 304 if (!cross_navigation_pending_)
297 return; 305 return;
298 306
299 if (proceed) { 307 if (proceed) {
300 // Ok to unload the current page, so proceed with the cross-site 308 // Ok to unload the current page, so proceed with the cross-site
301 // navigation. Note that if navigations are not currently suspended, it 309 // navigation. Note that if navigations are not currently suspended, it
302 // might be because the renderer was deemed unresponsive and this call was 310 // might be because the renderer was deemed unresponsive and this call was
303 // already made by ShouldCloseTabOnUnresponsiveRenderer. In that case, it 311 // already made by ShouldCloseTabOnUnresponsiveRenderer. In that case, it
304 // is ok to do nothing here. 312 // is ok to do nothing here.
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 418
411 response_started_id_.reset(); 419 response_started_id_.reset();
412 } 420 }
413 421
414 void RenderFrameHostManager::ClearNavigationTransitionData() { 422 void RenderFrameHostManager::ClearNavigationTransitionData() {
415 render_frame_host_->ClearPendingTransitionRequestData(); 423 render_frame_host_->ClearPendingTransitionRequestData();
416 } 424 }
417 425
418 void RenderFrameHostManager::DidNavigateFrame( 426 void RenderFrameHostManager::DidNavigateFrame(
419 RenderFrameHostImpl* render_frame_host, 427 RenderFrameHostImpl* render_frame_host,
420 bool was_caused_by_user_gesture) { 428 bool was_caused_by_user_gesture,
429 bool was_within_same_page) {
430 DCHECK(render_frame_host);
431 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
432 switches::kEnableBrowserSideNavigation)) {
433 if (render_frame_host == speculative_render_frame_host_.get()) {
434 CommitPending();
435 } else if (render_frame_host == render_frame_host_.get()) {
436 DCHECK(was_within_same_page || !speculative_render_frame_host_);
437 // TODO(carlosk): if both |was_within_same_page| and
438 // |was_caused_by_user_gesture| are true properly cancel a possible
439 // ongoing navigation request.
440 } else {
441 // No one else should be sending us a DidNavigate in this state.
442 DCHECK(false);
443 }
444 DCHECK(!speculative_render_frame_host_);
445 return;
446 }
447
421 if (!cross_navigation_pending_) { 448 if (!cross_navigation_pending_) {
422 DCHECK(!pending_render_frame_host_); 449 DCHECK(!pending_render_frame_host_);
423 450
424 // We should only hear this from our current renderer. 451 // We should only hear this from our current renderer.
425 DCHECK_EQ(render_frame_host_, render_frame_host); 452 DCHECK_EQ(render_frame_host_, render_frame_host);
426 453
427 // Even when there is no pending RVH, there may be a pending Web UI. 454 // Even when there is no pending RVH, there may be a pending Web UI.
428 if (pending_web_ui()) 455 if (pending_web_ui())
429 CommitPending(); 456 CommitPending();
430 return; 457 return;
431 } 458 }
432 459
433 if (render_frame_host == pending_render_frame_host_) { 460 if (render_frame_host == pending_render_frame_host_) {
434 // The pending cross-site navigation completed, so show the renderer. 461 // The pending cross-site navigation completed, so show the renderer.
435 CommitPending(); 462 CommitPending();
436 cross_navigation_pending_ = false; 463 cross_navigation_pending_ = false;
437 } else if (render_frame_host == render_frame_host_) { 464 } else if (render_frame_host == render_frame_host_) {
438 if (was_caused_by_user_gesture) { 465 if (was_caused_by_user_gesture) {
439 // A navigation in the original page has taken place. Cancel the pending 466 // A navigation in the original page has taken place. Cancel the pending
440 // one. Only do it for user gesture originated navigations to prevent 467 // one. Only do it for user gesture originated navigations to prevent
441 // page doing any shenanigans to prevent user from navigating. 468 // page doing any shenanigans to prevent user from navigating.
442 // See https://code.google.com/p/chromium/issues/detail?id=75195 469 // See https://crbug.com/75195.
443 CancelPending(); 470 CancelPending();
444 cross_navigation_pending_ = false; 471 cross_navigation_pending_ = false;
445 } 472 }
446 } else { 473 } else {
447 // No one else should be sending us DidNavigate in this state. 474 // No one else should be sending us DidNavigate in this state.
448 DCHECK(false); 475 DCHECK(false);
449 } 476 }
450 } 477 }
451 478
452 void RenderFrameHostManager::DidDisownOpener( 479 void RenderFrameHostManager::DidDisownOpener(
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 // If the SiteInstance for the pending RFH is being used by others don't 598 // If the SiteInstance for the pending RFH is being used by others don't
572 // delete the RFH. Just swap it out and it can be reused at a later point. 599 // delete the RFH. Just swap it out and it can be reused at a later point.
573 SiteInstanceImpl* site_instance = render_frame_host->GetSiteInstance(); 600 SiteInstanceImpl* site_instance = render_frame_host->GetSiteInstance();
574 if (site_instance->HasSite() && site_instance->active_frame_count() > 1) { 601 if (site_instance->HasSite() && site_instance->active_frame_count() > 1) {
575 // Any currently suspended navigations are no longer needed. 602 // Any currently suspended navigations are no longer needed.
576 render_frame_host->CancelSuspendedNavigations(); 603 render_frame_host->CancelSuspendedNavigations();
577 604
578 RenderFrameProxyHost* proxy = 605 RenderFrameProxyHost* proxy =
579 new RenderFrameProxyHost(site_instance, frame_tree_node_); 606 new RenderFrameProxyHost(site_instance, frame_tree_node_);
580 proxy_hosts_[site_instance->GetId()] = proxy; 607 proxy_hosts_[site_instance->GetId()] = proxy;
581 render_frame_host->SwapOut(proxy, false); 608
609 // As the RenderFrameHost might already be swapped out, check if that is
610 // the case to avoid swapping it out again.
611 if (!render_frame_host->is_swapped_out())
612 render_frame_host->SwapOut(proxy, false);
613
582 if (frame_tree_node_->IsMainFrame()) 614 if (frame_tree_node_->IsMainFrame())
583 proxy->TakeFrameHostOwnership(render_frame_host.Pass()); 615 proxy->TakeFrameHostOwnership(render_frame_host.Pass());
584 } else { 616 } else {
585 // We won't be coming back, so delete this one. 617 // We won't be coming back, so delete this one.
586 render_frame_host.reset(); 618 render_frame_host.reset();
587 } 619 }
588 } 620 }
589 621
590 void RenderFrameHostManager::MoveToPendingDeleteHosts( 622 void RenderFrameHostManager::MoveToPendingDeleteHosts(
591 scoped_ptr<RenderFrameHostImpl> render_frame_host) { 623 scoped_ptr<RenderFrameHostImpl> render_frame_host) {
(...skipping 24 matching lines...) Expand all
616 } 648 }
617 } 649 }
618 return false; 650 return false;
619 } 651 }
620 652
621 void RenderFrameHostManager::ResetProxyHosts() { 653 void RenderFrameHostManager::ResetProxyHosts() {
622 STLDeleteValues(&proxy_hosts_); 654 STLDeleteValues(&proxy_hosts_);
623 } 655 }
624 656
625 // PlzNavigate 657 // PlzNavigate
626 RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation( 658 void RenderFrameHostManager::BeginNavigation(
627 const GURL& url, 659 const CommonNavigationParams& common_params) {
628 ui::PageTransition transition) {
629 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 660 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
630 switches::kEnableBrowserSideNavigation)); 661 switches::kEnableBrowserSideNavigation));
631 // TODO(clamy): When we handle renderer initiated navigations, make sure not 662 // Cleans up any state in case there's an ongoing navigation.
632 // to use a different process for subframes if --site-per-process is not 663 // TODO(carlosk): remove this cleanup here once we properly cancel ongoing
633 // enabled. 664 // navigations.
665 CleanUpNavigation();
634 666
667 RenderFrameHostImpl* future_rfh =
668 SelectFrameHostForNavigation(common_params.url, common_params.transition);
669 DCHECK(future_rfh);
670 }
671
672 // PlzNavigate
673 RenderFrameHostImpl* RenderFrameHostManager::SelectFrameHostForNavigation(
674 const GURL& url,
675 ui::PageTransition transition) {
676 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
677 switches::kEnableBrowserSideNavigation));
635 // Pick the right RenderFrameHost to commit the navigation. 678 // Pick the right RenderFrameHost to commit the navigation.
636 // TODO(clamy): Replace the default values by the right ones. 679 RenderFrameHostImpl* rfh_for_navigation = nullptr;
637 RenderFrameHostImpl* render_frame_host = UpdateStateForNavigate(
638 url, nullptr, nullptr, transition, false, false, GlobalRequestID(),
639 NavigationEntryImpl::kInvalidBindings);
640 680
641 // If the renderer that needs to navigate is not live (it was just created or 681 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
642 // it crashed), initialize it. 682 // TODO(carlosk): Replace the default values with the right ones for
nasko 2015/01/06 00:03:18 nit: empty line before the TODO
carlosk 2015/01/08 16:05:56 Done.
643 if (!render_frame_host->render_view_host()->IsRenderViewLive()) { 683 // source_instance, dest_instance, dest_is_restore, dest_is_view_source_mode.
684 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
685 url, nullptr, nullptr, transition, false, false);
686
687 // TODO(carlosk): do not swap processes for renderer initiated navigations
688 // (see crbug.com/440266).
689 if (current_instance == new_instance.get() ||
690 (!frame_tree_node_->IsMainFrame() &&
691 !base::CommandLine::ForCurrentProcess()->HasSwitch(
692 switches::kSitePerProcess))) {
693 // Will reuse the current RFH if its SiteInstance matches the new one from
694 // the navigation or if this is a subframe navigation. If --site-per-process
695 // is enabled the RFH is never kept when sites don't match.
696 CleanUpNavigation();
697 rfh_for_navigation = render_frame_host_.get();
698 } else {
699 // If the SiteInstance for the final URL doesn't match the one from the
700 // speculatively created RenderFrameHost, create a new RenderFrameHost using
701 // this new SiteInstance.
702 if (!speculative_render_frame_host_ ||
703 speculative_render_frame_host_->GetSiteInstance() !=
704 new_instance.get()) {
705 CleanUpNavigation();
706 // TODO(carlosk): Replace the binding value with the right one.
707 bool success = CreateSpeculativeRenderFrameHost(
708 url, current_instance, new_instance.get(),
709 NavigationEntryImpl::kInvalidBindings);
710 DCHECK(success);
711 }
712 DCHECK(speculative_render_frame_host_);
713 rfh_for_navigation = speculative_render_frame_host_.get();
714 }
715 DCHECK(rfh_for_navigation);
716
717 // If the renderer that needs to navigate is not live (it was just created
718 // or it crashed), initialize it.
719 if (!rfh_for_navigation->render_view_host()->IsRenderViewLive()) {
644 // Recreate the opener chain. 720 // Recreate the opener chain.
645 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager( 721 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
646 render_frame_host->GetSiteInstance()); 722 rfh_for_navigation->GetSiteInstance());
647 if (!InitRenderView(render_frame_host->render_view_host(), 723 if (!InitRenderView(rfh_for_navigation->render_view_host(), opener_route_id,
648 opener_route_id, 724 MSG_ROUTING_NONE, frame_tree_node_->IsMainFrame())) {
649 MSG_ROUTING_NONE,
650 frame_tree_node_->IsMainFrame())) {
651 return nullptr; 725 return nullptr;
652 } 726 }
653 } 727 }
nasko 2015/01/06 00:03:18 Don't we need to initialize the RenderFrame if it
carlosk 2015/01/08 16:05:55 I'm not sure of what you mean. Is that the rendere
nasko 2015/01/08 23:36:37 There are two objects - RenderFrameHost, which is
carlosk 2015/01/09 14:48:52 Yes, thanks for explaining. That's what I was refe
nasko 2015/01/09 18:13:07 No need to do anything extra here.
654 return render_frame_host; 728
729 DCHECK(new_instance->GetProcess()->HasConnection());
nasko 2015/01/06 00:03:17 What's the goal of this DCHECK?
carlosk 2015/01/08 16:05:55 I understand this checks for a connection with an
nasko 2015/01/08 23:36:37 Process creation is asynchronous, so you shouldn't
carlosk 2015/01/09 14:48:52 It's a check that already happens in this whole pr
nasko 2015/01/09 18:13:07 If it is already done, then why keep it here? The
carlosk 2015/01/12 14:35:25 Ack and done.
730 return rfh_for_navigation;
731 }
732
733 // PlzNavigate
734 void RenderFrameHostManager::CleanUpNavigation() {
735 scoped_ptr<RenderFrameHostImpl> rfh = UnsetSpeculativeRenderFrameHost();
736 if (rfh)
737 DiscardUnusedFrame(rfh.Pass());
738 }
739
740 // PlzNavigate
741 scoped_ptr<RenderFrameHostImpl>
742 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() {
743 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
744 switches::kEnableBrowserSideNavigation));
745 if (speculative_web_ui_)
746 speculative_web_ui_.reset();
747 should_reuse_web_ui_ = false;
748 if (speculative_render_frame_host_) {
749 speculative_render_frame_host_->GetProcess()->RemovePendingView();
nasko 2015/01/06 00:03:17 What codepath does AddPendingView on the speculati
carlosk 2015/01/08 16:05:55 CreatePendingRenderFrameHost -> CreateRenderFrame
nasko 2015/01/08 23:36:37 This method doesn't touch the pending RFH and we a
carlosk 2015/01/09 14:48:51 Doh, my bad! I meant to write: CreateSpeculativeR
nasko 2015/01/09 18:13:07 Ah, that clarifies it. Thanks.
750 return speculative_render_frame_host_.Pass();
751 }
752 return nullptr;
655 } 753 }
656 754
657 void RenderFrameHostManager::OnDidStartLoading() { 755 void RenderFrameHostManager::OnDidStartLoading() {
658 for (const auto& pair : proxy_hosts_) { 756 for (const auto& pair : proxy_hosts_) {
659 pair.second->Send( 757 pair.second->Send(
660 new FrameMsg_DidStartLoading(pair.second->GetRoutingID())); 758 new FrameMsg_DidStartLoading(pair.second->GetRoutingID()));
661 } 759 }
662 } 760 }
663 761
664 void RenderFrameHostManager::OnDidStopLoading() { 762 void RenderFrameHostManager::OnDidStopLoading() {
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 1148
1051 if (delegate_->IsHidden()) 1149 if (delegate_->IsHidden())
1052 create_render_frame_flags |= CREATE_RF_HIDDEN; 1150 create_render_frame_flags |= CREATE_RF_HIDDEN;
1053 1151
1054 int opener_route_id = 1152 int opener_route_id =
1055 CreateOpenerRenderViewsIfNeeded(old_instance, new_instance); 1153 CreateOpenerRenderViewsIfNeeded(old_instance, new_instance);
1056 1154
1057 if (pending_render_frame_host_) 1155 if (pending_render_frame_host_)
1058 CancelPending(); 1156 CancelPending();
1059 1157
1060 // Create a non-swapped-out RFH with the given opener. 1158 // Create a non swapped out RFH with the given opener.
1061 pending_render_frame_host_ = 1159 pending_render_frame_host_ =
1062 CreateRenderFrame(new_instance, pending_web_ui(), opener_route_id, 1160 CreateRenderFrame(new_instance, pending_web_ui(), opener_route_id,
1063 create_render_frame_flags, nullptr); 1161 create_render_frame_flags, nullptr);
1064 } 1162 }
1065 1163
1066 int RenderFrameHostManager::CreateOpenerRenderViewsIfNeeded( 1164 int RenderFrameHostManager::CreateOpenerRenderViewsIfNeeded(
1067 SiteInstance* old_instance, 1165 SiteInstance* old_instance,
1068 SiteInstance* new_instance) { 1166 SiteInstance* new_instance) {
1069 int opener_route_id = MSG_ROUTING_NONE; 1167 int opener_route_id = MSG_ROUTING_NONE;
1070 if (new_instance->IsRelatedSiteInstance(old_instance)) { 1168 if (new_instance->IsRelatedSiteInstance(old_instance)) {
(...skipping 16 matching lines...) Expand all
1087 int frame_routing_id, 1185 int frame_routing_id,
1088 int flags) { 1186 int flags) {
1089 if (frame_routing_id == MSG_ROUTING_NONE) 1187 if (frame_routing_id == MSG_ROUTING_NONE)
1090 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID(); 1188 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID();
1091 1189
1092 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); 1190 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
1093 bool hidden = !!(flags & CREATE_RF_HIDDEN); 1191 bool hidden = !!(flags & CREATE_RF_HIDDEN);
1094 1192
1095 // Create a RVH for main frames, or find the existing one for subframes. 1193 // Create a RVH for main frames, or find the existing one for subframes.
1096 FrameTree* frame_tree = frame_tree_node_->frame_tree(); 1194 FrameTree* frame_tree = frame_tree_node_->frame_tree();
1097 RenderViewHostImpl* render_view_host = NULL; 1195 RenderViewHostImpl* render_view_host = nullptr;
1098 if (frame_tree_node_->IsMainFrame()) { 1196 if (frame_tree_node_->IsMainFrame()) {
1099 render_view_host = frame_tree->CreateRenderViewHost( 1197 render_view_host = frame_tree->CreateRenderViewHost(
1100 site_instance, view_routing_id, frame_routing_id, swapped_out, hidden); 1198 site_instance, view_routing_id, frame_routing_id, swapped_out, hidden);
1101 } else { 1199 } else {
1102 render_view_host = frame_tree->GetRenderViewHost(site_instance); 1200 render_view_host = frame_tree->GetRenderViewHost(site_instance);
1103 1201
1104 CHECK(render_view_host); 1202 CHECK(render_view_host);
1105 } 1203 }
1106 1204
1107 // TODO(creis): Pass hidden to RFH. 1205 // TODO(creis): Pass hidden to RFH.
1108 scoped_ptr<RenderFrameHostImpl> render_frame_host = 1206 scoped_ptr<RenderFrameHostImpl> render_frame_host =
1109 make_scoped_ptr(RenderFrameHostFactory::Create( 1207 make_scoped_ptr(RenderFrameHostFactory::Create(
1110 render_view_host, render_frame_delegate_, frame_tree, 1208 render_view_host, render_frame_delegate_, frame_tree,
1111 frame_tree_node_, frame_routing_id, flags).release()); 1209 frame_tree_node_, frame_routing_id, flags).release());
1112 return render_frame_host.Pass(); 1210 return render_frame_host.Pass();
1113 } 1211 }
1114 1212
1213 // PlzNavigate
1214 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
1215 const GURL& url,
1216 SiteInstance* old_instance,
1217 SiteInstance* new_instance,
1218 int bindings) {
1219 CHECK(new_instance);
1220 CHECK_NE(old_instance, new_instance);
1221
1222 const NavigationEntry* current_navigation_entry =
1223 delegate_->GetLastCommittedNavigationEntryForRenderManager();
1224 scoped_ptr<WebUIImpl> new_web_ui;
1225 should_reuse_web_ui_ = ShouldReuseWebUI(current_navigation_entry, url);
1226 if (!should_reuse_web_ui_)
1227 new_web_ui = CreateWebUI(url, bindings);
1228
1229 int opener_route_id =
1230 CreateOpenerRenderViewsIfNeeded(old_instance, new_instance);
1231
1232 int create_render_frame_flags = 0;
1233 if (frame_tree_node_->IsMainFrame())
1234 create_render_frame_flags |= CREATE_RF_FOR_MAIN_FRAME_NAVIGATION;
1235 if (delegate_->IsHidden())
1236 create_render_frame_flags |= CREATE_RF_HIDDEN;
1237 scoped_ptr<RenderFrameHostImpl> new_render_frame_host =
1238 CreateRenderFrame(new_instance, new_web_ui.get(), opener_route_id,
1239 create_render_frame_flags, nullptr);
1240 if (!new_render_frame_host) {
nasko 2015/01/06 00:03:18 nit: no {} needed for one liners.
carlosk 2015/01/08 16:05:55 Done.
1241 return false;
1242 }
nasko 2015/01/06 00:03:17 Is there a specific reason why we don't call InitR
carlosk 2015/01/08 16:05:55 That's already done in CreateRenderFrame.
1243 speculative_render_frame_host_.reset(new_render_frame_host.release());
nasko 2015/01/06 00:03:17 Why not new_render_frame_host.Pass() instead of ne
carlosk 2015/01/08 16:05:55 Because there were used with the pending_web_ui an
1244 speculative_web_ui_.reset(new_web_ui.release());
1245 return true;
1246 }
1247
1115 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame( 1248 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
1116 SiteInstance* instance, 1249 SiteInstance* instance,
1117 WebUIImpl* web_ui, 1250 WebUIImpl* web_ui,
1118 int opener_route_id, 1251 int opener_route_id,
1119 int flags, 1252 int flags,
1120 int* view_routing_id_ptr) { 1253 int* view_routing_id_ptr) {
1121 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); 1254 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
1122 CHECK(instance); 1255 CHECK(instance);
1123 // Swapped out views should always be hidden. 1256 // Swapped out views should always be hidden.
1124 DCHECK(!swapped_out || (flags & CREATE_RF_HIDDEN)); 1257 DCHECK(!swapped_out || (flags & CREATE_RF_HIDDEN));
1125 1258
1126 // TODO(nasko): Remove the following CHECK once cross-site navigation no 1259 // TODO(nasko): Remove the following CHECK once cross-site navigation no
1127 // longer relies on swapped out RFH for the top-level frame. 1260 // longer relies on swapped out RFH for the top-level frame.
1128 if (!frame_tree_node_->IsMainFrame()) 1261 if (!frame_tree_node_->IsMainFrame())
1129 CHECK(!swapped_out); 1262 CHECK(!swapped_out);
1130 1263
1131 scoped_ptr<RenderFrameHostImpl> new_render_frame_host; 1264 scoped_ptr<RenderFrameHostImpl> new_render_frame_host;
1132 bool success = true; 1265 bool success = true;
1133 if (view_routing_id_ptr) 1266 if (view_routing_id_ptr)
1134 *view_routing_id_ptr = MSG_ROUTING_NONE; 1267 *view_routing_id_ptr = MSG_ROUTING_NONE;
1135 1268
1136 // We are creating a pending or swapped out RFH here. We should never create 1269 // We are creating a pending, speculative or swapped out RFH here. We should
1137 // it in the same SiteInstance as our current RFH. 1270 // never create it in the same SiteInstance as our current RFH.
1138 CHECK_NE(render_frame_host_->GetSiteInstance(), instance); 1271 CHECK_NE(render_frame_host_->GetSiteInstance(), instance);
1139 1272
1140 // Check if we've already created an RFH for this SiteInstance. If so, try 1273 // Check if we've already created an RFH for this SiteInstance. If so, try
1141 // to re-use the existing one, which has already been initialized. We'll 1274 // to re-use the existing one, which has already been initialized. We'll
1142 // remove it from the list of proxy hosts below if it will be active. 1275 // remove it from the list of proxy hosts below if it will be active.
1143 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance); 1276 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
1144 if (proxy && proxy->render_frame_host()) { 1277 if (proxy && proxy->render_frame_host()) {
1145 if (view_routing_id_ptr) 1278 if (view_routing_id_ptr)
1146 *view_routing_id_ptr = proxy->GetRenderViewHost()->GetRoutingID(); 1279 *view_routing_id_ptr = proxy->GetRenderViewHost()->GetRoutingID();
1147 // Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost. 1280 // Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost.
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1240 1373
1241 bool RenderFrameHostManager::InitRenderView( 1374 bool RenderFrameHostManager::InitRenderView(
1242 RenderViewHostImpl* render_view_host, 1375 RenderViewHostImpl* render_view_host,
1243 int opener_route_id, 1376 int opener_route_id,
1244 int proxy_routing_id, 1377 int proxy_routing_id,
1245 bool for_main_frame_navigation) { 1378 bool for_main_frame_navigation) {
1246 // We may have initialized this RenderViewHost for another RenderFrameHost. 1379 // We may have initialized this RenderViewHost for another RenderFrameHost.
1247 if (render_view_host->IsRenderViewLive()) 1380 if (render_view_host->IsRenderViewLive())
1248 return true; 1381 return true;
1249 1382
1250 // If the pending navigation is to a WebUI and the RenderView is not in a 1383 // If the ongoing navigation is to a WebUI and the RenderView is not in a
1251 // guest process, tell the RenderViewHost about any bindings it will need 1384 // guest process, tell the RenderViewHost about any bindings it will need
1252 // enabled. 1385 // enabled.
1253 if (pending_web_ui() && !render_view_host->GetProcess()->IsIsolatedGuest()) { 1386 WebUIImpl* future_web_ui;
1254 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); 1387 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1388 switches::kEnableBrowserSideNavigation)) {
1389 future_web_ui =
1390 should_reuse_web_ui_ ? web_ui_.get() : speculative_web_ui_.get();
1391 } else {
1392 future_web_ui = pending_web_ui();
1393 }
1394 if (future_web_ui && !render_view_host->GetProcess()->IsIsolatedGuest()) {
1395 render_view_host->AllowBindings(future_web_ui->GetBindings());
1255 } else { 1396 } else {
1256 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled 1397 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
1257 // process unless it's swapped out. 1398 // process unless it's swapped out.
1258 if (render_view_host->is_active()) { 1399 if (render_view_host->is_active()) {
1259 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 1400 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1260 render_view_host->GetProcess()->GetID())); 1401 render_view_host->GetProcess()->GetID()));
1261 } 1402 }
1262 } 1403 }
1263 1404
1264 return delegate_->CreateRenderViewForRenderManager(render_view_host, 1405 return delegate_->CreateRenderViewForRenderManager(render_view_host,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1306 proxy_hosts_.find(site_instance->GetId()); 1447 proxy_hosts_.find(site_instance->GetId());
1307 if (iter != proxy_hosts_.end()) 1448 if (iter != proxy_hosts_.end())
1308 return iter->second->GetRoutingID(); 1449 return iter->second->GetRoutingID();
1309 1450
1310 return MSG_ROUTING_NONE; 1451 return MSG_ROUTING_NONE;
1311 } 1452 }
1312 1453
1313 void RenderFrameHostManager::CommitPending() { 1454 void RenderFrameHostManager::CommitPending() {
1314 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", 1455 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending",
1315 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 1456 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
1457 bool browser_side_navigation =
1458 base::CommandLine::ForCurrentProcess()->HasSwitch(
1459 switches::kEnableBrowserSideNavigation);
1316 // First check whether we're going to want to focus the location bar after 1460 // First check whether we're going to want to focus the location bar after
1317 // this commit. We do this now because the navigation hasn't formally 1461 // this commit. We do this now because the navigation hasn't formally
1318 // committed yet, so if we've already cleared |pending_web_ui_| the call chain 1462 // committed yet, so if we've already cleared |pending_web_ui_| the call chain
1319 // this triggers won't be able to figure out what's going on. 1463 // this triggers won't be able to figure out what's going on.
1320 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 1464 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
1321 1465
1322 // Next commit the Web UI, if any. Either replace |web_ui_| with 1466 if (!browser_side_navigation) {
1323 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or 1467 DCHECK(!speculative_web_ui_);
1324 // leave |web_ui_| as is if reusing it. 1468 // Next commit the Web UI, if any. Either replace |web_ui_| with
1325 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); 1469 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
1326 if (pending_web_ui_) { 1470 // leave |web_ui_| as is if reusing it.
1327 web_ui_.reset(pending_web_ui_.release()); 1471 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get()));
1328 } else if (!pending_and_current_web_ui_.get()) { 1472 if (pending_web_ui_) {
1329 web_ui_.reset(); 1473 web_ui_.reset(pending_web_ui_.release());
1474 } else if (!pending_and_current_web_ui_.get()) {
1475 web_ui_.reset();
1476 } else {
1477 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
1478 pending_and_current_web_ui_.reset();
1479 }
1330 } else { 1480 } else {
1331 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); 1481 // PlzNavigate
1332 pending_and_current_web_ui_.reset(); 1482 if (!should_reuse_web_ui_)
1483 web_ui_.reset(speculative_web_ui_.release());
1484 DCHECK(!speculative_web_ui_);
1333 } 1485 }
1334 1486
1335 // It's possible for the pending_render_frame_host_ to be NULL when we aren't 1487 // It's possible for the pending_render_frame_host_ to be nullptr when we
1336 // crossing process boundaries. If so, we just needed to handle the Web UI 1488 // aren't crossing process boundaries. If so, we just needed to handle the Web
1337 // committing above and we're done. 1489 // UI committing above and we're done.
1338 if (!pending_render_frame_host_) { 1490 if (!pending_render_frame_host_ && !speculative_render_frame_host_) {
1339 if (will_focus_location_bar) 1491 if (will_focus_location_bar)
1340 delegate_->SetFocusToLocationBar(false); 1492 delegate_->SetFocusToLocationBar(false);
1341 return; 1493 return;
1342 } 1494 }
1343 1495
1344 // Remember if the page was focused so we can focus the new renderer in 1496 // Remember if the page was focused so we can focus the new renderer in
1345 // that case. 1497 // that case.
1346 bool focus_render_view = !will_focus_location_bar && 1498 bool focus_render_view = !will_focus_location_bar &&
1347 render_frame_host_->render_view_host()->GetView() && 1499 render_frame_host_->render_view_host()->GetView() &&
1348 render_frame_host_->render_view_host()->GetView()->HasFocus(); 1500 render_frame_host_->render_view_host()->GetView()->HasFocus();
1349 1501
1350 bool is_main_frame = frame_tree_node_->IsMainFrame(); 1502 bool is_main_frame = frame_tree_node_->IsMainFrame();
1351 1503
1352 // Swap in the pending frame and make it active. Also ensure the FrameTree 1504 // Swap in the pending or speculative frame and make it active. Also ensure
1353 // stays in sync. 1505 // the FrameTree stays in sync.
1354 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = 1506 scoped_ptr<RenderFrameHostImpl> old_render_frame_host;
1355 SetRenderFrameHost(pending_render_frame_host_.Pass()); 1507 if (!browser_side_navigation) {
1508 DCHECK(!speculative_render_frame_host_);
1509 old_render_frame_host =
1510 SetRenderFrameHost(pending_render_frame_host_.Pass());
1511 } else {
1512 // PlzNavigate
1513 DCHECK(speculative_render_frame_host_);
1514 old_render_frame_host =
1515 SetRenderFrameHost(speculative_render_frame_host_.Pass());
1516 }
1517
1356 if (is_main_frame) 1518 if (is_main_frame)
1357 render_frame_host_->render_view_host()->AttachToFrameTree(); 1519 render_frame_host_->render_view_host()->AttachToFrameTree();
1358 1520
1359 // The process will no longer try to exit, so we can decrement the count. 1521 // The process will no longer try to exit, so we can decrement the count.
1360 render_frame_host_->GetProcess()->RemovePendingView(); 1522 render_frame_host_->GetProcess()->RemovePendingView();
1361 1523
1362 // Show the new view (or a sad tab) if necessary. 1524 // Show the new view (or a sad tab) if necessary.
1363 bool new_rfh_has_view = !!render_frame_host_->render_view_host()->GetView(); 1525 bool new_rfh_has_view = !!render_frame_host_->render_view_host()->GetView();
1364 if (!delegate_->IsHidden() && new_rfh_has_view) { 1526 if (!delegate_->IsHidden() && new_rfh_has_view) {
1365 // In most cases, we need to show the new view. 1527 // In most cases, we need to show the new view.
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 TRACE_EVENT_INSTANT2( 1653 TRACE_EVENT_INSTANT2(
1492 "navigation", 1654 "navigation",
1493 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", 1655 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance",
1494 TRACE_EVENT_SCOPE_THREAD, 1656 TRACE_EVENT_SCOPE_THREAD,
1495 "current_instance id", current_instance->GetId(), 1657 "current_instance id", current_instance->GetId(),
1496 "new_instance id", new_instance->GetId()); 1658 "new_instance id", new_instance->GetId());
1497 1659
1498 // New SiteInstance: create a pending RFH to navigate. 1660 // New SiteInstance: create a pending RFH to navigate.
1499 DCHECK(!cross_navigation_pending_); 1661 DCHECK(!cross_navigation_pending_);
1500 1662
1501 // This will possibly create (set to NULL) a Web UI object for the pending 1663 // This will possibly create (set to nullptr) a Web UI object for the
1502 // page. We'll use this later to give the page special access. This must 1664 // pending page. We'll use this later to give the page special access. This
1503 // happen before the new renderer is created below so it will get bindings. 1665 // must happen before the new renderer is created below so it will get
1504 // It must also happen after the above conditional call to CancelPending(), 1666 // bindings. It must also happen after the above conditional call to
1505 // otherwise CancelPending may clear the pending_web_ui_ and the page will 1667 // CancelPending(), otherwise CancelPending may clear the pending_web_ui_
1506 // not have its bindings set appropriately. 1668 // and the page will not have its bindings set appropriately.
1507 SetPendingWebUI(dest_url, bindings); 1669 SetPendingWebUI(dest_url, bindings);
1508 CreatePendingRenderFrameHost(current_instance, new_instance.get(), 1670 CreatePendingRenderFrameHost(current_instance, new_instance.get(),
1509 frame_tree_node_->IsMainFrame()); 1671 frame_tree_node_->IsMainFrame());
1510 if (!pending_render_frame_host_.get()) { 1672 if (!pending_render_frame_host_.get()) {
1511 return NULL; 1673 return nullptr;
1512 } 1674 }
1513 1675
1514 // Check if our current RFH is live before we set up a transition. 1676 // Check if our current RFH is live before we set up a transition.
1515 if (!render_frame_host_->IsRenderFrameLive()) { 1677 if (!render_frame_host_->IsRenderFrameLive()) {
1516 if (!cross_navigation_pending_) { 1678 if (!cross_navigation_pending_) {
1517 // The current RFH is not live. There's no reason to sit around with a 1679 // The current RFH is not live. There's no reason to sit around with a
1518 // sad tab or a newly created RFH while we wait for the pending RFH to 1680 // sad tab or a newly created RFH while we wait for the pending RFH to
1519 // navigate. Just switch to the pending RFH now and go back to non 1681 // navigate. Just switch to the pending RFH now and go back to non
1520 // cross-navigating (Note that we don't care about on{before}unload 1682 // cross-navigating (Note that we don't care about on{before}unload
1521 // handlers if the current RFH isn't live.) 1683 // handlers if the current RFH isn't live.)
1522 CommitPending(); 1684 CommitPending();
1523 return render_frame_host_.get(); 1685 return render_frame_host_.get();
1524 } else { 1686 } else {
1525 NOTREACHED(); 1687 NOTREACHED();
1526 return render_frame_host_.get(); 1688 return render_frame_host_.get();
1527 } 1689 }
1528 } 1690 }
1529 // Otherwise, it's safe to treat this as a pending cross-site transition. 1691 // Otherwise, it's safe to treat this as a pending cross-site transition.
1530 1692
1531 // We now have a pending RFH. 1693 // We now have a pending RFH.
1532 DCHECK(!cross_navigation_pending_); 1694 DCHECK(!cross_navigation_pending_);
1533 cross_navigation_pending_ = true; 1695 cross_navigation_pending_ = true;
1534 1696
1535 // PlzNavigate: There is no notion of transfer navigations, and the old
1536 // renderer before unload handler has already run at that point, so return
1537 // here.
1538 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1539 switches::kEnableBrowserSideNavigation)) {
1540 return pending_render_frame_host_.get();
1541 }
1542
1543 // We need to wait until the beforeunload handler has run, unless we are 1697 // We need to wait until the beforeunload handler has run, unless we are
1544 // transferring an existing request (in which case it has already run). 1698 // transferring an existing request (in which case it has already run).
1545 // Suspend the new render view (i.e., don't let it send the cross-site 1699 // Suspend the new render view (i.e., don't let it send the cross-site
1546 // Navigate message) until we hear back from the old renderer's 1700 // Navigate message) until we hear back from the old renderer's
1547 // beforeunload handler. If the handler returns false, we'll have to 1701 // beforeunload handler. If the handler returns false, we'll have to
1548 // cancel the request. 1702 // cancel the request.
1549 // 1703 //
1550 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); 1704 DCHECK(!pending_render_frame_host_->are_navigations_suspended());
1551 bool is_transfer = transferred_request_id != GlobalRequestID(); 1705 bool is_transfer = transferred_request_id != GlobalRequestID();
1552 if (is_transfer) { 1706 if (is_transfer) {
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1707 void RenderFrameHostManager::DeleteRenderFrameProxyHost( 1861 void RenderFrameHostManager::DeleteRenderFrameProxyHost(
1708 SiteInstance* instance) { 1862 SiteInstance* instance) {
1709 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId()); 1863 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId());
1710 if (iter != proxy_hosts_.end()) { 1864 if (iter != proxy_hosts_.end()) {
1711 delete iter->second; 1865 delete iter->second;
1712 proxy_hosts_.erase(iter); 1866 proxy_hosts_.erase(iter);
1713 } 1867 }
1714 } 1868 }
1715 1869
1716 } // namespace content 1870 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698