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

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: Latest changes due to review 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(
Charlie Reis 2015/01/12 23:30:52 We should probably mimic the case above and check
carlosk 2015/01/13 15:54:13 Done. I was in doubt about this one because we w
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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 DCHECK(render_frame_host);
Charlie Reis 2015/01/12 23:30:52 This seems unnecessary to me, since the callers ar
carlosk 2015/01/13 15:54:13 Done.
430 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
431 switches::kEnableBrowserSideNavigation)) {
432 if (render_frame_host == speculative_render_frame_host_.get()) {
433 CommitPending();
434 } else if (render_frame_host == render_frame_host_.get()) {
435 // TODO(carlosk): this code doesn't properly handles in-page nor
Charlie Reis 2015/01/12 23:30:52 handle nor -> or
carlosk 2015/01/13 15:54:13 Done.
436 // interweaved navigation requests navigation.
Charlie Reis 2015/01/12 23:30:52 I don't know what this means.
carlosk 2015/01/13 15:54:13 Fixed: /interweaved/interwoven This case might ha
437 DCHECK(!speculative_render_frame_host_);
438 } else {
439 // No one else should be sending us a DidNavigate in this state.
440 DCHECK(false);
441 }
442 DCHECK(!speculative_render_frame_host_);
443 return;
444 }
445
421 if (!cross_navigation_pending_) { 446 if (!cross_navigation_pending_) {
Charlie Reis 2015/01/12 23:30:52 Why isn't this block above the one you added? Is
carlosk 2015/01/13 15:54:12 It is not used by PlzNavigate so I documented that
Charlie Reis 2015/01/13 18:48:21 Ok. Those cases will matter, but it sounds like y
carlosk 2015/01/14 10:09:47 Acknowledged.
422 DCHECK(!pending_render_frame_host_); 447 DCHECK(!pending_render_frame_host_);
423 448
424 // We should only hear this from our current renderer. 449 // We should only hear this from our current renderer.
425 DCHECK_EQ(render_frame_host_, render_frame_host); 450 DCHECK_EQ(render_frame_host_, render_frame_host);
426 451
427 // Even when there is no pending RVH, there may be a pending Web UI. 452 // Even when there is no pending RVH, there may be a pending Web UI.
428 if (pending_web_ui()) 453 if (pending_web_ui())
429 CommitPending(); 454 CommitPending();
430 return; 455 return;
431 } 456 }
432 457
433 if (render_frame_host == pending_render_frame_host_) { 458 if (render_frame_host == pending_render_frame_host_) {
434 // The pending cross-site navigation completed, so show the renderer. 459 // The pending cross-site navigation completed, so show the renderer.
435 CommitPending(); 460 CommitPending();
436 cross_navigation_pending_ = false; 461 cross_navigation_pending_ = false;
437 } else if (render_frame_host == render_frame_host_) { 462 } else if (render_frame_host == render_frame_host_) {
438 if (was_caused_by_user_gesture) { 463 if (was_caused_by_user_gesture) {
439 // A navigation in the original page has taken place. Cancel the pending 464 // A navigation in the original page has taken place. Cancel the pending
440 // one. Only do it for user gesture originated navigations to prevent 465 // one. Only do it for user gesture originated navigations to prevent
441 // page doing any shenanigans to prevent user from navigating. 466 // page doing any shenanigans to prevent user from navigating.
442 // See https://code.google.com/p/chromium/issues/detail?id=75195 467 // See https://crbug.com/75195.
Charlie Reis 2015/01/12 23:30:53 I have no problem with this change in general, but
carlosk 2015/01/13 15:54:12 Acknowledged and reverted. (FYI I was asked for th
443 CancelPending(); 468 CancelPending();
444 cross_navigation_pending_ = false; 469 cross_navigation_pending_ = false;
445 } 470 }
446 } else { 471 } else {
447 // No one else should be sending us DidNavigate in this state. 472 // No one else should be sending us DidNavigate in this state.
448 DCHECK(false); 473 DCHECK(false);
449 } 474 }
450 } 475 }
451 476
452 void RenderFrameHostManager::DidDisownOpener( 477 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 596 // 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. 597 // delete the RFH. Just swap it out and it can be reused at a later point.
573 SiteInstanceImpl* site_instance = render_frame_host->GetSiteInstance(); 598 SiteInstanceImpl* site_instance = render_frame_host->GetSiteInstance();
574 if (site_instance->HasSite() && site_instance->active_frame_count() > 1) { 599 if (site_instance->HasSite() && site_instance->active_frame_count() > 1) {
575 // Any currently suspended navigations are no longer needed. 600 // Any currently suspended navigations are no longer needed.
576 render_frame_host->CancelSuspendedNavigations(); 601 render_frame_host->CancelSuspendedNavigations();
577 602
578 RenderFrameProxyHost* proxy = 603 RenderFrameProxyHost* proxy =
579 new RenderFrameProxyHost(site_instance, frame_tree_node_); 604 new RenderFrameProxyHost(site_instance, frame_tree_node_);
580 proxy_hosts_[site_instance->GetId()] = proxy; 605 proxy_hosts_[site_instance->GetId()] = proxy;
581 render_frame_host->SwapOut(proxy, false); 606
607 // As the RenderFrameHost might already be swapped out, check if that is
Charlie Reis 2015/01/12 23:30:52 Simplify: "Check if the RenderFrameHost is already
carlosk 2015/01/13 15:54:13 Done.
608 // the case to avoid swapping it out again.
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 CommonNavigationParams& common_params) {
658 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
659 switches::kEnableBrowserSideNavigation));
660 // Cleans up any state in case there's an ongoing navigation.
Charlie Reis 2015/01/12 23:30:53 nit: Clean
carlosk 2015/01/13 15:54:13 Done.
661 // TODO(carlosk): remove this cleanup here once we properly cancel ongoing
662 // navigations.
663 CleanUpNavigation();
664
665 RenderFrameHostImpl* future_rfh =
Charlie Reis 2015/01/12 23:30:52 future_rfh -> dest_rfh Also, it's worth mentionin
carlosk 2015/01/13 15:54:13 Done the name change. And for the expectation you
666 GetFrameHostForNavigation(common_params.url, common_params.transition);
667 DCHECK(future_rfh);
668 }
669
670 // PlzNavigate
626 RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation( 671 RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
627 const GURL& url, 672 const GURL& url,
628 ui::PageTransition transition) { 673 ui::PageTransition transition) {
629 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 674 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
630 switches::kEnableBrowserSideNavigation)); 675 switches::kEnableBrowserSideNavigation));
631 // TODO(clamy): When we handle renderer initiated navigations, make sure not 676 // Pick the right RenderFrameHost to commit the navigation.
632 // to use a different process for subframes if --site-per-process is not 677 RenderFrameHostImpl* rfh_for_navigation = nullptr;
Charlie Reis 2015/01/12 23:30:52 new_rfh would better match new_instance. Please a
carlosk 2015/01/13 15:54:13 I went another route: current_instance -> current_
Charlie Reis 2015/01/13 18:48:21 *_site_instance instead of *_instance is fine. I
carlosk 2015/01/14 10:09:46 Done: navigation_site_instance -> dest_site_instan
633 // enabled.
634 678
635 // Pick the right RenderFrameHost to commit the navigation. 679 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
636 // TODO(clamy): Replace the default values by the right ones.
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 // TODO(carlosk): Replace the default values with the right ones for
642 // it crashed), initialize it. 682 // source_instance, dest_instance, dest_is_restore, dest_is_view_source_mode.
643 if (!render_frame_host->render_view_host()->IsRenderViewLive()) { 683 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
684 url, nullptr, nullptr, transition, false, false);
685
686 // TODO(carlosk): do not swap processes for renderer initiated navigations
687 // (see crbug.com/440266).
688 if (current_instance == new_instance.get() ||
689 (!frame_tree_node_->IsMainFrame() &&
690 !base::CommandLine::ForCurrentProcess()->HasSwitch(
691 switches::kSitePerProcess))) {
692 // Will reuse the current RFH if its SiteInstance matches the new one from
Charlie Reis 2015/01/12 23:30:53 Drop "Will"
carlosk 2015/01/13 15:54:12 Done. Also updated the rest a bit.
693 // the navigation or if this is a subframe navigation. If --site-per-process
694 // is enabled the RFH is never kept when sites don't match.
Charlie Reis 2015/01/12 23:30:52 This isn't quite true, since we don't plan to isol
carlosk 2015/01/13 15:54:12 Done.
695 CleanUpNavigation();
696 rfh_for_navigation = render_frame_host_.get();
697 } else {
698 // If the current render_frame_host_ isn't live, we should create it so
699 // that we don't show a sad tab while the navigation is ongoing.
700 // (Bug 1145340)
701 if (!render_frame_host_->IsRenderFrameLive()) {
702 // Note: we don't call InitRenderView here because we are navigating away
703 // soon anyway, and we don't have the NavigationEntry for this host.
704 delegate_->CreateRenderViewForRenderManager(
705 render_frame_host_->render_view_host(), MSG_ROUTING_NONE,
706 MSG_ROUTING_NONE, frame_tree_node_->IsMainFrame());
707 }
708
709 // If the SiteInstance for the final URL doesn't match the one from the
710 // speculatively created RenderFrameHost, create a new RenderFrameHost using
711 // this new SiteInstance.
712 if (!speculative_render_frame_host_ ||
713 speculative_render_frame_host_->GetSiteInstance() !=
714 new_instance.get()) {
715 CleanUpNavigation();
716 // TODO(carlosk): Replace the binding value with the right one.
717 bool success = CreateSpeculativeRenderFrameHost(
718 url, current_instance, new_instance.get(),
719 NavigationEntryImpl::kInvalidBindings);
720 DCHECK(success);
721 }
722 DCHECK(speculative_render_frame_host_);
723 rfh_for_navigation = speculative_render_frame_host_.get();
724 }
725 DCHECK(rfh_for_navigation);
726
727 // If the renderer that needs to navigate is not live (it was just created
728 // or it crashed), initialize it.
729 if (!rfh_for_navigation->render_view_host()->IsRenderViewLive()) {
Charlie Reis 2015/01/12 23:30:52 Why not IsRenderFrameLive() on the RFH, as above?
carlosk 2015/01/13 15:54:12 Replaced. I think I copied these two snippets from
Charlie Reis 2015/01/13 18:48:21 Oh, I see. I guess we left that case as IsRenderV
carlosk 2015/01/14 10:09:46 Acknowledged.
644 // Recreate the opener chain. 730 // Recreate the opener chain.
645 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager( 731 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
646 render_frame_host->GetSiteInstance()); 732 rfh_for_navigation->GetSiteInstance());
647 if (!InitRenderView(render_frame_host->render_view_host(), 733 if (!InitRenderView(rfh_for_navigation->render_view_host(), opener_route_id,
648 opener_route_id, 734 MSG_ROUTING_NONE, frame_tree_node_->IsMainFrame())) {
649 MSG_ROUTING_NONE,
650 frame_tree_node_->IsMainFrame())) {
651 return nullptr; 735 return nullptr;
652 } 736 }
653 } 737 }
654 return render_frame_host; 738
739 return rfh_for_navigation;
740 }
741
742 // PlzNavigate
743 void RenderFrameHostManager::CleanUpNavigation() {
744 scoped_ptr<RenderFrameHostImpl> rfh = UnsetSpeculativeRenderFrameHost();
Charlie Reis 2015/01/12 23:30:52 As mentioned below, this should be: if (speculativ
carlosk 2015/01/13 15:54:13 The reason I did it this way was to cover the case
Charlie Reis 2015/01/13 18:48:21 Acknowledged.
745 if (rfh)
746 DiscardUnusedFrame(rfh.Pass());
747 }
748
749 // PlzNavigate
750 scoped_ptr<RenderFrameHostImpl>
751 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() {
752 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
753 switches::kEnableBrowserSideNavigation));
754 if (speculative_web_ui_)
755 speculative_web_ui_.reset();
756 should_reuse_web_ui_ = false;
757 if (speculative_render_frame_host_) {
Charlie Reis 2015/01/12 23:30:52 Seems like we shouldn't call this unless there is
carlosk 2015/01/13 15:54:12 Now this one sounds a bit too risky for the potent
Charlie Reis 2015/01/13 18:48:21 I disagree. If we're calling this method with no
carlosk 2015/01/14 10:09:47 Done.
758 speculative_render_frame_host_->GetProcess()->RemovePendingView();
759 return speculative_render_frame_host_.Pass();
760 }
761 return nullptr;
655 } 762 }
656 763
657 void RenderFrameHostManager::OnDidStartLoading() { 764 void RenderFrameHostManager::OnDidStartLoading() {
658 for (const auto& pair : proxy_hosts_) { 765 for (const auto& pair : proxy_hosts_) {
659 pair.second->Send( 766 pair.second->Send(
660 new FrameMsg_DidStartLoading(pair.second->GetRoutingID())); 767 new FrameMsg_DidStartLoading(pair.second->GetRoutingID()));
661 } 768 }
662 } 769 }
663 770
664 void RenderFrameHostManager::OnDidStopLoading() { 771 void RenderFrameHostManager::OnDidStopLoading() {
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 1157
1051 if (delegate_->IsHidden()) 1158 if (delegate_->IsHidden())
1052 create_render_frame_flags |= CREATE_RF_HIDDEN; 1159 create_render_frame_flags |= CREATE_RF_HIDDEN;
1053 1160
1054 int opener_route_id = 1161 int opener_route_id =
1055 CreateOpenerRenderViewsIfNeeded(old_instance, new_instance); 1162 CreateOpenerRenderViewsIfNeeded(old_instance, new_instance);
1056 1163
1057 if (pending_render_frame_host_) 1164 if (pending_render_frame_host_)
1058 CancelPending(); 1165 CancelPending();
1059 1166
1060 // Create a non-swapped-out RFH with the given opener. 1167 // Create a non swapped out RFH with the given opener.
Charlie Reis 2015/01/12 23:30:52 No extra churn, please.
carlosk 2015/01/13 15:54:13 Done.
1061 pending_render_frame_host_ = 1168 pending_render_frame_host_ =
1062 CreateRenderFrame(new_instance, pending_web_ui(), opener_route_id, 1169 CreateRenderFrame(new_instance, pending_web_ui(), opener_route_id,
1063 create_render_frame_flags, nullptr); 1170 create_render_frame_flags, nullptr);
1064 } 1171 }
1065 1172
1066 int RenderFrameHostManager::CreateOpenerRenderViewsIfNeeded( 1173 int RenderFrameHostManager::CreateOpenerRenderViewsIfNeeded(
1067 SiteInstance* old_instance, 1174 SiteInstance* old_instance,
1068 SiteInstance* new_instance) { 1175 SiteInstance* new_instance) {
1069 int opener_route_id = MSG_ROUTING_NONE; 1176 int opener_route_id = MSG_ROUTING_NONE;
1070 if (new_instance->IsRelatedSiteInstance(old_instance)) { 1177 if (new_instance->IsRelatedSiteInstance(old_instance)) {
(...skipping 16 matching lines...) Expand all
1087 int frame_routing_id, 1194 int frame_routing_id,
1088 int flags) { 1195 int flags) {
1089 if (frame_routing_id == MSG_ROUTING_NONE) 1196 if (frame_routing_id == MSG_ROUTING_NONE)
1090 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID(); 1197 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID();
1091 1198
1092 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); 1199 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
1093 bool hidden = !!(flags & CREATE_RF_HIDDEN); 1200 bool hidden = !!(flags & CREATE_RF_HIDDEN);
1094 1201
1095 // Create a RVH for main frames, or find the existing one for subframes. 1202 // Create a RVH for main frames, or find the existing one for subframes.
1096 FrameTree* frame_tree = frame_tree_node_->frame_tree(); 1203 FrameTree* frame_tree = frame_tree_node_->frame_tree();
1097 RenderViewHostImpl* render_view_host = NULL; 1204 RenderViewHostImpl* render_view_host = nullptr;
1098 if (frame_tree_node_->IsMainFrame()) { 1205 if (frame_tree_node_->IsMainFrame()) {
1099 render_view_host = frame_tree->CreateRenderViewHost( 1206 render_view_host = frame_tree->CreateRenderViewHost(
1100 site_instance, view_routing_id, frame_routing_id, swapped_out, hidden); 1207 site_instance, view_routing_id, frame_routing_id, swapped_out, hidden);
1101 } else { 1208 } else {
1102 render_view_host = frame_tree->GetRenderViewHost(site_instance); 1209 render_view_host = frame_tree->GetRenderViewHost(site_instance);
1103 1210
1104 CHECK(render_view_host); 1211 CHECK(render_view_host);
1105 } 1212 }
1106 1213
1107 // TODO(creis): Pass hidden to RFH. 1214 // TODO(creis): Pass hidden to RFH.
1108 scoped_ptr<RenderFrameHostImpl> render_frame_host = 1215 scoped_ptr<RenderFrameHostImpl> render_frame_host =
1109 make_scoped_ptr(RenderFrameHostFactory::Create( 1216 make_scoped_ptr(RenderFrameHostFactory::Create(
1110 render_view_host, render_frame_delegate_, frame_tree, 1217 render_view_host, render_frame_delegate_, frame_tree,
1111 frame_tree_node_, frame_routing_id, flags).release()); 1218 frame_tree_node_, frame_routing_id, flags).release());
1112 return render_frame_host.Pass(); 1219 return render_frame_host.Pass();
1113 } 1220 }
1114 1221
1222 // PlzNavigate
1223 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
1224 const GURL& url,
1225 SiteInstance* old_instance,
1226 SiteInstance* new_instance,
1227 int bindings) {
1228 CHECK(new_instance);
1229 CHECK_NE(old_instance, new_instance);
1230
1231 const NavigationEntry* current_navigation_entry =
1232 delegate_->GetLastCommittedNavigationEntryForRenderManager();
1233 scoped_ptr<WebUIImpl> new_web_ui;
1234 should_reuse_web_ui_ = ShouldReuseWebUI(current_navigation_entry, url);
1235 if (!should_reuse_web_ui_)
1236 new_web_ui = CreateWebUI(url, bindings);
1237
1238 int opener_route_id =
1239 CreateOpenerRenderViewsIfNeeded(old_instance, new_instance);
1240
1241 int create_render_frame_flags = 0;
1242 if (frame_tree_node_->IsMainFrame())
1243 create_render_frame_flags |= CREATE_RF_FOR_MAIN_FRAME_NAVIGATION;
1244 if (delegate_->IsHidden())
1245 create_render_frame_flags |= CREATE_RF_HIDDEN;
1246 scoped_ptr<RenderFrameHostImpl> new_render_frame_host =
1247 CreateRenderFrame(new_instance, new_web_ui.get(), opener_route_id,
1248 create_render_frame_flags, nullptr);
1249
1250 if (!new_render_frame_host)
1251 return false;
1252
1253 speculative_render_frame_host_ = new_render_frame_host.Pass();
1254 speculative_web_ui_ = new_web_ui.Pass();
1255 return true;
1256 }
1257
1115 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame( 1258 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
1116 SiteInstance* instance, 1259 SiteInstance* instance,
1117 WebUIImpl* web_ui, 1260 WebUIImpl* web_ui,
1118 int opener_route_id, 1261 int opener_route_id,
1119 int flags, 1262 int flags,
1120 int* view_routing_id_ptr) { 1263 int* view_routing_id_ptr) {
1121 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); 1264 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
1122 CHECK(instance); 1265 CHECK(instance);
1123 // Swapped out views should always be hidden. 1266 // Swapped out views should always be hidden.
1124 DCHECK(!swapped_out || (flags & CREATE_RF_HIDDEN)); 1267 DCHECK(!swapped_out || (flags & CREATE_RF_HIDDEN));
1125 1268
1126 // TODO(nasko): Remove the following CHECK once cross-site navigation no 1269 // TODO(nasko): Remove the following CHECK once cross-site navigation no
1127 // longer relies on swapped out RFH for the top-level frame. 1270 // longer relies on swapped out RFH for the top-level frame.
1128 if (!frame_tree_node_->IsMainFrame()) 1271 if (!frame_tree_node_->IsMainFrame())
1129 CHECK(!swapped_out); 1272 CHECK(!swapped_out);
1130 1273
1131 scoped_ptr<RenderFrameHostImpl> new_render_frame_host; 1274 scoped_ptr<RenderFrameHostImpl> new_render_frame_host;
1132 bool success = true; 1275 bool success = true;
1133 if (view_routing_id_ptr) 1276 if (view_routing_id_ptr)
1134 *view_routing_id_ptr = MSG_ROUTING_NONE; 1277 *view_routing_id_ptr = MSG_ROUTING_NONE;
1135 1278
1136 // We are creating a pending or swapped out RFH here. We should never create 1279 // We are creating a pending, speculative or swapped out RFH here. We should
1137 // it in the same SiteInstance as our current RFH. 1280 // never create it in the same SiteInstance as our current RFH.
1138 CHECK_NE(render_frame_host_->GetSiteInstance(), instance); 1281 CHECK_NE(render_frame_host_->GetSiteInstance(), instance);
1139 1282
1140 // Check if we've already created an RFH for this SiteInstance. If so, try 1283 // 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 1284 // 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. 1285 // remove it from the list of proxy hosts below if it will be active.
1143 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance); 1286 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
1144 if (proxy && proxy->render_frame_host()) { 1287 if (proxy && proxy->render_frame_host()) {
1145 if (view_routing_id_ptr) 1288 if (view_routing_id_ptr)
1146 *view_routing_id_ptr = proxy->GetRenderViewHost()->GetRoutingID(); 1289 *view_routing_id_ptr = proxy->GetRenderViewHost()->GetRoutingID();
1147 // Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost. 1290 // Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost.
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1240 1383
1241 bool RenderFrameHostManager::InitRenderView( 1384 bool RenderFrameHostManager::InitRenderView(
1242 RenderViewHostImpl* render_view_host, 1385 RenderViewHostImpl* render_view_host,
1243 int opener_route_id, 1386 int opener_route_id,
1244 int proxy_routing_id, 1387 int proxy_routing_id,
1245 bool for_main_frame_navigation) { 1388 bool for_main_frame_navigation) {
1246 // We may have initialized this RenderViewHost for another RenderFrameHost. 1389 // We may have initialized this RenderViewHost for another RenderFrameHost.
1247 if (render_view_host->IsRenderViewLive()) 1390 if (render_view_host->IsRenderViewLive())
1248 return true; 1391 return true;
1249 1392
1250 // If the pending navigation is to a WebUI and the RenderView is not in a 1393 // 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 1394 // guest process, tell the RenderViewHost about any bindings it will need
1252 // enabled. 1395 // enabled.
1253 if (pending_web_ui() && !render_view_host->GetProcess()->IsIsolatedGuest()) { 1396 WebUIImpl* future_web_ui;
Charlie Reis 2015/01/12 23:30:52 dest_web_ui = nullptr;
carlosk 2015/01/13 15:54:13 Done.
1254 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); 1397 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1398 switches::kEnableBrowserSideNavigation)) {
1399 future_web_ui =
1400 should_reuse_web_ui_ ? web_ui_.get() : speculative_web_ui_.get();
1401 } else {
1402 future_web_ui = pending_web_ui();
1403 }
1404 if (future_web_ui && !render_view_host->GetProcess()->IsIsolatedGuest()) {
1405 render_view_host->AllowBindings(future_web_ui->GetBindings());
1255 } else { 1406 } else {
1256 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled 1407 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
1257 // process unless it's swapped out. 1408 // process unless it's swapped out.
1258 if (render_view_host->is_active()) { 1409 if (render_view_host->is_active()) {
1259 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 1410 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1260 render_view_host->GetProcess()->GetID())); 1411 render_view_host->GetProcess()->GetID()));
1261 } 1412 }
1262 } 1413 }
1263 1414
1264 return delegate_->CreateRenderViewForRenderManager(render_view_host, 1415 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()); 1457 proxy_hosts_.find(site_instance->GetId());
1307 if (iter != proxy_hosts_.end()) 1458 if (iter != proxy_hosts_.end())
1308 return iter->second->GetRoutingID(); 1459 return iter->second->GetRoutingID();
1309 1460
1310 return MSG_ROUTING_NONE; 1461 return MSG_ROUTING_NONE;
1311 } 1462 }
1312 1463
1313 void RenderFrameHostManager::CommitPending() { 1464 void RenderFrameHostManager::CommitPending() {
1314 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", 1465 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending",
1315 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 1466 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
1467 bool browser_side_navigation =
1468 base::CommandLine::ForCurrentProcess()->HasSwitch(
1469 switches::kEnableBrowserSideNavigation);
1316 // First check whether we're going to want to focus the location bar after 1470 // 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 1471 // 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 1472 // 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. 1473 // this triggers won't be able to figure out what's going on.
1320 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 1474 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
1321 1475
1322 // Next commit the Web UI, if any. Either replace |web_ui_| with 1476 if (!browser_side_navigation) {
1323 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or 1477 DCHECK(!speculative_web_ui_);
1324 // leave |web_ui_| as is if reusing it. 1478 // Next commit the Web UI, if any. Either replace |web_ui_| with
1325 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); 1479 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
1326 if (pending_web_ui_) { 1480 // leave |web_ui_| as is if reusing it.
1327 web_ui_.reset(pending_web_ui_.release()); 1481 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get()));
1328 } else if (!pending_and_current_web_ui_.get()) { 1482 if (pending_web_ui_) {
1329 web_ui_.reset(); 1483 web_ui_.reset(pending_web_ui_.release());
1484 } else if (!pending_and_current_web_ui_.get()) {
1485 web_ui_.reset();
1486 } else {
1487 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
1488 pending_and_current_web_ui_.reset();
1489 }
1330 } else { 1490 } else {
1331 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); 1491 // PlzNavigate
1332 pending_and_current_web_ui_.reset(); 1492 if (!should_reuse_web_ui_)
1493 web_ui_.reset(speculative_web_ui_.release());
1494 DCHECK(!speculative_web_ui_);
1333 } 1495 }
1334 1496
1335 // It's possible for the pending_render_frame_host_ to be NULL when we aren't 1497 // 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 1498 // aren't crossing process boundaries. If so, we just needed to handle the Web
1337 // committing above and we're done. 1499 // UI committing above and we're done.
1338 if (!pending_render_frame_host_) { 1500 if (!pending_render_frame_host_ && !speculative_render_frame_host_) {
1339 if (will_focus_location_bar) 1501 if (will_focus_location_bar)
1340 delegate_->SetFocusToLocationBar(false); 1502 delegate_->SetFocusToLocationBar(false);
1341 return; 1503 return;
1342 } 1504 }
1343 1505
1344 // Remember if the page was focused so we can focus the new renderer in 1506 // Remember if the page was focused so we can focus the new renderer in
1345 // that case. 1507 // that case.
1346 bool focus_render_view = !will_focus_location_bar && 1508 bool focus_render_view = !will_focus_location_bar &&
1347 render_frame_host_->render_view_host()->GetView() && 1509 render_frame_host_->render_view_host()->GetView() &&
1348 render_frame_host_->render_view_host()->GetView()->HasFocus(); 1510 render_frame_host_->render_view_host()->GetView()->HasFocus();
1349 1511
1350 bool is_main_frame = frame_tree_node_->IsMainFrame(); 1512 bool is_main_frame = frame_tree_node_->IsMainFrame();
1351 1513
1352 // Swap in the pending frame and make it active. Also ensure the FrameTree 1514 // Swap in the pending or speculative frame and make it active. Also ensure
1353 // stays in sync. 1515 // the FrameTree stays in sync.
1354 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = 1516 scoped_ptr<RenderFrameHostImpl> old_render_frame_host;
1355 SetRenderFrameHost(pending_render_frame_host_.Pass()); 1517 if (!browser_side_navigation) {
1518 DCHECK(!speculative_render_frame_host_);
1519 old_render_frame_host =
1520 SetRenderFrameHost(pending_render_frame_host_.Pass());
1521 } else {
1522 // PlzNavigate
1523 DCHECK(speculative_render_frame_host_);
1524 old_render_frame_host =
1525 SetRenderFrameHost(speculative_render_frame_host_.Pass());
1526 }
1527
1356 if (is_main_frame) 1528 if (is_main_frame)
1357 render_frame_host_->render_view_host()->AttachToFrameTree(); 1529 render_frame_host_->render_view_host()->AttachToFrameTree();
1358 1530
1359 // The process will no longer try to exit, so we can decrement the count. 1531 // The process will no longer try to exit, so we can decrement the count.
1360 render_frame_host_->GetProcess()->RemovePendingView(); 1532 render_frame_host_->GetProcess()->RemovePendingView();
1361 1533
1362 // Show the new view (or a sad tab) if necessary. 1534 // Show the new view (or a sad tab) if necessary.
1363 bool new_rfh_has_view = !!render_frame_host_->render_view_host()->GetView(); 1535 bool new_rfh_has_view = !!render_frame_host_->render_view_host()->GetView();
1364 if (!delegate_->IsHidden() && new_rfh_has_view) { 1536 if (!delegate_->IsHidden() && new_rfh_has_view) {
1365 // In most cases, we need to show the new view. 1537 // 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( 1663 TRACE_EVENT_INSTANT2(
1492 "navigation", 1664 "navigation",
1493 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", 1665 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance",
1494 TRACE_EVENT_SCOPE_THREAD, 1666 TRACE_EVENT_SCOPE_THREAD,
1495 "current_instance id", current_instance->GetId(), 1667 "current_instance id", current_instance->GetId(),
1496 "new_instance id", new_instance->GetId()); 1668 "new_instance id", new_instance->GetId());
1497 1669
1498 // New SiteInstance: create a pending RFH to navigate. 1670 // New SiteInstance: create a pending RFH to navigate.
1499 DCHECK(!cross_navigation_pending_); 1671 DCHECK(!cross_navigation_pending_);
1500 1672
1501 // This will possibly create (set to NULL) a Web UI object for the pending 1673 // 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 1674 // 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. 1675 // 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(), 1676 // bindings. It must also happen after the above conditional call to
1505 // otherwise CancelPending may clear the pending_web_ui_ and the page will 1677 // CancelPending(), otherwise CancelPending may clear the pending_web_ui_
1506 // not have its bindings set appropriately. 1678 // and the page will not have its bindings set appropriately.
1507 SetPendingWebUI(dest_url, bindings); 1679 SetPendingWebUI(dest_url, bindings);
1508 CreatePendingRenderFrameHost(current_instance, new_instance.get(), 1680 CreatePendingRenderFrameHost(current_instance, new_instance.get(),
1509 frame_tree_node_->IsMainFrame()); 1681 frame_tree_node_->IsMainFrame());
1510 if (!pending_render_frame_host_.get()) { 1682 if (!pending_render_frame_host_.get()) {
1511 return NULL; 1683 return nullptr;
1512 } 1684 }
1513 1685
1514 // Check if our current RFH is live before we set up a transition. 1686 // Check if our current RFH is live before we set up a transition.
1515 if (!render_frame_host_->IsRenderFrameLive()) { 1687 if (!render_frame_host_->IsRenderFrameLive()) {
1516 if (!cross_navigation_pending_) { 1688 if (!cross_navigation_pending_) {
1517 // The current RFH is not live. There's no reason to sit around with a 1689 // 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 1690 // 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 1691 // 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 1692 // cross-navigating (Note that we don't care about on{before}unload
1521 // handlers if the current RFH isn't live.) 1693 // handlers if the current RFH isn't live.)
1522 CommitPending(); 1694 CommitPending();
1523 return render_frame_host_.get(); 1695 return render_frame_host_.get();
1524 } else { 1696 } else {
1525 NOTREACHED(); 1697 NOTREACHED();
1526 return render_frame_host_.get(); 1698 return render_frame_host_.get();
1527 } 1699 }
1528 } 1700 }
1529 // Otherwise, it's safe to treat this as a pending cross-site transition. 1701 // Otherwise, it's safe to treat this as a pending cross-site transition.
1530 1702
1531 // We now have a pending RFH. 1703 // We now have a pending RFH.
1532 DCHECK(!cross_navigation_pending_); 1704 DCHECK(!cross_navigation_pending_);
1533 cross_navigation_pending_ = true; 1705 cross_navigation_pending_ = true;
1534 1706
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 1707 // 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). 1708 // 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 1709 // 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 1710 // Navigate message) until we hear back from the old renderer's
1547 // beforeunload handler. If the handler returns false, we'll have to 1711 // beforeunload handler. If the handler returns false, we'll have to
1548 // cancel the request. 1712 // cancel the request.
1549 // 1713 //
1550 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); 1714 DCHECK(!pending_render_frame_host_->are_navigations_suspended());
1551 bool is_transfer = transferred_request_id != GlobalRequestID(); 1715 bool is_transfer = transferred_request_id != GlobalRequestID();
1552 if (is_transfer) { 1716 if (is_transfer) {
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1707 void RenderFrameHostManager::DeleteRenderFrameProxyHost( 1871 void RenderFrameHostManager::DeleteRenderFrameProxyHost(
1708 SiteInstance* instance) { 1872 SiteInstance* instance) {
1709 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId()); 1873 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId());
1710 if (iter != proxy_hosts_.end()) { 1874 if (iter != proxy_hosts_.end()) {
1711 delete iter->second; 1875 delete iter->second;
1712 proxy_hosts_.erase(iter); 1876 proxy_hosts_.erase(iter);
1713 } 1877 }
1714 } 1878 }
1715 1879
1716 } // namespace content 1880 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698