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

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

Powered by Google App Engine
This is Rietveld 408576698