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

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, added simple test, other minor changes. Created 6 years, 1 month 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 render_widget_delegate_(render_widget_delegate), 62 render_widget_delegate_(render_widget_delegate),
63 interstitial_page_(NULL), 63 interstitial_page_(NULL),
64 weak_factory_(this) { 64 weak_factory_(this) {
65 DCHECK(frame_tree_node_); 65 DCHECK(frame_tree_node_);
66 } 66 }
67 67
68 RenderFrameHostManager::~RenderFrameHostManager() { 68 RenderFrameHostManager::~RenderFrameHostManager() {
69 if (pending_render_frame_host_) 69 if (pending_render_frame_host_)
70 CancelPending(); 70 CancelPending();
71 71
72 if (CommandLine::ForCurrentProcess()->HasSwitch(
73 switches::kEnableBrowserSideNavigation)) {
74 CleanUpSpeculativeRenderFrameHost();
75 }
76
72 // We should always have a current RenderFrameHost except in some tests. 77 // We should always have a current RenderFrameHost except in some tests.
73 SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>()); 78 SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>());
74 79
75 // Delete any swapped out RenderFrameHosts. 80 // Delete any swapped out RenderFrameHosts.
76 STLDeleteValues(&proxy_hosts_); 81 STLDeleteValues(&proxy_hosts_);
77 } 82 }
78 83
79 void RenderFrameHostManager::Init(BrowserContext* browser_context, 84 void RenderFrameHostManager::Init(BrowserContext* browser_context,
80 SiteInstance* site_instance, 85 SiteInstance* site_instance,
81 int view_routing_id, 86 int view_routing_id,
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 // is ok to do nothing here. 305 // is ok to do nothing here.
301 if (pending_render_frame_host_ && 306 if (pending_render_frame_host_ &&
302 pending_render_frame_host_->are_navigations_suspended()) { 307 pending_render_frame_host_->are_navigations_suspended()) {
303 pending_render_frame_host_->SetNavigationsSuspended(false, 308 pending_render_frame_host_->SetNavigationsSuspended(false,
304 proceed_time); 309 proceed_time);
305 } 310 }
306 } else { 311 } else {
307 // Current page says to cancel. 312 // Current page says to cancel.
308 CancelPending(); 313 CancelPending();
309 cross_navigation_pending_ = false; 314 cross_navigation_pending_ = false;
315 if (CommandLine::ForCurrentProcess()->HasSwitch(
316 switches::kEnableBrowserSideNavigation)) {
317 CleanUpSpeculativeRenderFrameHost();
318 }
310 } 319 }
311 } else { 320 } else {
312 // Non-cross site transition means closing the entire tab. 321 // Non-cross site transition means closing the entire tab.
313 bool proceed_to_fire_unload; 322 bool proceed_to_fire_unload;
314 delegate_->BeforeUnloadFiredFromRenderManager(proceed, proceed_time, 323 delegate_->BeforeUnloadFiredFromRenderManager(proceed, proceed_time,
315 &proceed_to_fire_unload); 324 &proceed_to_fire_unload);
316 325
317 if (proceed_to_fire_unload) { 326 if (proceed_to_fire_unload) {
318 // If we're about to close the tab and there's a pending RFH, cancel it. 327 // If we're about to close the tab and there's a pending RFH, cancel it.
319 // Otherwise, if the navigation in the pending RFH completes before the 328 // Otherwise, if the navigation in the pending RFH completes before the
320 // close in the current RFH, we'll lose the tab close. 329 // close in the current RFH, we'll lose the tab close.
321 if (pending_render_frame_host_) { 330 if (pending_render_frame_host_) {
322 CancelPending(); 331 CancelPending();
323 cross_navigation_pending_ = false; 332 cross_navigation_pending_ = false;
333 if (CommandLine::ForCurrentProcess()->HasSwitch(
334 switches::kEnableBrowserSideNavigation)) {
335 CleanUpSpeculativeRenderFrameHost();
336 }
324 } 337 }
325 338
326 // This is not a cross-site navigation, the tab is being closed. 339 // This is not a cross-site navigation, the tab is being closed.
327 render_frame_host_->render_view_host()->ClosePage(); 340 render_frame_host_->render_view_host()->ClosePage();
328 } 341 }
329 } 342 }
330 } 343 }
331 344
332 void RenderFrameHostManager::OnCrossSiteResponse( 345 void RenderFrameHostManager::OnCrossSiteResponse(
333 RenderFrameHostImpl* pending_render_frame_host, 346 RenderFrameHostImpl* pending_render_frame_host,
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 425
413 response_started_id_.reset(); 426 response_started_id_.reset();
414 } 427 }
415 428
416 void RenderFrameHostManager::ClearNavigationTransitionData() { 429 void RenderFrameHostManager::ClearNavigationTransitionData() {
417 render_frame_host_->ClearPendingTransitionRequestData(); 430 render_frame_host_->ClearPendingTransitionRequestData();
418 } 431 }
419 432
420 void RenderFrameHostManager::DidNavigateFrame( 433 void RenderFrameHostManager::DidNavigateFrame(
421 RenderFrameHostImpl* render_frame_host) { 434 RenderFrameHostImpl* render_frame_host) {
435 DCHECK(render_frame_host);
436 if (CommandLine::ForCurrentProcess()->HasSwitch(
437 switches::kEnableBrowserSideNavigation)) {
438 if (speculative_render_frame_host_.get() == render_frame_host) {
439 CommitPending(true);
440 return;
441 }
442 CleanUpSpeculativeRenderFrameHost();
443 }
444
422 if (!cross_navigation_pending_) { 445 if (!cross_navigation_pending_) {
423 DCHECK(!pending_render_frame_host_); 446 DCHECK(!pending_render_frame_host_);
424 447
425 // We should only hear this from our current renderer. 448 // We should only hear this from our current renderer.
426 DCHECK_EQ(render_frame_host_, render_frame_host); 449 DCHECK_EQ(render_frame_host_, render_frame_host);
427 450
428 // Even when there is no pending RVH, there may be a pending Web UI. 451 // Even when there is no pending RVH, there may be a pending Web UI.
429 if (pending_web_ui()) 452 if (pending_web_ui())
430 CommitPending(); 453 CommitPending(false);
431 return; 454 return;
432 } 455 }
433 456
434 if (render_frame_host == pending_render_frame_host_) { 457 if (render_frame_host == pending_render_frame_host_) {
435 // The pending cross-site navigation completed, so show the renderer. 458 // The pending cross-site navigation completed, so show the renderer.
436 CommitPending(); 459 CommitPending(false);
437 cross_navigation_pending_ = false; 460 cross_navigation_pending_ = false;
438 } else if (render_frame_host == render_frame_host_) { 461 } else if (render_frame_host == render_frame_host_) {
439 // A navigation in the original page has taken place. Cancel the pending 462 // A navigation in the original page has taken place. Cancel the pending
440 // one. 463 // one.
441 CancelPending(); 464 CancelPending();
442 cross_navigation_pending_ = false; 465 cross_navigation_pending_ = false;
443 } else { 466 } else {
444 // No one else should be sending us DidNavigate in this state. 467 // No one else should be sending us DidNavigate in this state.
445 DCHECK(false); 468 DCHECK(false);
446 } 469 }
447 } 470 }
448 471
472 void RenderFrameHostManager::CancelNavigation() {
473 CleanUpSpeculativeRenderFrameHost();
474 }
475
449 void RenderFrameHostManager::DidDisownOpener( 476 void RenderFrameHostManager::DidDisownOpener(
450 RenderFrameHost* render_frame_host) { 477 RenderFrameHost* render_frame_host) {
451 // Notify all RenderFrameHosts but the one that notified us. This is necessary 478 // Notify all RenderFrameHosts but the one that notified us. This is necessary
452 // in case a process swap has occurred while the message was in flight. 479 // in case a process swap has occurred while the message was in flight.
453 for (RenderFrameProxyHostMap::iterator iter = proxy_hosts_.begin(); 480 for (RenderFrameProxyHostMap::iterator iter = proxy_hosts_.begin();
454 iter != proxy_hosts_.end(); 481 iter != proxy_hosts_.end();
455 ++iter) { 482 ++iter) {
456 DCHECK_NE(iter->second->GetSiteInstance(), 483 DCHECK_NE(iter->second->GetSiteInstance(),
457 current_frame_host()->GetSiteInstance()); 484 current_frame_host()->GetSiteInstance());
458 iter->second->DisownOpener(); 485 iter->second->DisownOpener();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 // We shouldn't get here for subframes, since we only swap subframes when 579 // We shouldn't get here for subframes, since we only swap subframes when
553 // --site-per-process is used. 580 // --site-per-process is used.
554 DCHECK(is_main_frame); 581 DCHECK(is_main_frame);
555 582
556 // The old RenderFrameHost will stay alive inside the proxy so that existing 583 // The old RenderFrameHost will stay alive inside the proxy so that existing
557 // JavaScript window references to it stay valid. 584 // JavaScript window references to it stay valid.
558 proxy->TakeFrameHostOwnership(old_render_frame_host.Pass()); 585 proxy->TakeFrameHostOwnership(old_render_frame_host.Pass());
559 } 586 }
560 } 587 }
561 588
589 void RenderFrameHostManager::RecycleRenderFrameHost(
590 scoped_ptr<RenderFrameHostImpl> render_frame_host) {
591 // TODO(carlosk): this code is very similar to what can be found in
592 // SwapOutOldFrame and we should see that these are unified at some point.
593
594 // If the SiteInstance for the pending RFH is being used by others, don't
595 // delete the RFH, just swap it out and it can be reused at a later point.
596 SiteInstanceImpl* site_instance = render_frame_host->GetSiteInstance();
597 if (site_instance->HasSite() && site_instance->active_frame_count() > 1) {
598 // Any currently suspended navigations are no longer needed.
599 render_frame_host->CancelSuspendedNavigations();
600
601 RenderFrameProxyHost* proxy =
602 new RenderFrameProxyHost(site_instance, frame_tree_node_);
603 proxy_hosts_[site_instance->GetId()] = proxy;
604 render_frame_host->SwapOut(proxy);
605 if (frame_tree_node_->IsMainFrame())
606 proxy->TakeFrameHostOwnership(render_frame_host.Pass());
607 } else {
608 // We won't be coming back, so delete this one.
609 render_frame_host.reset();
610 }
611 }
612
562 void RenderFrameHostManager::MoveToPendingDeleteHosts( 613 void RenderFrameHostManager::MoveToPendingDeleteHosts(
563 scoped_ptr<RenderFrameHostImpl> render_frame_host) { 614 scoped_ptr<RenderFrameHostImpl> render_frame_host) {
564 // |render_frame_host| will be deleted when its SwapOut ACK is received, or 615 // |render_frame_host| will be deleted when its SwapOut ACK is received, or
565 // when the timer times out, or when the RFHM itself is deleted (whichever 616 // when the timer times out, or when the RFHM itself is deleted (whichever
566 // comes first). 617 // comes first).
567 pending_delete_hosts_.push_back( 618 pending_delete_hosts_.push_back(
568 linked_ptr<RenderFrameHostImpl>(render_frame_host.release())); 619 linked_ptr<RenderFrameHostImpl>(render_frame_host.release()));
569 } 620 }
570 621
571 bool RenderFrameHostManager::IsPendingDeletion( 622 bool RenderFrameHostManager::IsPendingDeletion(
(...skipping 15 matching lines...) Expand all
587 return true; 638 return true;
588 } 639 }
589 } 640 }
590 return false; 641 return false;
591 } 642 }
592 643
593 void RenderFrameHostManager::ResetProxyHosts() { 644 void RenderFrameHostManager::ResetProxyHosts() {
594 STLDeleteValues(&proxy_hosts_); 645 STLDeleteValues(&proxy_hosts_);
595 } 646 }
596 647
648 void RenderFrameHostManager::BeginNavigation(
649 const FrameHostMsg_BeginNavigation_Params& params,
650 const CommonNavigationParams& common_params) {
651 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
652 switches::kEnableBrowserSideNavigation));
653 // If there is an ongoing navigation, just clean it up.
clamy 2014/11/14 10:11:09 nit: s/just clean it up/cancel it
carlosk 2014/11/14 17:43:37 Done.
654 CancelNavigation();
655
656 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
657 // TODO(carlosk): Replace the default values by the right ones.
658 scoped_refptr<SiteInstanceImpl> new_instance =
659 static_cast<SiteInstanceImpl*>(GetSiteInstanceForNavigation(
660 common_params.url, NULL, common_params.transition, false, false,
661 true));
662
663 if (new_instance.get() != current_instance) {
664 // Navigating to a new SiteInstance -> speculatively create a new RFH
665
666 // TODO(carlosk): what the TRACE_EVENT_INSTANT2 for New SiteInstance found
667 // in UpdateStateForNavigate be copied here?
668
669 bool success = CreateSpeculativeRenderFrameHost(
670 common_params.url, current_instance, new_instance.get());
671 if (!success)
672 return;
673 } else {
674 // Navigating to the same SiteInstance -> make sure the current RFH is alive
675 DCHECK(render_frame_host_->GetSiteInstance() == new_instance);
676 if (!render_frame_host_->render_view_host()->IsRenderViewLive()) {
677 // Recreate the opener chain.
678 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
679 render_frame_host_->GetSiteInstance());
680 if (!InitRenderView(render_frame_host_->render_view_host(),
681 opener_route_id, MSG_ROUTING_NONE,
682 frame_tree_node_->IsMainFrame())) {
683 return;
684 }
685 }
686 }
687 DCHECK(new_instance->GetProcess()->HasConnection());
688 DCHECK(new_instance->GetProcess()->GetBrowserContext());
689 }
690
691 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
692 const GURL& url,
693 SiteInstance* old_instance,
694 SiteInstance* new_instance) {
695 CHECK(new_instance);
696 CHECK_NE(old_instance, new_instance);
697
698 // TODO(carlosk): should also try to reuse the current web_ui
699 // (ShouldReuseWebUI)?
700 scoped_ptr<WebUIImpl> new_web_ui(delegate_->CreateWebUIForRenderManager(url));
701 // TODO(carlosk): confirm this next section copied from SetPendingWebUI
702 // is in fact needed... I need access to the respective navigation entry
703 // though.
704 // If we have assigned (zero or more) bindings to this NavigationEntry in the
705 // past, make sure we're not granting it different bindings than it had
706 // before. If so, note it and don't give it any bindings, to avoid a
707 // potential privilege escalation.
708 // if (new_web_ui &&
709 // bindings != NavigationEntryImpl::kInvalidBindings &&
710 // new_web_ui->GetBindings() != bindings) {
711 // RecordAction(
712 // base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
713 // new_web_ui.reset();
714 // }
715
716 scoped_ptr<RenderFrameHostImpl> new_render_frame_host;
717
718 // Check if we've already created an RFH for this SiteInstance. If so, try
719 // to re-use the existing one, which has already been initialized. We'll
720 // remove it from the list of proxy hosts below if it will be active.
721 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(new_instance);
722 if (proxy && proxy->render_frame_host()) {
723 // Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost.
724 // Prevent the process from exiting while we're trying to use it.
725 new_render_frame_host = proxy->PassFrameHostOwnership();
726 new_render_frame_host->GetProcess()->AddPendingView();
727
728 proxy_hosts_.erase(new_instance->GetId());
729 delete proxy;
730
731 // When a new render view is created by the renderer, the new WebContents
732 // gets a RenderViewHost in the SiteInstance of its opener WebContents.
733 // If not used in the first navigation, this RVH is swapped out and is not
734 // granted bindings, so we may need to grant them when swapping it in.
735 if (new_web_ui && !new_render_frame_host->GetProcess()->IsIsolatedGuest()) {
736 int required_bindings = new_web_ui->GetBindings();
737 RenderViewHost* rvh = new_render_frame_host->render_view_host();
738 if ((rvh->GetEnabledBindings() & required_bindings) !=
739 required_bindings) {
740 rvh->AllowBindings(required_bindings);
741 }
742 }
743 } else {
744 // Create a new RenderFrameHost if we don't find an existing one.
745 new_render_frame_host =
746 CreateRenderFrameHost(new_instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE,
747 false, delegate_->IsHidden());
748 DCHECK(new_render_frame_host);
749 RenderViewHostImpl* rvh = new_render_frame_host->render_view_host();
750
751 // Prevent the process from exiting while we're trying to navigate in it.
752 // Otherwise, if the new RFH is swapped out already, store it.
753 new_render_frame_host->GetProcess()->AddPendingView();
754
755 // Ensure that we have created RFHs for the new RFH's opener chain if
756 // we are staying in the same BrowsingInstance. This allows the new RFH
757 // to send cross-process script calls to its opener(s).
758 int opener_route_id = MSG_ROUTING_NONE;
759 if (new_instance->IsRelatedSiteInstance(old_instance)) {
760 opener_route_id =
761 delegate_->CreateOpenerRenderViewsForRenderManager(new_instance);
762 if (CommandLine::ForCurrentProcess()->HasSwitch(
763 switches::kSitePerProcess)) {
764 // Ensure that the frame tree has RenderFrameProxyHosts for the new
765 // SiteInstance in all nodes except the current one.
766 frame_tree_node_->frame_tree()->CreateProxiesForSiteInstance(
767 frame_tree_node_, new_instance);
768 }
769 }
770
771 bool success = InitRenderView(rvh, opener_route_id, MSG_ROUTING_NONE,
772 frame_tree_node_->IsMainFrame());
773 if (success) {
774 if (frame_tree_node_->IsMainFrame()) {
775 // Don't show the main frame's view until we know it will be used.
776 rvh->GetView()->Hide();
777 } else {
778 // Init the RFH, so a RenderFrame is created in the renderer.
779 success = InitRenderFrame(new_render_frame_host.get());
780 }
781 }
782 if (!success)
783 return false;
784
785 render_frame_delegate_->RenderFrameCreated(new_render_frame_host.get());
786 }
787
788 DCHECK(new_render_frame_host->GetSiteInstance() == new_instance);
789 speculative_render_frame_host_.reset(new_render_frame_host.release());
790 speculative_web_ui_.reset(new_web_ui.release());
791 return true;
792 }
793
597 // PlzNavigate 794 // PlzNavigate
598 RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation( 795 RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
599 const GURL& url, 796 const GURL& url,
600 ui::PageTransition transition) { 797 ui::PageTransition transition) {
601 CHECK(CommandLine::ForCurrentProcess()->HasSwitch( 798 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
602 switches::kEnableBrowserSideNavigation)); 799 switches::kEnableBrowserSideNavigation));
603 // TODO(clamy): When we handle renderer initiated navigations, make sure not 800 // TODO(clamy): When we handle renderer initiated navigations, make sure not
604 // to use a different process for subframes if --site-per-process is not 801 // to use a different process for subframes if --site-per-process is not
605 // enabled. 802 // enabled.
606 803
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 controller.GetBrowserContext(), current_entry->GetURL()) == 947 controller.GetBrowserContext(), current_entry->GetURL()) ==
751 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( 948 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
752 controller.GetBrowserContext(), new_url)); 949 controller.GetBrowserContext(), new_url));
753 } 950 }
754 951
755 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation( 952 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
756 const GURL& dest_url, 953 const GURL& dest_url,
757 SiteInstance* dest_instance, 954 SiteInstance* dest_instance,
758 ui::PageTransition dest_transition, 955 ui::PageTransition dest_transition,
759 bool dest_is_restore, 956 bool dest_is_restore,
760 bool dest_is_view_source_mode) { 957 bool dest_is_view_source_mode,
958 bool create_unbounded_site_instance) {
761 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); 959 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
762 SiteInstance* new_instance = current_instance; 960 SiteInstance* new_instance = current_instance;
763 961
764 // We do not currently swap processes for navigations in webview tag guests. 962 // We do not currently swap processes for navigations in webview tag guests.
765 if (current_instance->GetSiteURL().SchemeIs(kGuestScheme)) 963 if (current_instance->GetSiteURL().SchemeIs(kGuestScheme))
766 return current_instance; 964 return current_instance;
767 965
768 // Determine if we need a new BrowsingInstance for this entry. If true, this 966 // Determine if we need a new BrowsingInstance for this entry. If true, this
769 // implies that it will get a new SiteInstance (and likely process), and that 967 // implies that it will get a new SiteInstance (and likely process), and that
770 // other tabs in the current BrowsingInstance will be unable to script it. 968 // other tabs in the current BrowsingInstance will be unable to script it.
(...skipping 11 matching lines...) Expand all
782 bool current_is_view_source_mode = current_entry ? 980 bool current_is_view_source_mode = current_entry ?
783 current_entry->IsViewSourceMode() : dest_is_view_source_mode; 981 current_entry->IsViewSourceMode() : dest_is_view_source_mode;
784 bool force_swap = ShouldSwapBrowsingInstancesForNavigation( 982 bool force_swap = ShouldSwapBrowsingInstancesForNavigation(
785 current_effective_url, 983 current_effective_url,
786 current_is_view_source_mode, 984 current_is_view_source_mode,
787 dest_instance, 985 dest_instance,
788 SiteInstanceImpl::GetEffectiveURL(browser_context, dest_url), 986 SiteInstanceImpl::GetEffectiveURL(browser_context, dest_url),
789 dest_is_view_source_mode); 987 dest_is_view_source_mode);
790 if (ShouldTransitionCrossSite() || force_swap) { 988 if (ShouldTransitionCrossSite() || force_swap) {
791 new_instance = GetSiteInstanceForURL( 989 new_instance = GetSiteInstanceForURL(
792 dest_url, 990 dest_url, dest_instance, dest_transition, dest_is_restore,
793 dest_instance, 991 dest_is_view_source_mode, current_instance, force_swap,
794 dest_transition, 992 create_unbounded_site_instance);
795 dest_is_restore,
796 dest_is_view_source_mode,
797 current_instance,
798 force_swap);
799 } 993 }
800 994
801 // If force_swap is true, we must use a different SiteInstance. If we didn't, 995 // If force_swap is true, we must use a different SiteInstance. If we didn't,
802 // we would have two RenderFrameHosts in the same SiteInstance and the same 996 // we would have two RenderFrameHosts in the same SiteInstance and the same
803 // frame, resulting in page_id conflicts for their NavigationEntries. 997 // frame, resulting in page_id conflicts for their NavigationEntries.
804 if (force_swap) 998 if (force_swap)
805 CHECK_NE(new_instance, current_instance); 999 CHECK_NE(new_instance, current_instance);
806 return new_instance; 1000 return new_instance;
807 } 1001 }
808 1002
809 SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL( 1003 SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
810 const GURL& dest_url, 1004 const GURL& dest_url,
811 SiteInstance* dest_instance, 1005 SiteInstance* dest_instance,
812 ui::PageTransition dest_transition, 1006 ui::PageTransition dest_transition,
813 bool dest_is_restore, 1007 bool dest_is_restore,
814 bool dest_is_view_source_mode, 1008 bool dest_is_view_source_mode,
815 SiteInstance* current_instance, 1009 SiteInstance* current_instance,
816 bool force_browsing_instance_swap) { 1010 bool force_browsing_instance_swap,
1011 bool create_unbounded_site_instance) {
817 NavigationControllerImpl& controller = 1012 NavigationControllerImpl& controller =
818 delegate_->GetControllerForRenderManager(); 1013 delegate_->GetControllerForRenderManager();
819 BrowserContext* browser_context = controller.GetBrowserContext(); 1014 BrowserContext* browser_context = controller.GetBrowserContext();
820 1015
821 // If the entry has an instance already we should use it. 1016 // If the entry has an instance already we should use it.
822 if (dest_instance) { 1017 if (dest_instance) {
823 // If we are forcing a swap, this should be in a different BrowsingInstance. 1018 // If we are forcing a swap, this should be in a different BrowsingInstance.
824 if (force_browsing_instance_swap) { 1019 if (force_browsing_instance_swap) {
825 CHECK(!dest_instance->IsRelatedSiteInstance( 1020 CHECK(!dest_instance->IsRelatedSiteInstance(
826 render_frame_host_->GetSiteInstance())); 1021 render_frame_host_->GetSiteInstance()));
827 } 1022 }
828 return dest_instance; 1023 return dest_instance;
829 } 1024 }
830 1025
1026 SiteInstanceImpl* current_site_instance =
1027 static_cast<SiteInstanceImpl*>(current_instance);
1028
831 // If a swap is required, we need to force the SiteInstance AND 1029 // If a swap is required, we need to force the SiteInstance AND
832 // BrowsingInstance to be different ones, using CreateForURL. 1030 // BrowsingInstance to be different ones, using CreateForURL.
833 if (force_browsing_instance_swap) 1031 if (force_browsing_instance_swap) {
834 return SiteInstance::CreateForURL(browser_context, dest_url); 1032 return CreateSiteInstanceForURL(browser_context, dest_url,
1033 create_unbounded_site_instance,
1034 current_site_instance);
1035 }
835 1036
836 // (UGLY) HEURISTIC, process-per-site only: 1037 // (UGLY) HEURISTIC, process-per-site only:
837 // 1038 //
838 // If this navigation is generated, then it probably corresponds to a search 1039 // If this navigation is generated, then it probably corresponds to a search
839 // query. Given that search results typically lead to users navigating to 1040 // query. Given that search results typically lead to users navigating to
840 // other sites, we don't really want to use the search engine hostname to 1041 // other sites, we don't really want to use the search engine hostname to
841 // determine the site instance for this navigation. 1042 // determine the site instance for this navigation.
842 // 1043 //
843 // NOTE: This can be removed once we have a way to transition between 1044 // NOTE: This can be removed once we have a way to transition between
844 // RenderViews in response to a link click. 1045 // RenderViews in response to a link click.
845 // 1046 //
846 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) && 1047 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) &&
847 ui::PageTransitionCoreTypeIs( 1048 ui::PageTransitionCoreTypeIs(
848 dest_transition, ui::PAGE_TRANSITION_GENERATED)) { 1049 dest_transition, ui::PAGE_TRANSITION_GENERATED)) {
849 return current_instance; 1050 return current_instance;
850 } 1051 }
851 1052
852 SiteInstanceImpl* current_site_instance =
853 static_cast<SiteInstanceImpl*>(current_instance);
854
855 // If we haven't used our SiteInstance (and thus RVH) yet, then we can use it 1053 // If we haven't used our SiteInstance (and thus RVH) yet, then we can use it
856 // for this entry. We won't commit the SiteInstance to this site until the 1054 // for this entry. We won't commit the SiteInstance to this site until the
857 // navigation commits (in DidNavigate), unless the navigation entry was 1055 // navigation commits (in DidNavigate), unless the navigation entry was
858 // restored or it's a Web UI as described below. 1056 // restored or it's a Web UI as described below.
859 if (!current_site_instance->HasSite()) { 1057 if (!current_site_instance->HasSite()) {
860 // If we've already created a SiteInstance for our destination, we don't 1058 // If we've already created a SiteInstance for our destination, we don't
861 // want to use this unused SiteInstance; use the existing one. (We don't 1059 // want to use this unused SiteInstance; use the existing one. (We don't
862 // do this check if the current_instance has a site, because for now, we 1060 // do this check if the current_instance has a site, because for now, we
863 // want to compare against the current URL and not the SiteInstance's site. 1061 // want to compare against the current URL and not the SiteInstance's site.
864 // In this case, there is no current URL, so comparing against the site is 1062 // In this case, there is no current URL, so comparing against the site is
865 // ok. See additional comments below.) 1063 // ok. See additional comments below.)
866 // 1064 //
867 // Also, if the URL should use process-per-site mode and there is an 1065 // Also, if the URL should use process-per-site mode and there is an
868 // existing process for the site, we should use it. We can call 1066 // existing process for the site, we should use it. We can call
869 // GetRelatedSiteInstance() for this, which will eagerly set the site and 1067 // GetRelatedSiteInstance() for this, which will eagerly set the site and
870 // thus use the correct process. 1068 // thus use the correct process.
871 bool use_process_per_site = 1069 bool use_process_per_site =
872 RenderProcessHost::ShouldUseProcessPerSite(browser_context, dest_url) && 1070 RenderProcessHost::ShouldUseProcessPerSite(browser_context, dest_url) &&
873 RenderProcessHostImpl::GetProcessHostForSite(browser_context, dest_url); 1071 RenderProcessHostImpl::GetProcessHostForSite(browser_context, dest_url);
874 if (current_site_instance->HasRelatedSiteInstance(dest_url) || 1072 if (current_site_instance->HasRelatedSiteInstance(dest_url) ||
875 use_process_per_site) { 1073 use_process_per_site) {
876 return current_site_instance->GetRelatedSiteInstance(dest_url); 1074 return GetRelatedSiteInstanceForURL(current_site_instance, dest_url,
1075 create_unbounded_site_instance);
877 } 1076 }
878 1077
879 // For extensions, Web UI URLs (such as the new tab page), and apps we do 1078 // For extensions, Web UI URLs (such as the new tab page), and apps we do
880 // not want to use the current_instance if it has no site, since it will 1079 // not want to use the current_instance if it has no site, since it will
881 // have a RenderProcessHost of PRIV_NORMAL. Create a new SiteInstance for 1080 // have a RenderProcessHost of PRIV_NORMAL. Create a new SiteInstance for
882 // this URL instead (with the correct process type). 1081 // this URL instead (with the correct process type).
883 if (current_site_instance->HasWrongProcessForURL(dest_url)) 1082 if (current_site_instance->HasWrongProcessForURL(dest_url)) {
884 return current_site_instance->GetRelatedSiteInstance(dest_url); 1083 return GetRelatedSiteInstanceForURL(current_site_instance, dest_url,
1084 create_unbounded_site_instance);
1085 }
885 1086
886 // View-source URLs must use a new SiteInstance and BrowsingInstance. 1087 // View-source URLs must use a new SiteInstance and BrowsingInstance.
887 // TODO(nasko): This is the same condition as later in the function. This 1088 // TODO(nasko): This is the same condition as later in the function. This
888 // should be taken into account when refactoring this method as part of 1089 // should be taken into account when refactoring this method as part of
889 // http://crbug.com/123007. 1090 // http://crbug.com/123007.
890 if (dest_is_view_source_mode) 1091 if (dest_is_view_source_mode) {
891 return SiteInstance::CreateForURL(browser_context, dest_url); 1092 return CreateSiteInstanceForURL(browser_context, dest_url,
1093 create_unbounded_site_instance,
1094 current_site_instance);
1095 }
892 1096
893 // If we are navigating from a blank SiteInstance to a WebUI, make sure we 1097 // If we are navigating from a blank SiteInstance to a WebUI, make sure we
894 // create a new SiteInstance. 1098 // create a new SiteInstance.
895 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( 1099 if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
896 browser_context, dest_url)) { 1100 browser_context, dest_url)) {
897 return SiteInstance::CreateForURL(browser_context, dest_url); 1101 return CreateSiteInstanceForURL(browser_context, dest_url,
1102 create_unbounded_site_instance,
1103 current_site_instance);
898 } 1104 }
899 1105
900 // Normally the "site" on the SiteInstance is set lazily when the load 1106 // Normally the "site" on the SiteInstance is set lazily when the load
901 // actually commits. This is to support better process sharing in case 1107 // actually commits. This is to support better process sharing in case
902 // the site redirects to some other site: we want to use the destination 1108 // the site redirects to some other site: we want to use the destination
903 // site in the site instance. 1109 // site in the site instance.
904 // 1110 //
905 // In the case of session restore, as it loads all the pages immediately 1111 // In the case of session restore, as it loads all the pages immediately
906 // we need to set the site first, otherwise after a restore none of the 1112 // we need to set the site first, otherwise after a restore none of the
907 // pages would share renderers in process-per-site. 1113 // pages would share renderers in process-per-site.
(...skipping 29 matching lines...) Expand all
937 } 1143 }
938 1144
939 // View-source URLs must use a new SiteInstance and BrowsingInstance. 1145 // View-source URLs must use a new SiteInstance and BrowsingInstance.
940 // We don't need a swap when going from view-source to a debug URL like 1146 // We don't need a swap when going from view-source to a debug URL like
941 // chrome://crash, however. 1147 // chrome://crash, however.
942 // TODO(creis): Refactor this method so this duplicated code isn't needed. 1148 // TODO(creis): Refactor this method so this duplicated code isn't needed.
943 // See http://crbug.com/123007. 1149 // See http://crbug.com/123007.
944 if (current_entry && 1150 if (current_entry &&
945 current_entry->IsViewSourceMode() != dest_is_view_source_mode && 1151 current_entry->IsViewSourceMode() != dest_is_view_source_mode &&
946 !IsRendererDebugURL(dest_url)) { 1152 !IsRendererDebugURL(dest_url)) {
947 return SiteInstance::CreateForURL(browser_context, dest_url); 1153 return CreateSiteInstanceForURL(browser_context, dest_url,
1154 create_unbounded_site_instance,
1155 current_site_instance);
948 } 1156 }
949 1157
950 // Use the current SiteInstance for same site navigations, as long as the 1158 // Use the current SiteInstance for same site navigations, as long as the
951 // process type is correct. (The URL may have been installed as an app since 1159 // process type is correct. (The URL may have been installed as an app since
952 // the last time we visited it.) 1160 // the last time we visited it.)
953 const GURL& current_url = 1161 const GURL& current_url =
954 GetCurrentURLForSiteInstance(current_instance, current_entry); 1162 GetCurrentURLForSiteInstance(current_instance, current_entry);
955 if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) && 1163 if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) &&
956 !current_site_instance->HasWrongProcessForURL(dest_url)) { 1164 !current_site_instance->HasWrongProcessForURL(dest_url)) {
957 return current_instance; 1165 return current_instance;
958 } 1166 }
959 1167
960 // Start the new renderer in a new SiteInstance, but in the current 1168 // Start the new renderer in a new SiteInstance, but in the current
961 // BrowsingInstance. It is important to immediately give this new 1169 // BrowsingInstance. It is important to immediately give this new
962 // SiteInstance to a RenderViewHost (if it is different than our current 1170 // SiteInstance to a RenderViewHost (if it is different than our current
963 // SiteInstance), so that it is ref counted. This will happen in 1171 // SiteInstance), so that it is ref counted. This will happen in
964 // CreateRenderView. 1172 // CreateRenderView.
1173 return GetRelatedSiteInstanceForURL(current_site_instance, dest_url,
1174 create_unbounded_site_instance);
1175 }
1176
1177 SiteInstance* RenderFrameHostManager::CreateSiteInstanceForURL(
1178 BrowserContext* browser_context,
1179 const GURL& dest_url,
1180 bool create_unbounded_site_instance,
1181 SiteInstanceImpl* current_instance) {
1182 if (CommandLine::ForCurrentProcess()->HasSwitch(
1183 switches::kEnableBrowserSideNavigation)) {
1184 if (create_unbounded_site_instance) {
1185 return SiteInstance::Create(browser_context);
1186 }
1187 if (speculative_render_frame_host_) {
1188 SiteInstanceImpl* sii = speculative_render_frame_host_->GetSiteInstance();
1189 if (!sii->HasSite() && !sii->IsRelatedSiteInstance(current_instance)) {
1190 return sii;
1191 }
1192 }
1193 }
1194
1195 return SiteInstance::CreateForURL(browser_context, dest_url);
1196 }
1197
1198 SiteInstance* RenderFrameHostManager::GetRelatedSiteInstanceForURL(
1199 SiteInstanceImpl* current_instance,
1200 const GURL& dest_url,
1201 bool create_unbounded_site_instance) {
1202 if (CommandLine::ForCurrentProcess()->HasSwitch(
1203 switches::kEnableBrowserSideNavigation)) {
1204 if (!current_instance->HasRelatedSiteInstance(dest_url)) {
1205 if (create_unbounded_site_instance) {
1206 return current_instance->GetRelatedEmptySiteInstance();
1207 }
1208 if (speculative_render_frame_host_) {
1209 SiteInstanceImpl* sii =
1210 speculative_render_frame_host_->GetSiteInstance();
1211 if (!sii->HasSite() && sii->IsRelatedSiteInstance(current_instance)) {
1212 return sii;
1213 }
1214 }
1215 }
1216 }
1217
965 return current_instance->GetRelatedSiteInstance(dest_url); 1218 return current_instance->GetRelatedSiteInstance(dest_url);
966 } 1219 }
967 1220
968 const GURL& RenderFrameHostManager::GetCurrentURLForSiteInstance( 1221 const GURL& RenderFrameHostManager::GetCurrentURLForSiteInstance(
969 SiteInstance* current_instance, NavigationEntry* current_entry) { 1222 SiteInstance* current_instance, NavigationEntry* current_entry) {
970 // If this is a subframe that is potentially out of process from its parent, 1223 // If this is a subframe that is potentially out of process from its parent,
971 // don't consider using current_entry's url for SiteInstance selection, since 1224 // don't consider using current_entry's url for SiteInstance selection, since
972 // current_entry's url is for the main frame and may be in a different site 1225 // current_entry's url is for the main frame and may be in a different site
973 // than this frame. 1226 // than this frame.
974 // TODO(creis): Remove this when we can check the FrameNavigationEntry's url. 1227 // TODO(creis): Remove this when we can check the FrameNavigationEntry's url.
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1190 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); 1443 render_view_host->AllowBindings(pending_web_ui()->GetBindings());
1191 } else { 1444 } else {
1192 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled 1445 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
1193 // process unless it's swapped out. 1446 // process unless it's swapped out.
1194 if (render_view_host->is_active()) { 1447 if (render_view_host->is_active()) {
1195 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 1448 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1196 render_view_host->GetProcess()->GetID())); 1449 render_view_host->GetProcess()->GetID()));
1197 } 1450 }
1198 } 1451 }
1199 1452
1200 return delegate_->CreateRenderViewForRenderManager(render_view_host, 1453 return delegate_->CreateRenderViewForRenderManager(
1201 opener_route_id, 1454 render_view_host, opener_route_id, proxy_routing_id,
1202 proxy_routing_id, 1455 for_main_frame_navigation);
1203 for_main_frame_navigation);
1204 } 1456 }
1205 1457
1206 bool RenderFrameHostManager::InitRenderFrame( 1458 bool RenderFrameHostManager::InitRenderFrame(
1207 RenderFrameHostImpl* render_frame_host) { 1459 RenderFrameHostImpl* render_frame_host) {
1208 if (render_frame_host->IsRenderFrameLive()) 1460 if (render_frame_host->IsRenderFrameLive())
1209 return true; 1461 return true;
1210 1462
1211 int parent_routing_id = MSG_ROUTING_NONE; 1463 int parent_routing_id = MSG_ROUTING_NONE;
1212 int proxy_routing_id = MSG_ROUTING_NONE; 1464 int proxy_routing_id = MSG_ROUTING_NONE;
1213 if (frame_tree_node_->parent()) { 1465 if (frame_tree_node_->parent()) {
(...skipping 25 matching lines...) Expand all
1239 return render_frame_host_->GetRoutingID(); 1491 return render_frame_host_->GetRoutingID();
1240 1492
1241 RenderFrameProxyHostMap::iterator iter = 1493 RenderFrameProxyHostMap::iterator iter =
1242 proxy_hosts_.find(site_instance->GetId()); 1494 proxy_hosts_.find(site_instance->GetId());
1243 if (iter != proxy_hosts_.end()) 1495 if (iter != proxy_hosts_.end())
1244 return iter->second->GetRoutingID(); 1496 return iter->second->GetRoutingID();
1245 1497
1246 return MSG_ROUTING_NONE; 1498 return MSG_ROUTING_NONE;
1247 } 1499 }
1248 1500
1249 void RenderFrameHostManager::CommitPending() { 1501 void RenderFrameHostManager::CommitPending(bool use_speculative_rfh) {
1250 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", 1502 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending",
1251 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 1503 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
1504 // If use_speculative_rfh then kEnableBrowserSideNavigation must be enabled.
1505 CHECK(!use_speculative_rfh ||
1506 CommandLine::ForCurrentProcess()->HasSwitch(
1507 switches::kEnableBrowserSideNavigation));
1508
1252 // First check whether we're going to want to focus the location bar after 1509 // First check whether we're going to want to focus the location bar after
1253 // this commit. We do this now because the navigation hasn't formally 1510 // this commit. We do this now because the navigation hasn't formally
1254 // committed yet, so if we've already cleared |pending_web_ui_| the call chain 1511 // committed yet, so if we've already cleared |pending_web_ui_| the call chain
1255 // this triggers won't be able to figure out what's going on. 1512 // this triggers won't be able to figure out what's going on.
1256 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 1513 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
1257 1514
1258 // Next commit the Web UI, if any. Either replace |web_ui_| with 1515 if (!use_speculative_rfh) {
1259 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or 1516 DCHECK(!speculative_web_ui_);
1260 // leave |web_ui_| as is if reusing it. 1517 // Next commit the Web UI, if any. Either replace |web_ui_| with
1261 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); 1518 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
1262 if (pending_web_ui_) { 1519 // leave |web_ui_| as is if reusing it.
1263 web_ui_.reset(pending_web_ui_.release()); 1520 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get()));
1264 } else if (!pending_and_current_web_ui_.get()) { 1521 if (pending_web_ui_) {
1265 web_ui_.reset(); 1522 web_ui_.reset(pending_web_ui_.release());
1523 } else if (!pending_and_current_web_ui_.get()) {
1524 web_ui_.reset();
1525 } else {
1526 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
1527 pending_and_current_web_ui_.reset();
1528 }
1266 } else { 1529 } else {
1267 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); 1530 web_ui_.reset(speculative_web_ui_.release());
1268 pending_and_current_web_ui_.reset();
1269 } 1531 }
1270 1532
1271 // It's possible for the pending_render_frame_host_ to be NULL when we aren't 1533 // It's possible for the pending_render_frame_host_ to be NULL when we aren't
1272 // crossing process boundaries. If so, we just needed to handle the Web UI 1534 // crossing process boundaries. If so, we just needed to handle the Web UI
1273 // committing above and we're done. 1535 // committing above and we're done.
1274 if (!pending_render_frame_host_) { 1536 if (!pending_render_frame_host_ && !use_speculative_rfh) {
1275 if (will_focus_location_bar) 1537 if (will_focus_location_bar)
1276 delegate_->SetFocusToLocationBar(false); 1538 delegate_->SetFocusToLocationBar(false);
1277 return; 1539 return;
1278 } 1540 }
1279 1541
1280 // Remember if the page was focused so we can focus the new renderer in 1542 // Remember if the page was focused so we can focus the new renderer in
1281 // that case. 1543 // that case.
1282 bool focus_render_view = !will_focus_location_bar && 1544 bool focus_render_view = !will_focus_location_bar &&
1283 render_frame_host_->render_view_host()->GetView() && 1545 render_frame_host_->render_view_host()->GetView() &&
1284 render_frame_host_->render_view_host()->GetView()->HasFocus(); 1546 render_frame_host_->render_view_host()->GetView()->HasFocus();
1285 1547
1286 bool is_main_frame = frame_tree_node_->IsMainFrame(); 1548 bool is_main_frame = frame_tree_node_->IsMainFrame();
1287 1549
1288 // Swap in the pending frame and make it active. Also ensure the FrameTree 1550 scoped_ptr<RenderFrameHostImpl> old_render_frame_host;
1289 // stays in sync. 1551 if (!use_speculative_rfh) {
1290 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = 1552 DCHECK(!speculative_render_frame_host_);
1291 SetRenderFrameHost(pending_render_frame_host_.Pass()); 1553 // Swap in the pending frame and make it active. Also ensure the FrameTree
1554 // stays in sync.
1555 old_render_frame_host =
1556 SetRenderFrameHost(pending_render_frame_host_.Pass());
1557 } else {
1558 DCHECK(speculative_render_frame_host_);
1559 old_render_frame_host =
1560 SetRenderFrameHost(speculative_render_frame_host_.Pass());
1561 }
1562
1292 if (is_main_frame) 1563 if (is_main_frame)
1293 render_frame_host_->render_view_host()->AttachToFrameTree(); 1564 render_frame_host_->render_view_host()->AttachToFrameTree();
1294 1565
1295 // The process will no longer try to exit, so we can decrement the count. 1566 // The process will no longer try to exit, so we can decrement the count.
1296 render_frame_host_->GetProcess()->RemovePendingView(); 1567 render_frame_host_->GetProcess()->RemovePendingView();
1297 1568
1298 // Show the new view (or a sad tab) if necessary. 1569 // Show the new view (or a sad tab) if necessary.
1299 bool new_rfh_has_view = !!render_frame_host_->render_view_host()->GetView(); 1570 bool new_rfh_has_view = !!render_frame_host_->render_view_host()->GetView();
1300 if (!delegate_->IsHidden() && new_rfh_has_view) { 1571 if (!delegate_->IsHidden() && new_rfh_has_view) {
1301 // In most cases, we need to show the new view. 1572 // In most cases, we need to show the new view.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1408 // If we are currently navigating cross-process, we want to get back to normal 1679 // If we are currently navigating cross-process, we want to get back to normal
1409 // and then navigate as usual. 1680 // and then navigate as usual.
1410 if (cross_navigation_pending_) { 1681 if (cross_navigation_pending_) {
1411 if (pending_render_frame_host_) 1682 if (pending_render_frame_host_)
1412 CancelPending(); 1683 CancelPending();
1413 cross_navigation_pending_ = false; 1684 cross_navigation_pending_ = false;
1414 } 1685 }
1415 1686
1416 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); 1687 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
1417 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( 1688 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
1418 url, instance, transition, is_restore, is_view_source_mode); 1689 url, instance, transition, is_restore, is_view_source_mode, false);
1690
1691 if (CommandLine::ForCurrentProcess()->HasSwitch(
1692 switches::kEnableBrowserSideNavigation) &&
1693 speculative_render_frame_host_) {
1694 if (speculative_render_frame_host_->GetSiteInstance() == new_instance)
1695 return speculative_render_frame_host_.get();
1696 CleanUpSpeculativeRenderFrameHost();
1697 }
1419 1698
1420 const NavigationEntry* current_entry = 1699 const NavigationEntry* current_entry =
1421 delegate_->GetLastCommittedNavigationEntryForRenderManager(); 1700 delegate_->GetLastCommittedNavigationEntryForRenderManager();
1422 1701
1423 if (new_instance.get() != current_instance) { 1702 if (new_instance.get() != current_instance) {
1424 TRACE_EVENT_INSTANT2( 1703 TRACE_EVENT_INSTANT2(
1425 "navigation", 1704 "navigation",
1426 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", 1705 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance",
1427 TRACE_EVENT_SCOPE_THREAD, 1706 TRACE_EVENT_SCOPE_THREAD,
1428 "current_instance id", current_instance->GetId(), 1707 "current_instance id", current_instance->GetId(),
(...skipping 16 matching lines...) Expand all
1445 } 1724 }
1446 1725
1447 // Check if our current RFH is live before we set up a transition. 1726 // Check if our current RFH is live before we set up a transition.
1448 if (!render_frame_host_->IsRenderFrameLive()) { 1727 if (!render_frame_host_->IsRenderFrameLive()) {
1449 if (!cross_navigation_pending_) { 1728 if (!cross_navigation_pending_) {
1450 // The current RFH is not live. There's no reason to sit around with a 1729 // The current RFH is not live. There's no reason to sit around with a
1451 // sad tab or a newly created RFH while we wait for the pending RFH to 1730 // sad tab or a newly created RFH while we wait for the pending RFH to
1452 // navigate. Just switch to the pending RFH now and go back to non 1731 // navigate. Just switch to the pending RFH now and go back to non
1453 // cross-navigating (Note that we don't care about on{before}unload 1732 // cross-navigating (Note that we don't care about on{before}unload
1454 // handlers if the current RFH isn't live.) 1733 // handlers if the current RFH isn't live.)
1455 CommitPending(); 1734 CommitPending(false);
1456 return render_frame_host_.get(); 1735 return render_frame_host_.get();
1457 } else { 1736 } else {
1458 NOTREACHED(); 1737 NOTREACHED();
1459 return render_frame_host_.get(); 1738 return render_frame_host_.get();
1460 } 1739 }
1461 } 1740 }
1462 // Otherwise, it's safe to treat this as a pending cross-site transition. 1741 // Otherwise, it's safe to treat this as a pending cross-site transition.
1463 1742
1464 // We now have a pending RFH. 1743 // We now have a pending RFH.
1465 DCHECK(!cross_navigation_pending_); 1744 DCHECK(!cross_navigation_pending_);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1550 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host = 1829 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host =
1551 pending_render_frame_host_.Pass(); 1830 pending_render_frame_host_.Pass();
1552 1831
1553 RenderViewDevToolsAgentHost::OnCancelPendingNavigation( 1832 RenderViewDevToolsAgentHost::OnCancelPendingNavigation(
1554 pending_render_frame_host->render_view_host(), 1833 pending_render_frame_host->render_view_host(),
1555 render_frame_host_->render_view_host()); 1834 render_frame_host_->render_view_host());
1556 1835
1557 // We no longer need to prevent the process from exiting. 1836 // We no longer need to prevent the process from exiting.
1558 pending_render_frame_host->GetProcess()->RemovePendingView(); 1837 pending_render_frame_host->GetProcess()->RemovePendingView();
1559 1838
1560 // If the SiteInstance for the pending RFH is being used by others, don't 1839 RecycleRenderFrameHost(pending_render_frame_host.Pass());
1561 // delete the RFH, just swap it out and it can be reused at a later point.
1562 SiteInstanceImpl* site_instance =
1563 pending_render_frame_host->GetSiteInstance();
1564 if (site_instance->active_frame_count() > 1) {
1565 // Any currently suspended navigations are no longer needed.
1566 pending_render_frame_host->CancelSuspendedNavigations();
1567
1568 RenderFrameProxyHost* proxy =
1569 new RenderFrameProxyHost(site_instance, frame_tree_node_);
1570 proxy_hosts_[site_instance->GetId()] = proxy;
1571 pending_render_frame_host->SwapOut(proxy);
1572 if (frame_tree_node_->IsMainFrame())
1573 proxy->TakeFrameHostOwnership(pending_render_frame_host.Pass());
1574 } else {
1575 // We won't be coming back, so delete this one.
1576 pending_render_frame_host.reset();
1577 }
1578 1840
1579 pending_web_ui_.reset(); 1841 pending_web_ui_.reset();
1580 pending_and_current_web_ui_.reset(); 1842 pending_and_current_web_ui_.reset();
1581 } 1843 }
1582 1844
1845 void RenderFrameHostManager::CleanUpSpeculativeRenderFrameHost() {
1846 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
1847 switches::kEnableBrowserSideNavigation));
1848 if (speculative_render_frame_host_) {
1849 speculative_render_frame_host_->GetProcess()->RemovePendingView();
1850 RecycleRenderFrameHost(speculative_render_frame_host_.Pass());
1851 }
1852 if (speculative_web_ui_)
1853 speculative_web_ui_.reset();
1854 }
1855
1583 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost( 1856 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost(
1584 scoped_ptr<RenderFrameHostImpl> render_frame_host) { 1857 scoped_ptr<RenderFrameHostImpl> render_frame_host) {
1585 // Swap the two. 1858 // Swap the two.
1586 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = 1859 scoped_ptr<RenderFrameHostImpl> old_render_frame_host =
1587 render_frame_host_.Pass(); 1860 render_frame_host_.Pass();
1588 render_frame_host_ = render_frame_host.Pass(); 1861 render_frame_host_ = render_frame_host.Pass();
1589 1862
1590 if (frame_tree_node_->IsMainFrame()) { 1863 if (frame_tree_node_->IsMainFrame()) {
1591 // Update the count of top-level frames using this SiteInstance. All 1864 // Update the count of top-level frames using this SiteInstance. All
1592 // subframes are in the same BrowsingInstance as the main frame, so we only 1865 // subframes are in the same BrowsingInstance as the main frame, so we only
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1652 void RenderFrameHostManager::DeleteRenderFrameProxyHost( 1925 void RenderFrameHostManager::DeleteRenderFrameProxyHost(
1653 SiteInstance* instance) { 1926 SiteInstance* instance) {
1654 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId()); 1927 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId());
1655 if (iter != proxy_hosts_.end()) { 1928 if (iter != proxy_hosts_.end()) {
1656 delete iter->second; 1929 delete iter->second;
1657 proxy_hosts_.erase(iter); 1930 proxy_hosts_.erase(iter);
1658 } 1931 }
1659 } 1932 }
1660 1933
1661 } // namespace content 1934 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698