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

Side by Side Diff: content/browser/tab_contents/render_view_host_manager.cc

Issue 6319001: Support window.opener after a process swap. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge with trunk. Created 9 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/tab_contents/render_view_host_manager.h" 5 #include "content/browser/tab_contents/render_view_host_manager.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "chrome/browser/profiles/profile.h" 9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/common/chrome_switches.h" 10 #include "chrome/common/chrome_switches.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 } 42 }
43 43
44 RenderViewHostManager::~RenderViewHostManager() { 44 RenderViewHostManager::~RenderViewHostManager() {
45 if (pending_render_view_host_) 45 if (pending_render_view_host_)
46 CancelPending(); 46 CancelPending();
47 47
48 // We should always have a main RenderViewHost. 48 // We should always have a main RenderViewHost.
49 RenderViewHost* render_view_host = render_view_host_; 49 RenderViewHost* render_view_host = render_view_host_;
50 render_view_host_ = NULL; 50 render_view_host_ = NULL;
51 render_view_host->Shutdown(); 51 render_view_host->Shutdown();
52
53 // Shut down any swapped out RenderViewHosts.
54 for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin();
55 iter != swapped_out_hosts_.end();
56 ++iter) {
57 iter->second->Shutdown();
58 }
52 } 59 }
53 60
54 void RenderViewHostManager::Init(Profile* profile, 61 void RenderViewHostManager::Init(Profile* profile,
55 SiteInstance* site_instance, 62 SiteInstance* site_instance,
56 int routing_id) { 63 int routing_id) {
57 // Create a RenderViewHost, once we have an instance. It is important to 64 // Create a RenderViewHost, once we have an instance. It is important to
58 // immediately give this SiteInstance to a RenderViewHost so that it is 65 // immediately give this SiteInstance to a RenderViewHost so that it is
59 // ref counted. 66 // ref counted.
60 if (!site_instance) 67 if (!site_instance)
61 site_instance = SiteInstance::CreateSiteInstance(profile); 68 site_instance = SiteInstance::CreateSiteInstance(profile);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 if (pending_request_id == -1) { 152 if (pending_request_id == -1) {
146 // Haven't gotten around to starting the request, because we're still 153 // Haven't gotten around to starting the request, because we're still
147 // waiting for the beforeunload handler to finish. We'll pretend that it 154 // waiting for the beforeunload handler to finish. We'll pretend that it
148 // did finish, to let the navigation proceed. Note that there's a danger 155 // did finish, to let the navigation proceed. Note that there's a danger
149 // that the beforeunload handler will later finish and possibly return 156 // that the beforeunload handler will later finish and possibly return
150 // false (meaning the navigation should not proceed), but we'll ignore it 157 // false (meaning the navigation should not proceed), but we'll ignore it
151 // in this case because it took too long. 158 // in this case because it took too long.
152 if (pending_render_view_host_->are_navigations_suspended()) 159 if (pending_render_view_host_->are_navigations_suspended())
153 pending_render_view_host_->SetNavigationsSuspended(false); 160 pending_render_view_host_->SetNavigationsSuspended(false);
154 } else { 161 } else {
155 // The request has been started and paused, while we're waiting for the 162 // The request has been started and paused while we're waiting for the
156 // unload handler to finish. We'll pretend that it did, by notifying the 163 // unload handler to finish. We'll pretend that it did, by notifying the
157 // IO thread to let the response continue. The pending renderer will then 164 // IO thread to let the response continue. The pending renderer will then
158 // be swapped in as part of the usual DidNavigate logic. (If the unload 165 // be swapped in as part of the usual DidNavigate logic. (If the unload
159 // handler later finishes, this call will be ignored because the state in 166 // handler later finishes, this call will be ignored because the state in
160 // CrossSiteResourceHandler will already be cleaned up.) 167 // CrossSiteResourceHandler will already be cleaned up.)
161 ViewMsg_ClosePage_Params params; 168 ViewMsg_SwapOut_Params params;
162 params.closing_process_id =
163 render_view_host_->process()->id();
164 params.closing_route_id = render_view_host_->routing_id();
165 params.for_cross_site_transition = true;
166 params.new_render_process_host_id = 169 params.new_render_process_host_id =
167 pending_render_view_host_->process()->id(); 170 pending_render_view_host_->process()->id();
168 params.new_request_id = pending_request_id; 171 params.new_request_id = pending_request_id;
169 current_host()->process()->CrossSiteClosePageACK(params); 172 current_host()->process()->CrossSiteSwapOutACK(params);
170 } 173 }
171 return false; 174 return false;
172 } 175 }
173 176
174 void RenderViewHostManager::DidNavigateMainFrame( 177 void RenderViewHostManager::DidNavigateMainFrame(
175 RenderViewHost* render_view_host) { 178 RenderViewHost* render_view_host) {
176 if (!cross_navigation_pending_) { 179 if (!cross_navigation_pending_) {
177 DCHECK(!pending_render_view_host_); 180 DCHECK(!pending_render_view_host_);
178 181
179 // We should only hear this from our current renderer. 182 // We should only hear this from our current renderer.
180 DCHECK(render_view_host == render_view_host_); 183 DCHECK(render_view_host == render_view_host_);
181 184
182 // Even when there is no pending RVH, there may be a pending Web UI. 185 // Even when there is no pending RVH, there may be a pending Web UI.
183 if (pending_web_ui_.get()) 186 if (pending_web_ui_.get())
184 CommitPending(); 187 CommitPending();
185 return; 188 return;
186 } 189 }
187 190
188 if (render_view_host == pending_render_view_host_) { 191 if (render_view_host == pending_render_view_host_) {
189 // The pending cross-site navigation completed, so show the renderer. 192 // The pending cross-site navigation completed, so show the renderer.
193 // If it committed without sending network requests (e.g., data URLs),
194 // then we still need to swap out the old RVH first and run its unload
195 // handler. OK for that to happen in the background.
196 if (pending_render_view_host_->GetPendingRequestId() == -1) {
197 OnCrossSiteResponse(pending_render_view_host_->process()->id(),
198 pending_render_view_host_->routing_id());
199 }
200
190 CommitPending(); 201 CommitPending();
191 cross_navigation_pending_ = false; 202 cross_navigation_pending_ = false;
192 } else if (render_view_host == render_view_host_) { 203 } else if (render_view_host == render_view_host_) {
193 // A navigation in the original page has taken place. Cancel the pending 204 // A navigation in the original page has taken place. Cancel the pending
194 // one. 205 // one.
195 CancelPending(); 206 CancelPending();
196 cross_navigation_pending_ = false; 207 cross_navigation_pending_ = false;
197 } else { 208 } else {
198 // No one else should be sending us DidNavigate in this state. 209 // No one else should be sending us DidNavigate in this state.
199 DCHECK(false); 210 DCHECK(false);
(...skipping 14 matching lines...) Expand all
214 // (Navigate, DidNavigate, etc), which will clean it up properly. 225 // (Navigate, DidNavigate, etc), which will clean it up properly.
215 // TODO(creis): All of this will go away when we move the cross-site logic 226 // TODO(creis): All of this will go away when we move the cross-site logic
216 // to ResourceDispatcherHost, so that we intercept responses rather than 227 // to ResourceDispatcherHost, so that we intercept responses rather than
217 // navigation events. (That's necessary to support onunload anyway.) Once 228 // navigation events. (That's necessary to support onunload anyway.) Once
218 // we've made that change, we won't create a pending renderer until we know 229 // we've made that change, we won't create a pending renderer until we know
219 // the response is not a download. 230 // the response is not a download.
220 } 231 }
221 232
222 void RenderViewHostManager::RendererProcessClosing( 233 void RenderViewHostManager::RendererProcessClosing(
223 RenderProcessHost* render_process_host) { 234 RenderProcessHost* render_process_host) {
224 // TODO(creis): Don't schedule new navigations in RenderViewHosts of this 235 // Remove any swapped out RVHs from this process, so that we don't try to
225 // process. (Part of http://crbug.com/65953.) 236 // swap them back in while the process is exiting. Start by finding them,
237 // since there could be more than one.
238 std::list<int> ids_to_remove;
239 for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin();
240 iter != swapped_out_hosts_.end();
241 ++iter) {
242 if (iter->second->process() == render_process_host)
243 ids_to_remove.push_back(iter->first);
244 }
245
246 // Now delete them.
247 while (!ids_to_remove.empty()) {
248 swapped_out_hosts_[ids_to_remove.back()]->Shutdown();
249 swapped_out_hosts_.erase(ids_to_remove.back());
250 ids_to_remove.pop_back();
251 }
226 } 252 }
227 253
228 void RenderViewHostManager::ShouldClosePage(bool for_cross_site_transition, 254 void RenderViewHostManager::ShouldClosePage(bool for_cross_site_transition,
229 bool proceed) { 255 bool proceed) {
230 if (for_cross_site_transition) { 256 if (for_cross_site_transition) {
231 // Ignore if we're not in a cross-site navigation. 257 // Ignore if we're not in a cross-site navigation.
232 if (!cross_navigation_pending_) 258 if (!cross_navigation_pending_)
233 return; 259 return;
234 260
235 if (proceed) { 261 if (proceed) {
(...skipping 11 matching lines...) Expand all
247 cross_navigation_pending_ = false; 273 cross_navigation_pending_ = false;
248 } 274 }
249 } else { 275 } else {
250 // Non-cross site transition means closing the entire tab. 276 // Non-cross site transition means closing the entire tab.
251 bool proceed_to_fire_unload; 277 bool proceed_to_fire_unload;
252 delegate_->BeforeUnloadFiredFromRenderManager(proceed, 278 delegate_->BeforeUnloadFiredFromRenderManager(proceed,
253 &proceed_to_fire_unload); 279 &proceed_to_fire_unload);
254 280
255 if (proceed_to_fire_unload) { 281 if (proceed_to_fire_unload) {
256 // This is not a cross-site navigation, the tab is being closed. 282 // This is not a cross-site navigation, the tab is being closed.
257 render_view_host_->ClosePage(false, -1, -1); 283 render_view_host_->ClosePage();
258 } 284 }
259 } 285 }
260 } 286 }
261 287
262 void RenderViewHostManager::OnCrossSiteResponse(int new_render_process_host_id, 288 void RenderViewHostManager::OnCrossSiteResponse(int new_render_process_host_id,
263 int new_request_id) { 289 int new_request_id) {
264 // Should only see this while we have a pending renderer. 290 // Should only see this while we have a pending renderer.
265 if (!cross_navigation_pending_) 291 if (!cross_navigation_pending_)
266 return; 292 return;
267 DCHECK(pending_render_view_host_); 293 DCHECK(pending_render_view_host_);
268 294
269 // Tell the old renderer to run its onunload handler. When it finishes, it 295 // Tell the old renderer it is being swapped out. This will fire the unload
270 // will send a ClosePage_ACK to the ResourceDispatcherHost with the given 296 // handler (without firing the beforeunload handler a second time). When the
271 // IDs (of the pending RVH's request), allowing the pending RVH's response to 297 // unload handler finishes and the navigation completes, we will send a
272 // resume. 298 // message to the ResourceDispatcherHost with the given pending request IDs,
273 render_view_host_->ClosePage(true, 299 // allowing the pending RVH's response to resume.
274 new_render_process_host_id, new_request_id); 300 render_view_host_->SwapOut(new_render_process_host_id, new_request_id);
275 301
276 // ResourceDispatcherHost has told us to run the onunload handler, which 302 // ResourceDispatcherHost has told us to run the onunload handler, which
277 // means it is not a download or unsafe page, and we are going to perform the 303 // means it is not a download or unsafe page, and we are going to perform the
278 // navigation. Thus, we no longer need to remember that the RenderViewHost 304 // navigation. Thus, we no longer need to remember that the RenderViewHost
279 // is part of a pending cross-site request. 305 // is part of a pending cross-site request.
280 pending_render_view_host_->SetHasPendingCrossSiteRequest(false, 306 pending_render_view_host_->SetHasPendingCrossSiteRequest(false,
281 new_request_id); 307 new_request_id);
282 } 308 }
283 309
284 void RenderViewHostManager::OnCrossSiteNavigationCanceled() { 310 void RenderViewHostManager::OnCrossSiteNavigationCanceled() {
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 bool RenderViewHostManager::CreatePendingRenderView( 501 bool RenderViewHostManager::CreatePendingRenderView(
476 const NavigationEntry& entry, SiteInstance* instance) { 502 const NavigationEntry& entry, SiteInstance* instance) {
477 NavigationEntry* curr_entry = 503 NavigationEntry* curr_entry =
478 delegate_->GetControllerForRenderManager().GetLastCommittedEntry(); 504 delegate_->GetControllerForRenderManager().GetLastCommittedEntry();
479 if (curr_entry) { 505 if (curr_entry) {
480 DCHECK(!curr_entry->content_state().empty()); 506 DCHECK(!curr_entry->content_state().empty());
481 // TODO(creis): Should send a message to the RenderView to let it know 507 // TODO(creis): Should send a message to the RenderView to let it know
482 // we're about to switch away, so that it sends an UpdateState message. 508 // we're about to switch away, so that it sends an UpdateState message.
483 } 509 }
484 510
511 // Check if we've already created an RVH for this SiteInstance.
512 CHECK(instance);
513 RenderViewHostMap::iterator iter =
514 swapped_out_hosts_.find(instance->id());
515 if (iter != swapped_out_hosts_.end()) {
516 // Re-use the existing RenderViewHost, which has already been initialized.
517 // We'll remove it from the list of swapped out hosts if it commits.
518 pending_render_view_host_ = iter->second;
519
520 // Prevent the process from exiting while we're trying to use it.
521 pending_render_view_host_->process()->AddPendingView();
522
523 return true;
524 }
525
485 pending_render_view_host_ = RenderViewHostFactory::Create( 526 pending_render_view_host_ = RenderViewHostFactory::Create(
486 instance, render_view_delegate_, MSG_ROUTING_NONE, delegate_-> 527 instance, render_view_delegate_, MSG_ROUTING_NONE, delegate_->
487 GetControllerForRenderManager().session_storage_namespace()); 528 GetControllerForRenderManager().session_storage_namespace());
488 529
489 // Prevent the process from exiting while we're trying to use it. 530 // Prevent the process from exiting while we're trying to use it.
490 pending_render_view_host_->process()->AddPendingView(); 531 pending_render_view_host_->process()->AddPendingView();
491 532
492 bool success = InitRenderView(pending_render_view_host_, entry); 533 bool success = InitRenderView(pending_render_view_host_, entry);
493 if (success) { 534 if (success) {
494 // Don't show the view until we get a DidNavigate from it. 535 // Don't show the view until we get a DidNavigate from it.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 if (will_focus_location_bar) 570 if (will_focus_location_bar)
530 delegate_->SetFocusToLocationBar(false); 571 delegate_->SetFocusToLocationBar(false);
531 return; 572 return;
532 } 573 }
533 574
534 // Remember if the page was focused so we can focus the new renderer in 575 // Remember if the page was focused so we can focus the new renderer in
535 // that case. 576 // that case.
536 bool focus_render_view = !will_focus_location_bar && 577 bool focus_render_view = !will_focus_location_bar &&
537 render_view_host_->view() && render_view_host_->view()->HasFocus(); 578 render_view_host_->view() && render_view_host_->view()->HasFocus();
538 579
539 // Hide the current view and prepare to destroy it. 580 // Swap in the pending view and make it active.
540 // TODO(creis): Get the old RenderViewHost to send us an UpdateState message
541 // before we destroy it.
542 if (render_view_host_->view())
543 render_view_host_->view()->Hide();
544 RenderViewHost* old_render_view_host = render_view_host_; 581 RenderViewHost* old_render_view_host = render_view_host_;
545
546 // Swap in the pending view and make it active.
547 render_view_host_ = pending_render_view_host_; 582 render_view_host_ = pending_render_view_host_;
548 pending_render_view_host_ = NULL; 583 pending_render_view_host_ = NULL;
549 584
550 // The process will no longer try to exit, so we can decrement the count. 585 // The process will no longer try to exit, so we can decrement the count.
551 render_view_host_->process()->RemovePendingView(); 586 render_view_host_->process()->RemovePendingView();
552 587
553 // If the view is gone, then this RenderViewHost died while it was hidden. 588 // If the view is gone, then this RenderViewHost died while it was hidden.
554 // We ignored the RenderViewGone call at the time, so we should send it now 589 // We ignored the RenderViewGone call at the time, so we should send it now
555 // to make sure the sad tab shows up, etc. 590 // to make sure the sad tab shows up, etc.
556 if (render_view_host_->view()) 591 if (render_view_host_->view())
557 render_view_host_->view()->Show(); 592 render_view_host_->view()->Show();
558 else 593 else
559 delegate_->RenderViewGoneFromRenderManager(render_view_host_); 594 delegate_->RenderViewGoneFromRenderManager(render_view_host_);
560 595
596 // Hide the old view now that the new one is visible.
597 if (old_render_view_host->view()) {
598 old_render_view_host->view()->Hide();
599 old_render_view_host->WasSwappedOut();
600 }
601
561 // Make sure the size is up to date. (Fix for bug 1079768.) 602 // Make sure the size is up to date. (Fix for bug 1079768.)
562 delegate_->UpdateRenderViewSizeForRenderManager(); 603 delegate_->UpdateRenderViewSizeForRenderManager();
563 604
564 if (will_focus_location_bar) 605 if (will_focus_location_bar)
565 delegate_->SetFocusToLocationBar(false); 606 delegate_->SetFocusToLocationBar(false);
566 else if (focus_render_view && render_view_host_->view()) 607 else if (focus_render_view && render_view_host_->view())
567 render_view_host_->view()->Focus(); 608 render_view_host_->view()->Focus();
568 609
569 RenderViewHostSwitchedDetails details; 610 RenderViewHostSwitchedDetails details;
570 details.new_host = render_view_host_; 611 details.new_host = render_view_host_;
571 details.old_host = old_render_view_host; 612 details.old_host = old_render_view_host;
572 NotificationService::current()->Notify( 613 NotificationService::current()->Notify(
573 NotificationType::RENDER_VIEW_HOST_CHANGED, 614 NotificationType::RENDER_VIEW_HOST_CHANGED,
574 Source<NavigationController>(&delegate_->GetControllerForRenderManager()), 615 Source<NavigationController>(&delegate_->GetControllerForRenderManager()),
575 Details<RenderViewHostSwitchedDetails>(&details)); 616 Details<RenderViewHostSwitchedDetails>(&details));
576 617
577 old_render_view_host->Shutdown(); 618 // If the pending view was on the swapped out list, we can remove it.
619 swapped_out_hosts_.erase(render_view_host_->site_instance()->id());
620
621 // If the old RVH is live, we are swapping it out and should keep track of it
622 // in case we navigate back to it.
623 if (old_render_view_host->IsRenderViewLive()) {
624 DCHECK(old_render_view_host->is_swapped_out());
625 swapped_out_hosts_[old_render_view_host->site_instance()->id()] =
626 old_render_view_host;
627 } else {
628 old_render_view_host->Shutdown();
629 }
578 630
579 // Let the task manager know that we've swapped RenderViewHosts, since it 631 // Let the task manager know that we've swapped RenderViewHosts, since it
580 // might need to update its process groupings. 632 // might need to update its process groupings.
581 delegate_->NotifySwappedFromRenderManager(); 633 delegate_->NotifySwappedFromRenderManager();
582 } 634 }
583 635
584 RenderViewHost* RenderViewHostManager::UpdateRendererStateForNavigate( 636 RenderViewHost* RenderViewHostManager::UpdateRendererStateForNavigate(
585 const NavigationEntry& entry) { 637 const NavigationEntry& entry) {
586 // If we are cross-navigating, then we want to get back to normal and navigate 638 // If we are cross-navigating, then we want to get back to normal and navigate
587 // as usual. 639 // as usual.
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 } 729 }
678 730
679 // Same SiteInstance can be used. Navigate render_view_host_ if we are not 731 // Same SiteInstance can be used. Navigate render_view_host_ if we are not
680 // cross navigating. 732 // cross navigating.
681 DCHECK(!cross_navigation_pending_); 733 DCHECK(!cross_navigation_pending_);
682 return render_view_host_; 734 return render_view_host_;
683 } 735 }
684 736
685 void RenderViewHostManager::CancelPending() { 737 void RenderViewHostManager::CancelPending() {
686 RenderViewHost* pending_render_view_host = pending_render_view_host_; 738 RenderViewHost* pending_render_view_host = pending_render_view_host_;
739 pending_render_view_host_ = NULL;
687 740
688 // We no longer need to prevent the process from exiting. 741 // We no longer need to prevent the process from exiting.
689 pending_render_view_host->process()->RemovePendingView(); 742 pending_render_view_host->process()->RemovePendingView();
690 743
691 pending_render_view_host_ = NULL; 744 // The pending RVH may already be on the swapped out list if we started to
692 pending_render_view_host->Shutdown(); 745 // swap it back in and then canceled. If so, make sure it gets swapped out
746 // again. If it's not on the swapped out list (e.g., aborting a pending
747 // load), then it's safe to shut down.
748 if (IsSwappedOut(pending_render_view_host)) {
749 // Any currently suspended navigations are no longer needed.
750 pending_render_view_host->CancelSuspendedNavigations();
751
752 // We can pass -1,-1 because there is no pending response in the
753 // ResourceDispatcherHost to unpause.
754 pending_render_view_host->SwapOut(-1, -1);
755 } else {
756 // We won't be coming back, so shut this one down.
757 pending_render_view_host->Shutdown();
758 }
693 759
694 pending_web_ui_.reset(); 760 pending_web_ui_.reset();
695 } 761 }
696 762
697 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) { 763 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) {
698 // We are doing this in order to work around and to track a crasher 764 // We are doing this in order to work around and to track a crasher
699 // (http://crbug.com/23411) where it seems that pending_render_view_host_ is 765 // (http://crbug.com/23411) where it seems that pending_render_view_host_ is
700 // deleted (not sure from where) but not NULLed. 766 // deleted (not sure from where) but not NULLed.
701 if (rvh == pending_render_view_host_) { 767 if (rvh == pending_render_view_host_) {
702 // If you hit this NOTREACHED, please report it in the following bug 768 // If you hit this NOTREACHED, please report it in the following bug
703 // http://crbug.com/23411 Make sure to include what you were doing when it 769 // http://crbug.com/23411 Make sure to include what you were doing when it
704 // happened (navigating to a new page, closing a tab...) and if you can 770 // happened (navigating to a new page, closing a tab...) and if you can
705 // reproduce. 771 // reproduce.
706 NOTREACHED(); 772 NOTREACHED();
707 pending_render_view_host_ = NULL; 773 pending_render_view_host_ = NULL;
708 } 774 }
775
776 // Make sure deleted RVHs are not kept in the swapped out list while we are
777 // still alive. (If render_view_host_ is null, we're already being deleted.)
778 if (!render_view_host_)
779 return;
780 // We can't look it up by SiteInstance ID, which may no longer be valid.
781 for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin();
782 iter != swapped_out_hosts_.end();
783 ++iter) {
784 if (iter->second == rvh) {
785 swapped_out_hosts_.erase(iter);
786 break;
787 }
788 }
709 } 789 }
710 790
711 void RenderViewHostManager::SwapInRenderViewHost(RenderViewHost* rvh) { 791 void RenderViewHostManager::SwapInRenderViewHost(RenderViewHost* rvh) {
792 // TODO(creis): Abstract out the common code between this and CommitPending.
712 web_ui_.reset(); 793 web_ui_.reset();
713 794
714 // Hide the current view and prepare to destroy it. 795 // Make sure the current RVH is swapped out so that it filters out any
715 if (render_view_host_->view()) 796 // disruptive messages from the renderer. We can pass -1,-1 because there is
716 render_view_host_->view()->Hide(); 797 // no pending response in the ResourceDispatcherHost to unpause.
717 RenderViewHost* old_render_view_host = render_view_host_; 798 render_view_host_->SwapOut(-1, -1);
718 799
719 // Swap in the new view and make it active. 800 // Swap in the new view and make it active.
801 RenderViewHost* old_render_view_host = render_view_host_;
720 render_view_host_ = rvh; 802 render_view_host_ = rvh;
721 render_view_host_->set_delegate(render_view_delegate_); 803 render_view_host_->set_delegate(render_view_delegate_);
722 // Remove old RenderWidgetHostView with mocked out methods so it can be 804 // Remove old RenderWidgetHostView with mocked out methods so it can be
723 // replaced with a new one that's a child of |delegate_|'s view. 805 // replaced with a new one that's a child of |delegate_|'s view.
724 scoped_ptr<RenderWidgetHostView> old_view(render_view_host_->view()); 806 scoped_ptr<RenderWidgetHostView> old_view(render_view_host_->view());
725 render_view_host_->set_view(NULL); 807 render_view_host_->set_view(NULL);
726 delegate_->CreateViewAndSetSizeForRVH(render_view_host_); 808 delegate_->CreateViewAndSetSizeForRVH(render_view_host_);
727 render_view_host_->ActivateDeferredPluginHandles(); 809 render_view_host_->ActivateDeferredPluginHandles();
728 // If the view is gone, then this RenderViewHost died while it was hidden. 810 // If the view is gone, then this RenderViewHost died while it was hidden.
729 // We ignored the RenderViewGone call at the time, so we should send it now 811 // We ignored the RenderViewGone call at the time, so we should send it now
730 // to make sure the sad tab shows up, etc. 812 // to make sure the sad tab shows up, etc.
731 if (render_view_host_->view()) { 813 if (render_view_host_->view()) {
732 // The Hide() is needed to sync the state of |render_view_host_|, which is 814 // The Hide() is needed to sync the state of |render_view_host_|, which is
733 // hidden, with the newly created view, which does not know the 815 // hidden, with the newly created view, which does not know the
734 // RenderViewHost is hidden. 816 // RenderViewHost is hidden.
735 // TODO(tburkard,cbentzel): Figure out if this hack can be removed 817 // TODO(tburkard,cbentzel): Figure out if this hack can be removed
736 // (http://crbug.com/79891). 818 // (http://crbug.com/79891).
737 render_view_host_->view()->Hide(); 819 render_view_host_->view()->Hide();
738 render_view_host_->view()->Show(); 820 render_view_host_->view()->Show();
739 } 821 }
740 822
823 // Hide the current view and prepare to swap it out.
824 if (old_render_view_host->view()) {
825 old_render_view_host->view()->Hide();
826 old_render_view_host->WasSwappedOut();
827 }
828
741 delegate_->UpdateRenderViewSizeForRenderManager(); 829 delegate_->UpdateRenderViewSizeForRenderManager();
742 830
743 RenderViewHostSwitchedDetails details; 831 RenderViewHostSwitchedDetails details;
744 details.new_host = render_view_host_; 832 details.new_host = render_view_host_;
745 details.old_host = old_render_view_host; 833 details.old_host = old_render_view_host;
746 NotificationService::current()->Notify( 834 NotificationService::current()->Notify(
747 NotificationType::RENDER_VIEW_HOST_CHANGED, 835 NotificationType::RENDER_VIEW_HOST_CHANGED,
748 Source<NavigationController>(&delegate_->GetControllerForRenderManager()), 836 Source<NavigationController>(&delegate_->GetControllerForRenderManager()),
749 Details<RenderViewHostSwitchedDetails>(&details)); 837 Details<RenderViewHostSwitchedDetails>(&details));
750 838
751 // This will cause the old RenderViewHost to delete itself. 839 // If the given RVH was on the swapped out list, we can remove it.
752 old_render_view_host->Shutdown(); 840 swapped_out_hosts_.erase(render_view_host_->site_instance()->id());
841
842 // If the old RVH is live, we are swapping it out and should keep track of it
843 // in case we navigate back to it.
844 if (old_render_view_host->IsRenderViewLive()) {
845 DCHECK(old_render_view_host->is_swapped_out());
846 swapped_out_hosts_[old_render_view_host->site_instance()->id()] =
847 old_render_view_host;
848 } else {
849 old_render_view_host->Shutdown();
850 }
753 851
754 // Let the task manager know that we've swapped RenderViewHosts, since it 852 // Let the task manager know that we've swapped RenderViewHosts, since it
755 // might need to update its process groupings. 853 // might need to update its process groupings.
756 delegate_->NotifySwappedFromRenderManager(); 854 delegate_->NotifySwappedFromRenderManager();
757 } 855 }
856
857 bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) {
858 if (!rvh->site_instance())
859 return false;
860
861 return swapped_out_hosts_.find(rvh->site_instance()->id()) !=
862 swapped_out_hosts_.end();
863 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698