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