OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |