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

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: Fixed missing references to |base| namespace. 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 if (!render_frame_host->is_swapped_out())
610 render_frame_host->SwapOut(proxy, false);
611
582 if (frame_tree_node_->IsMainFrame()) 612 if (frame_tree_node_->IsMainFrame())
583 proxy->TakeFrameHostOwnership(render_frame_host.Pass()); 613 proxy->TakeFrameHostOwnership(render_frame_host.Pass());
584 } else { 614 } else {
585 // We won't be coming back, so delete this one. 615 // We won't be coming back, so delete this one.
586 render_frame_host.reset(); 616 render_frame_host.reset();
587 } 617 }
588 } 618 }
589 619
590 void RenderFrameHostManager::MoveToPendingDeleteHosts( 620 void RenderFrameHostManager::MoveToPendingDeleteHosts(
591 scoped_ptr<RenderFrameHostImpl> render_frame_host) { 621 scoped_ptr<RenderFrameHostImpl> render_frame_host) {
(...skipping 24 matching lines...) Expand all
616 } 646 }
617 } 647 }
618 return false; 648 return false;
619 } 649 }
620 650
621 void RenderFrameHostManager::ResetProxyHosts() { 651 void RenderFrameHostManager::ResetProxyHosts() {
622 STLDeleteValues(&proxy_hosts_); 652 STLDeleteValues(&proxy_hosts_);
623 } 653 }
624 654
625 // PlzNavigate 655 // PlzNavigate
656 void RenderFrameHostManager::BeginNavigation(
657 const FrameHostMsg_BeginNavigation_Params& params,
658 const CommonNavigationParams& common_params) {
659 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
660 switches::kEnableBrowserSideNavigation));
661 // Cleans up any state in case there's an ongoing navigation.
662 // TODO(carlosk): remove this cleanup here once we properly cancel ongoing
663 // navigations.
664 CleanUpNavigation();
665
666 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
667 // TODO(carlosk): Replace the default values with the right ones for
668 // source_instance, dest_instance, dest_is_restore, dest_is_view_source_mode.
669 scoped_refptr<SiteInstanceImpl> new_instance = static_cast<SiteInstanceImpl*>(
670 GetSiteInstanceForNavigation(common_params.url, nullptr, nullptr,
671 common_params.transition, false, false));
672
673 // Will keep the current RFH if its SiteInstance matches the new one from
674 // the navigation or if this is a subframe navigation. If --site-per-process
675 // is enabled the RFH is never kept when sites don't match.
676 // TODO(carlosk): do not swap processes for renderer initiated navigations
677 // (see crbug.com/440266).
678 if (current_instance == new_instance.get() ||
679 (!frame_tree_node_->IsMainFrame() &&
680 !base::CommandLine::ForCurrentProcess()->HasSwitch(
681 switches::kSitePerProcess))) {
682 // Make sure the current RFH is alive.
683 if (!render_frame_host_->render_view_host()->IsRenderViewLive()) {
684 // Recreate the opener chain.
685 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
686 render_frame_host_->GetSiteInstance());
687 bool success = InitRenderView(render_frame_host_->render_view_host(),
688 opener_route_id, MSG_ROUTING_NONE,
689 frame_tree_node_->IsMainFrame());
690 DCHECK(success);
691 }
692 DCHECK(current_instance->GetProcess()->HasConnection());
693 return;
694 }
695
696 // Speculatively create a new RFH.
697 // TODO(carlosk): enable bindings check below.
698 bool success = CreateSpeculativeRenderFrameHost(
699 common_params.url, current_instance, new_instance.get(),
700 NavigationEntryImpl::kInvalidBindings);
701 DCHECK(success);
702 DCHECK(new_instance->GetProcess()->HasConnection());
703 }
704
705 // PlzNavigate
706 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
707 const GURL& url,
708 SiteInstance* old_instance,
709 SiteInstance* new_instance,
710 int bindings) {
711 CHECK(new_instance);
712 CHECK_NE(old_instance, new_instance);
713
714 const NavigationEntry* current_navigation_entry =
715 delegate_->GetLastCommittedNavigationEntryForRenderManager();
716 scoped_ptr<WebUIImpl> new_web_ui;
717 should_reuse_web_ui_ = ShouldReuseWebUI(current_navigation_entry, url);
718 if (!should_reuse_web_ui_)
719 new_web_ui = CreateWebUI(url, bindings);
720
721 int opener_route_id =
722 CreateOpenerRenderViewsIfNeeded(old_instance, new_instance);
723
724 int create_render_frame_flags = 0;
725 if (frame_tree_node_->IsMainFrame())
726 create_render_frame_flags |= CREATE_RF_FOR_MAIN_FRAME_NAVIGATION;
727 if (delegate_->IsHidden())
728 create_render_frame_flags |= CREATE_RF_HIDDEN;
729 scoped_ptr<RenderFrameHostImpl> new_render_frame_host =
730 CreateRenderFrame(new_instance, new_web_ui.get(), opener_route_id,
731 create_render_frame_flags, nullptr);
732 if (!new_render_frame_host) {
733 return false;
734 }
735 speculative_render_frame_host_.reset(new_render_frame_host.release());
736 speculative_web_ui_.reset(new_web_ui.release());
737 return true;
738 }
739
740 // PlzNavigate
626 RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation( 741 RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
627 const GURL& url, 742 const GURL& url,
628 ui::PageTransition transition) { 743 ui::PageTransition transition) {
629 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 744 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
630 switches::kEnableBrowserSideNavigation)); 745 switches::kEnableBrowserSideNavigation));
631 // TODO(clamy): When we handle renderer initiated navigations, make sure not 746 // Pick the right RenderFrameHost to commit the navigation.
632 // to use a different process for subframes if --site-per-process is not 747 RenderFrameHostImpl* rfh_for_navigation = nullptr;
633 // enabled.
634 748
635 // Pick the right RenderFrameHost to commit the navigation. 749 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
636 // TODO(clamy): Replace the default values by the right ones. 750 // TODO(clamy): Replace the default values with the right ones for
637 RenderFrameHostImpl* render_frame_host = UpdateStateForNavigate( 751 // source_instance, dest_instance, dest_is_restore, dest_is_view_source_mode.
638 url, nullptr, nullptr, transition, false, false, GlobalRequestID(), 752 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
639 NavigationEntryImpl::kInvalidBindings); 753 url, nullptr, nullptr, transition, false, false);
640 754
641 // If the renderer that needs to navigate is not live (it was just created or 755 // Will keep the current RFH if its SiteInstance matches the new one from
642 // it crashed), initialize it. 756 // the navigation or if this is a subframe navigation. If --site-per-process
643 if (!render_frame_host->render_view_host()->IsRenderViewLive()) { 757 // is enabled the RFH is never kept when sites don't match.
758 // TODO(carlosk): do not swap processes for renderer initiated navigations
759 // (see crbug.com/440266).
760 if (current_instance == new_instance.get() ||
761 (!frame_tree_node_->IsMainFrame() &&
762 !base::CommandLine::ForCurrentProcess()->HasSwitch(
763 switches::kSitePerProcess))) {
764 CleanUpNavigation();
765 rfh_for_navigation = render_frame_host_.get();
766 } else {
767 // If the SiteInstance for the final URL doesn't match the one from the
768 // speculatively created RenderFrameHost, create a new RenderFrameHost using
769 // this new SiteInstance.
770 if (!speculative_render_frame_host_ ||
771 speculative_render_frame_host_->GetSiteInstance() !=
772 new_instance.get()) {
773 CleanUpNavigation();
774 // TODO(clamy): Replace the binding value with the right one.
775 bool success = CreateSpeculativeRenderFrameHost(
776 url, current_instance, new_instance.get(),
777 NavigationEntryImpl::kInvalidBindings);
778 CHECK(success);
779 }
780 DCHECK(speculative_render_frame_host_);
781 rfh_for_navigation = speculative_render_frame_host_.get();
782 }
783 DCHECK(rfh_for_navigation);
784
785 // If the renderer that needs to navigate is not live (it was just created
786 // or it crashed), initialize it.
787 if (!rfh_for_navigation->render_view_host()->IsRenderViewLive()) {
644 // Recreate the opener chain. 788 // Recreate the opener chain.
645 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager( 789 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
646 render_frame_host->GetSiteInstance()); 790 rfh_for_navigation->GetSiteInstance());
647 if (!InitRenderView(render_frame_host->render_view_host(), 791 if (!InitRenderView(rfh_for_navigation->render_view_host(), opener_route_id,
648 opener_route_id, 792 MSG_ROUTING_NONE, frame_tree_node_->IsMainFrame())) {
649 MSG_ROUTING_NONE,
650 frame_tree_node_->IsMainFrame())) {
651 return nullptr; 793 return nullptr;
652 } 794 }
653 } 795 }
654 return render_frame_host; 796
797 return rfh_for_navigation;
798 }
799
800 // PlzNavigate
801 void RenderFrameHostManager::CleanUpNavigation() {
802 scoped_ptr<RenderFrameHostImpl> rfh = UnsetSpeculativeRenderFrameHost();
803 if (rfh)
804 DiscardUnusedFrame(rfh.Pass());
805 }
806
807 // PlzNavigate
808 scoped_ptr<RenderFrameHostImpl>
809 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() {
810 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
811 switches::kEnableBrowserSideNavigation));
812 if (speculative_web_ui_)
813 speculative_web_ui_.reset();
814 should_reuse_web_ui_ = false;
815 if (speculative_render_frame_host_) {
816 speculative_render_frame_host_->GetProcess()->RemovePendingView();
817 return speculative_render_frame_host_.Pass();
818 }
819 return nullptr;
655 } 820 }
656 821
657 void RenderFrameHostManager::OnDidStartLoading() { 822 void RenderFrameHostManager::OnDidStartLoading() {
658 for (const auto& pair : proxy_hosts_) { 823 for (const auto& pair : proxy_hosts_) {
659 pair.second->Send( 824 pair.second->Send(
660 new FrameMsg_DidStartLoading(pair.second->GetRoutingID())); 825 new FrameMsg_DidStartLoading(pair.second->GetRoutingID()));
661 } 826 }
662 } 827 }
663 828
664 void RenderFrameHostManager::OnDidStopLoading() { 829 void RenderFrameHostManager::OnDidStopLoading() {
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 int frame_routing_id, 1252 int frame_routing_id,
1088 int flags) { 1253 int flags) {
1089 if (frame_routing_id == MSG_ROUTING_NONE) 1254 if (frame_routing_id == MSG_ROUTING_NONE)
1090 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID(); 1255 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID();
1091 1256
1092 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); 1257 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
1093 bool hidden = !!(flags & CREATE_RF_HIDDEN); 1258 bool hidden = !!(flags & CREATE_RF_HIDDEN);
1094 1259
1095 // Create a RVH for main frames, or find the existing one for subframes. 1260 // Create a RVH for main frames, or find the existing one for subframes.
1096 FrameTree* frame_tree = frame_tree_node_->frame_tree(); 1261 FrameTree* frame_tree = frame_tree_node_->frame_tree();
1097 RenderViewHostImpl* render_view_host = NULL; 1262 RenderViewHostImpl* render_view_host = nullptr;
1098 if (frame_tree_node_->IsMainFrame()) { 1263 if (frame_tree_node_->IsMainFrame()) {
1099 render_view_host = frame_tree->CreateRenderViewHost( 1264 render_view_host = frame_tree->CreateRenderViewHost(
1100 site_instance, view_routing_id, frame_routing_id, swapped_out, hidden); 1265 site_instance, view_routing_id, frame_routing_id, swapped_out, hidden);
1101 } else { 1266 } else {
1102 render_view_host = frame_tree->GetRenderViewHost(site_instance); 1267 render_view_host = frame_tree->GetRenderViewHost(site_instance);
1103 1268
1104 CHECK(render_view_host); 1269 CHECK(render_view_host);
1105 } 1270 }
1106 1271
1107 // TODO(creis): Pass hidden to RFH. 1272 // TODO(creis): Pass hidden to RFH.
(...skipping 18 matching lines...) Expand all
1126 // TODO(nasko): Remove the following CHECK once cross-site navigation no 1291 // TODO(nasko): Remove the following CHECK once cross-site navigation no
1127 // longer relies on swapped out RFH for the top-level frame. 1292 // longer relies on swapped out RFH for the top-level frame.
1128 if (!frame_tree_node_->IsMainFrame()) 1293 if (!frame_tree_node_->IsMainFrame())
1129 CHECK(!swapped_out); 1294 CHECK(!swapped_out);
1130 1295
1131 scoped_ptr<RenderFrameHostImpl> new_render_frame_host; 1296 scoped_ptr<RenderFrameHostImpl> new_render_frame_host;
1132 bool success = true; 1297 bool success = true;
1133 if (view_routing_id_ptr) 1298 if (view_routing_id_ptr)
1134 *view_routing_id_ptr = MSG_ROUTING_NONE; 1299 *view_routing_id_ptr = MSG_ROUTING_NONE;
1135 1300
1136 // We are creating a pending or swapped out RFH here. We should never create 1301 // We are creating a pending, speculative or swapped out RFH here. We should
1137 // it in the same SiteInstance as our current RFH. 1302 // never create it in the same SiteInstance as our current RFH.
1138 CHECK_NE(render_frame_host_->GetSiteInstance(), instance); 1303 CHECK_NE(render_frame_host_->GetSiteInstance(), instance);
1139 1304
1140 // Check if we've already created an RFH for this SiteInstance. If so, try 1305 // 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 1306 // 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. 1307 // remove it from the list of proxy hosts below if it will be active.
1143 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance); 1308 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
1144 if (proxy && proxy->render_frame_host()) { 1309 if (proxy && proxy->render_frame_host()) {
1145 if (view_routing_id_ptr) 1310 if (view_routing_id_ptr)
1146 *view_routing_id_ptr = proxy->GetRenderViewHost()->GetRoutingID(); 1311 *view_routing_id_ptr = proxy->GetRenderViewHost()->GetRoutingID();
1147 // Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost. 1312 // Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost.
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1306 proxy_hosts_.find(site_instance->GetId()); 1471 proxy_hosts_.find(site_instance->GetId());
1307 if (iter != proxy_hosts_.end()) 1472 if (iter != proxy_hosts_.end())
1308 return iter->second->GetRoutingID(); 1473 return iter->second->GetRoutingID();
1309 1474
1310 return MSG_ROUTING_NONE; 1475 return MSG_ROUTING_NONE;
1311 } 1476 }
1312 1477
1313 void RenderFrameHostManager::CommitPending() { 1478 void RenderFrameHostManager::CommitPending() {
1314 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", 1479 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending",
1315 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 1480 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
1481 bool browser_side_navigation =
1482 base::CommandLine::ForCurrentProcess()->HasSwitch(
1483 switches::kEnableBrowserSideNavigation);
1316 // First check whether we're going to want to focus the location bar after 1484 // 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 1485 // 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 1486 // 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. 1487 // this triggers won't be able to figure out what's going on.
1320 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 1488 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
1321 1489
1322 // Next commit the Web UI, if any. Either replace |web_ui_| with 1490 if (!browser_side_navigation) {
1323 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or 1491 DCHECK(!speculative_web_ui_);
1324 // leave |web_ui_| as is if reusing it. 1492 // Next commit the Web UI, if any. Either replace |web_ui_| with
1325 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); 1493 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
1326 if (pending_web_ui_) { 1494 // leave |web_ui_| as is if reusing it.
1327 web_ui_.reset(pending_web_ui_.release()); 1495 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get()));
1328 } else if (!pending_and_current_web_ui_.get()) { 1496 if (pending_web_ui_) {
1329 web_ui_.reset(); 1497 web_ui_.reset(pending_web_ui_.release());
1498 } else if (!pending_and_current_web_ui_.get()) {
1499 web_ui_.reset();
1500 } else {
1501 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
1502 pending_and_current_web_ui_.reset();
1503 }
1330 } else { 1504 } else {
1331 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); 1505 // PlzNavigate
1332 pending_and_current_web_ui_.reset(); 1506 if (!should_reuse_web_ui_)
1507 web_ui_.reset(speculative_web_ui_.release());
1508 DCHECK(!speculative_web_ui_);
1333 } 1509 }
1334 1510
1335 // It's possible for the pending_render_frame_host_ to be NULL when we aren't 1511 // 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 1512 // aren't crossing process boundaries. If so, we just needed to handle the Web
1337 // committing above and we're done. 1513 // UI committing above and we're done.
1338 if (!pending_render_frame_host_) { 1514 if (!pending_render_frame_host_ && !speculative_render_frame_host_) {
1339 if (will_focus_location_bar) 1515 if (will_focus_location_bar)
1340 delegate_->SetFocusToLocationBar(false); 1516 delegate_->SetFocusToLocationBar(false);
1341 return; 1517 return;
1342 } 1518 }
1343 1519
1344 // Remember if the page was focused so we can focus the new renderer in 1520 // Remember if the page was focused so we can focus the new renderer in
1345 // that case. 1521 // that case.
1346 bool focus_render_view = !will_focus_location_bar && 1522 bool focus_render_view = !will_focus_location_bar &&
1347 render_frame_host_->render_view_host()->GetView() && 1523 render_frame_host_->render_view_host()->GetView() &&
1348 render_frame_host_->render_view_host()->GetView()->HasFocus(); 1524 render_frame_host_->render_view_host()->GetView()->HasFocus();
1349 1525
1350 bool is_main_frame = frame_tree_node_->IsMainFrame(); 1526 bool is_main_frame = frame_tree_node_->IsMainFrame();
1351 1527
1352 // Swap in the pending frame and make it active. Also ensure the FrameTree 1528 // Swap in the pending or speculative frame and make it active. Also ensure
1353 // stays in sync. 1529 // the FrameTree stays in sync.
1354 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = 1530 scoped_ptr<RenderFrameHostImpl> old_render_frame_host;
1355 SetRenderFrameHost(pending_render_frame_host_.Pass()); 1531 if (!browser_side_navigation) {
1532 DCHECK(!speculative_render_frame_host_);
1533 old_render_frame_host =
1534 SetRenderFrameHost(pending_render_frame_host_.Pass());
1535 } else {
1536 // PlzNavigate
1537 DCHECK(speculative_render_frame_host_);
1538 old_render_frame_host =
1539 SetRenderFrameHost(speculative_render_frame_host_.Pass());
1540 }
1541
1356 if (is_main_frame) 1542 if (is_main_frame)
1357 render_frame_host_->render_view_host()->AttachToFrameTree(); 1543 render_frame_host_->render_view_host()->AttachToFrameTree();
1358 1544
1359 // The process will no longer try to exit, so we can decrement the count. 1545 // The process will no longer try to exit, so we can decrement the count.
1360 render_frame_host_->GetProcess()->RemovePendingView(); 1546 render_frame_host_->GetProcess()->RemovePendingView();
1361 1547
1362 // Show the new view (or a sad tab) if necessary. 1548 // Show the new view (or a sad tab) if necessary.
1363 bool new_rfh_has_view = !!render_frame_host_->render_view_host()->GetView(); 1549 bool new_rfh_has_view = !!render_frame_host_->render_view_host()->GetView();
1364 if (!delegate_->IsHidden() && new_rfh_has_view) { 1550 if (!delegate_->IsHidden() && new_rfh_has_view) {
1365 // In most cases, we need to show the new view. 1551 // 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( 1677 TRACE_EVENT_INSTANT2(
1492 "navigation", 1678 "navigation",
1493 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", 1679 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance",
1494 TRACE_EVENT_SCOPE_THREAD, 1680 TRACE_EVENT_SCOPE_THREAD,
1495 "current_instance id", current_instance->GetId(), 1681 "current_instance id", current_instance->GetId(),
1496 "new_instance id", new_instance->GetId()); 1682 "new_instance id", new_instance->GetId());
1497 1683
1498 // New SiteInstance: create a pending RFH to navigate. 1684 // New SiteInstance: create a pending RFH to navigate.
1499 DCHECK(!cross_navigation_pending_); 1685 DCHECK(!cross_navigation_pending_);
1500 1686
1501 // This will possibly create (set to NULL) a Web UI object for the pending 1687 // 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 1688 // 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. 1689 // 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(), 1690 // bindings. It must also happen after the above conditional call to
1505 // otherwise CancelPending may clear the pending_web_ui_ and the page will 1691 // CancelPending(), otherwise CancelPending may clear the pending_web_ui_
1506 // not have its bindings set appropriately. 1692 // and the page will not have its bindings set appropriately.
1507 SetPendingWebUI(dest_url, bindings); 1693 SetPendingWebUI(dest_url, bindings);
1508 CreatePendingRenderFrameHost(current_instance, new_instance.get(), 1694 CreatePendingRenderFrameHost(current_instance, new_instance.get(),
1509 frame_tree_node_->IsMainFrame()); 1695 frame_tree_node_->IsMainFrame());
1510 if (!pending_render_frame_host_.get()) { 1696 if (!pending_render_frame_host_.get()) {
1511 return NULL; 1697 return nullptr;
1512 } 1698 }
1513 1699
1514 // Check if our current RFH is live before we set up a transition. 1700 // Check if our current RFH is live before we set up a transition.
1515 if (!render_frame_host_->IsRenderFrameLive()) { 1701 if (!render_frame_host_->IsRenderFrameLive()) {
1516 if (!cross_navigation_pending_) { 1702 if (!cross_navigation_pending_) {
1517 // The current RFH is not live. There's no reason to sit around with a 1703 // 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 1704 // 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 1705 // 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 1706 // cross-navigating (Note that we don't care about on{before}unload
1521 // handlers if the current RFH isn't live.) 1707 // handlers if the current RFH isn't live.)
1522 CommitPending(); 1708 CommitPending();
1523 return render_frame_host_.get(); 1709 return render_frame_host_.get();
1524 } else { 1710 } else {
1525 NOTREACHED(); 1711 NOTREACHED();
1526 return render_frame_host_.get(); 1712 return render_frame_host_.get();
1527 } 1713 }
1528 } 1714 }
1529 // Otherwise, it's safe to treat this as a pending cross-site transition. 1715 // Otherwise, it's safe to treat this as a pending cross-site transition.
1530 1716
1531 // We now have a pending RFH. 1717 // We now have a pending RFH.
1532 DCHECK(!cross_navigation_pending_); 1718 DCHECK(!cross_navigation_pending_);
1533 cross_navigation_pending_ = true; 1719 cross_navigation_pending_ = true;
1534 1720
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 1721 // 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). 1722 // 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 1723 // 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 1724 // Navigate message) until we hear back from the old renderer's
1547 // beforeunload handler. If the handler returns false, we'll have to 1725 // beforeunload handler. If the handler returns false, we'll have to
1548 // cancel the request. 1726 // cancel the request.
1549 // 1727 //
1550 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); 1728 DCHECK(!pending_render_frame_host_->are_navigations_suspended());
1551 bool is_transfer = transferred_request_id != GlobalRequestID(); 1729 bool is_transfer = transferred_request_id != GlobalRequestID();
1552 if (is_transfer) { 1730 if (is_transfer) {
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1707 void RenderFrameHostManager::DeleteRenderFrameProxyHost( 1885 void RenderFrameHostManager::DeleteRenderFrameProxyHost(
1708 SiteInstance* instance) { 1886 SiteInstance* instance) {
1709 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId()); 1887 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId());
1710 if (iter != proxy_hosts_.end()) { 1888 if (iter != proxy_hosts_.end()) {
1711 delete iter->second; 1889 delete iter->second;
1712 proxy_hosts_.erase(iter); 1890 proxy_hosts_.erase(iter);
1713 } 1891 }
1714 } 1892 }
1715 1893
1716 } // namespace content 1894 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698