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

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

Powered by Google App Engine
This is Rietveld 408576698