OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/web_contents/render_view_host_manager.h" | 5 #include "content/browser/web_contents/render_view_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/logging.h" | 10 #include "base/logging.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 void RenderViewHostManager::Init(content::BrowserContext* browser_context, | 68 void RenderViewHostManager::Init(content::BrowserContext* browser_context, |
69 SiteInstance* site_instance, | 69 SiteInstance* site_instance, |
70 int routing_id) { | 70 int routing_id) { |
71 // Create a RenderViewHost, once we have an instance. It is important to | 71 // Create a RenderViewHost, once we have an instance. It is important to |
72 // immediately give this SiteInstance to a RenderViewHost so that it is | 72 // immediately give this SiteInstance to a RenderViewHost so that it is |
73 // ref counted. | 73 // ref counted. |
74 if (!site_instance) | 74 if (!site_instance) |
75 site_instance = SiteInstance::Create(browser_context); | 75 site_instance = SiteInstance::Create(browser_context); |
76 render_view_host_ = static_cast<RenderViewHostImpl*>( | 76 render_view_host_ = static_cast<RenderViewHostImpl*>( |
77 RenderViewHostFactory::Create( | 77 RenderViewHostFactory::Create( |
78 site_instance, render_view_delegate_, routing_id, delegate_-> | 78 site_instance, render_view_delegate_, routing_id, false, delegate_-> |
79 GetControllerForRenderManager().GetSessionStorageNamespace())); | 79 GetControllerForRenderManager().GetSessionStorageNamespace())); |
80 | 80 |
81 // Keep track of renderer processes as they start to shut down. | 81 // Keep track of renderer processes as they start to shut down. |
82 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSING, | 82 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSING, |
83 content::NotificationService::AllSources()); | 83 content::NotificationService::AllSources()); |
84 } | 84 } |
85 | 85 |
86 RenderViewHostImpl* RenderViewHostManager::current_host() const { | 86 RenderViewHostImpl* RenderViewHostManager::current_host() const { |
87 return render_view_host_; | 87 return render_view_host_; |
88 } | 88 } |
(...skipping 16 matching lines...) Expand all Loading... |
105 if (!dest_render_view_host) | 105 if (!dest_render_view_host) |
106 return NULL; // We weren't able to create a pending render view host. | 106 return NULL; // We weren't able to create a pending render view host. |
107 | 107 |
108 // If the current render_view_host_ isn't live, we should create it so | 108 // If the current render_view_host_ isn't live, we should create it so |
109 // that we don't show a sad tab while the dest_render_view_host fetches | 109 // that we don't show a sad tab while the dest_render_view_host fetches |
110 // its first page. (Bug 1145340) | 110 // its first page. (Bug 1145340) |
111 if (dest_render_view_host != render_view_host_ && | 111 if (dest_render_view_host != render_view_host_ && |
112 !render_view_host_->IsRenderViewLive()) { | 112 !render_view_host_->IsRenderViewLive()) { |
113 // Note: we don't call InitRenderView here because we are navigating away | 113 // Note: we don't call InitRenderView here because we are navigating away |
114 // soon anyway, and we don't have the NavigationEntry for this host. | 114 // soon anyway, and we don't have the NavigationEntry for this host. |
115 delegate_->CreateRenderViewForRenderManager(render_view_host_); | 115 delegate_->CreateRenderViewForRenderManager(render_view_host_, |
| 116 MSG_ROUTING_NONE); |
116 } | 117 } |
117 | 118 |
118 // If the renderer crashed, then try to create a new one to satisfy this | 119 // If the renderer crashed, then try to create a new one to satisfy this |
119 // navigation request. | 120 // navigation request. |
120 if (!dest_render_view_host->IsRenderViewLive()) { | 121 if (!dest_render_view_host->IsRenderViewLive()) { |
121 if (!InitRenderView(dest_render_view_host, entry)) | 122 if (!InitRenderView(dest_render_view_host, MSG_ROUTING_NONE)) |
122 return NULL; | 123 return NULL; |
123 | 124 |
124 // Now that we've created a new renderer, be sure to hide it if it isn't | 125 // Now that we've created a new renderer, be sure to hide it if it isn't |
125 // our primary one. Otherwise, we might crash if we try to call Show() | 126 // our primary one. Otherwise, we might crash if we try to call Show() |
126 // on it later. | 127 // on it later. |
127 if (dest_render_view_host != render_view_host_ && | 128 if (dest_render_view_host != render_view_host_ && |
128 dest_render_view_host->GetView()) { | 129 dest_render_view_host->GetView()) { |
129 dest_render_view_host->GetView()->Hide(); | 130 dest_render_view_host->GetView()->Hide(); |
130 } else { | 131 } else { |
131 // This is our primary renderer, notify here as we won't be calling | 132 // This is our primary renderer, notify here as we won't be calling |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 // a single BrowsingInstance for all pages of a certain type (e.g., New Tab | 537 // a single BrowsingInstance for all pages of a certain type (e.g., New Tab |
537 // Pages), keeping them in the same process. When you navigate away from | 538 // Pages), keeping them in the same process. When you navigate away from |
538 // that page, we want to explicity ignore that BrowsingInstance and group | 539 // that page, we want to explicity ignore that BrowsingInstance and group |
539 // this page into the appropriate SiteInstance for its URL. | 540 // this page into the appropriate SiteInstance for its URL. |
540 return SiteInstance::CreateForURL(browser_context, dest_url); | 541 return SiteInstance::CreateForURL(browser_context, dest_url); |
541 } else { | 542 } else { |
542 // Start the new renderer in a new SiteInstance, but in the current | 543 // Start the new renderer in a new SiteInstance, but in the current |
543 // BrowsingInstance. It is important to immediately give this new | 544 // BrowsingInstance. It is important to immediately give this new |
544 // SiteInstance to a RenderViewHost (if it is different than our current | 545 // SiteInstance to a RenderViewHost (if it is different than our current |
545 // SiteInstance), so that it is ref counted. This will happen in | 546 // SiteInstance), so that it is ref counted. This will happen in |
546 // CreatePendingRenderView. | 547 // CreateRenderView. |
547 return curr_instance->GetRelatedSiteInstance(dest_url); | 548 return curr_instance->GetRelatedSiteInstance(dest_url); |
548 } | 549 } |
549 } | 550 } |
550 | 551 |
551 bool RenderViewHostManager::CreatePendingRenderView( | 552 int RenderViewHostManager::CreateRenderView( |
552 const NavigationEntryImpl& entry, SiteInstance* instance) { | 553 SiteInstance* instance, |
553 NavigationEntry* curr_entry = | 554 int opener_route_id, |
554 delegate_->GetControllerForRenderManager().GetLastCommittedEntry(); | 555 bool swapped_out) { |
555 if (curr_entry) { | 556 CHECK(instance); |
556 DCHECK(!curr_entry->GetContentState().empty()); | 557 |
557 // TODO(creis): Should send a message to the RenderView to let it know | 558 // Check if we've already created an RVH for this SiteInstance. If so, try |
558 // we're about to switch away, so that it sends an UpdateState message. | 559 // to re-use the existing one, which has already been initialized. We'll |
| 560 // remove it from the list of swapped out hosts if it commits. |
| 561 RenderViewHostImpl* new_render_view_host = static_cast<RenderViewHostImpl*>( |
| 562 GetSwappedOutRenderViewHost(instance)); |
| 563 if (new_render_view_host) { |
| 564 // Prevent the process from exiting while we're trying to use it. |
| 565 new_render_view_host->GetProcess()->AddPendingView(); |
| 566 } else { |
| 567 // Create a new RenderViewHost if we don't find an existing one. |
| 568 new_render_view_host = static_cast<RenderViewHostImpl*>( |
| 569 RenderViewHostFactory::Create(instance, |
| 570 render_view_delegate_, MSG_ROUTING_NONE, swapped_out, delegate_-> |
| 571 GetControllerForRenderManager().GetSessionStorageNamespace())); |
| 572 |
| 573 // Prevent the process from exiting while we're trying to use it. |
| 574 new_render_view_host->GetProcess()->AddPendingView(); |
| 575 |
| 576 // Store the new RVH as swapped out if necessary. |
| 577 if (swapped_out) |
| 578 swapped_out_hosts_[instance->GetId()] = new_render_view_host; |
| 579 |
| 580 bool success = InitRenderView(new_render_view_host, opener_route_id); |
| 581 if (success) { |
| 582 // Don't show the view until we get a DidNavigate from it. |
| 583 new_render_view_host->GetView()->Hide(); |
| 584 } else if (!swapped_out) { |
| 585 CancelPending(); |
| 586 } |
559 } | 587 } |
560 | 588 |
561 // Check if we've already created an RVH for this SiteInstance. | 589 // Use this as our new pending RVH if it isn't swapped out. |
562 CHECK(instance); | 590 if (!swapped_out) |
563 RenderViewHostMap::iterator iter = | 591 pending_render_view_host_ = new_render_view_host; |
564 swapped_out_hosts_.find(instance->GetId()); | |
565 if (iter != swapped_out_hosts_.end()) { | |
566 // Re-use the existing RenderViewHost, which has already been initialized. | |
567 // We'll remove it from the list of swapped out hosts if it commits. | |
568 pending_render_view_host_ = iter->second; | |
569 | 592 |
570 // Prevent the process from exiting while we're trying to use it. | 593 return new_render_view_host->GetRoutingID(); |
571 pending_render_view_host_->GetProcess()->AddPendingView(); | |
572 | |
573 return true; | |
574 } | |
575 | |
576 pending_render_view_host_ = static_cast<RenderViewHostImpl*>( | |
577 RenderViewHostFactory::Create( | |
578 instance, render_view_delegate_, MSG_ROUTING_NONE, delegate_-> | |
579 GetControllerForRenderManager().GetSessionStorageNamespace())); | |
580 | |
581 // Prevent the process from exiting while we're trying to use it. | |
582 pending_render_view_host_->GetProcess()->AddPendingView(); | |
583 | |
584 bool success = InitRenderView(pending_render_view_host_, entry); | |
585 if (success) { | |
586 // Don't show the view until we get a DidNavigate from it. | |
587 pending_render_view_host_->GetView()->Hide(); | |
588 } else { | |
589 CancelPending(); | |
590 } | |
591 return success; | |
592 } | 594 } |
593 | 595 |
594 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, | 596 bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, |
595 const NavigationEntryImpl& entry) { | 597 int opener_route_id) { |
596 // If the pending navigation is to a WebUI, tell the RenderView about any | 598 // If the pending navigation is to a WebUI, tell the RenderView about any |
597 // bindings it will need enabled. | 599 // bindings it will need enabled. |
598 if (pending_web_ui()) | 600 if (pending_web_ui()) |
599 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); | 601 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); |
600 | 602 |
601 return delegate_->CreateRenderViewForRenderManager(render_view_host); | 603 return delegate_->CreateRenderViewForRenderManager(render_view_host, |
| 604 opener_route_id); |
602 } | 605 } |
603 | 606 |
604 void RenderViewHostManager::CommitPending() { | 607 void RenderViewHostManager::CommitPending() { |
605 // First check whether we're going to want to focus the location bar after | 608 // First check whether we're going to want to focus the location bar after |
606 // this commit. We do this now because the navigation hasn't formally | 609 // this commit. We do this now because the navigation hasn't formally |
607 // committed yet, so if we've already cleared |pending_web_ui_| the call chain | 610 // committed yet, so if we've already cleared |pending_web_ui_| the call chain |
608 // this triggers won't be able to figure out what's going on. | 611 // this triggers won't be able to figure out what's going on. |
609 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); | 612 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); |
610 | 613 |
611 // Next commit the Web UI, if any. Either replace |web_ui_| with | 614 // Next commit the Web UI, if any. Either replace |web_ui_| with |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 // This will possibly create (set to NULL) a Web UI object for the pending | 733 // This will possibly create (set to NULL) a Web UI object for the pending |
731 // page. We'll use this later to give the page special access. This must | 734 // page. We'll use this later to give the page special access. This must |
732 // happen before the new renderer is created below so it will get bindings. | 735 // happen before the new renderer is created below so it will get bindings. |
733 // It must also happen after the above conditional call to CancelPending(), | 736 // It must also happen after the above conditional call to CancelPending(), |
734 // otherwise CancelPending may clear the pending_web_ui_ and the page will | 737 // otherwise CancelPending may clear the pending_web_ui_ and the page will |
735 // not have its bindings set appropriately. | 738 // not have its bindings set appropriately. |
736 pending_web_ui_.reset( | 739 pending_web_ui_.reset( |
737 delegate_->CreateWebUIForRenderManager(entry.GetURL())); | 740 delegate_->CreateWebUIForRenderManager(entry.GetURL())); |
738 pending_and_current_web_ui_.reset(); | 741 pending_and_current_web_ui_.reset(); |
739 | 742 |
740 // Create a pending RVH and navigate it. | 743 // Ensure that we have created RVHs for the new RVH's opener chain if |
741 bool success = CreatePendingRenderView(entry, new_instance); | 744 // we are staying in the same BrowsingInstance. This allows the pending RVH |
742 if (!success) | 745 // to send cross-process script calls to its opener(s). |
| 746 int opener_route_id = MSG_ROUTING_NONE; |
| 747 if (new_instance->IsRelatedSiteInstance(curr_instance)) { |
| 748 opener_route_id = |
| 749 delegate_->CreateOpenerRenderViewsForRenderManager(new_instance); |
| 750 } |
| 751 |
| 752 // Create a non-swapped-out pending RVH with the given opener and navigate |
| 753 // it. |
| 754 int route_id = CreateRenderView(new_instance, opener_route_id, false); |
| 755 if (route_id == MSG_ROUTING_NONE) |
743 return NULL; | 756 return NULL; |
744 | 757 |
745 // Check if our current RVH is live before we set up a transition. | 758 // Check if our current RVH is live before we set up a transition. |
746 if (!render_view_host_->IsRenderViewLive()) { | 759 if (!render_view_host_->IsRenderViewLive()) { |
747 if (!cross_navigation_pending_) { | 760 if (!cross_navigation_pending_) { |
748 // The current RVH is not live. There's no reason to sit around with a | 761 // The current RVH is not live. There's no reason to sit around with a |
749 // sad tab or a newly created RVH while we wait for the pending RVH to | 762 // sad tab or a newly created RVH while we wait for the pending RVH to |
750 // navigate. Just switch to the pending RVH now and go back to non | 763 // navigate. Just switch to the pending RVH now and go back to non |
751 // cross-navigating (Note that we don't care about on{before}unload | 764 // cross-navigating (Note that we don't care about on{before}unload |
752 // handlers if the current RVH isn't live.) | 765 // handlers if the current RVH isn't live.) |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 } | 884 } |
872 } | 885 } |
873 | 886 |
874 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { | 887 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) { |
875 if (!rvh->GetSiteInstance()) | 888 if (!rvh->GetSiteInstance()) |
876 return false; | 889 return false; |
877 | 890 |
878 return swapped_out_hosts_.find(rvh->GetSiteInstance()->GetId()) != | 891 return swapped_out_hosts_.find(rvh->GetSiteInstance()->GetId()) != |
879 swapped_out_hosts_.end(); | 892 swapped_out_hosts_.end(); |
880 } | 893 } |
| 894 |
| 895 RenderViewHost* RenderViewHostManager::GetSwappedOutRenderViewHost( |
| 896 SiteInstance* instance) { |
| 897 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); |
| 898 if (iter != swapped_out_hosts_.end()) |
| 899 return iter->second; |
| 900 |
| 901 return NULL; |
| 902 } |
OLD | NEW |