OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/frame_host/render_frame_host_manager.h" | 5 #include "content/browser/frame_host/render_frame_host_manager.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 24 matching lines...) Expand all Loading... | |
35 #include "content/public/browser/notification_types.h" | 35 #include "content/public/browser/notification_types.h" |
36 #include "content/public/browser/render_widget_host_iterator.h" | 36 #include "content/public/browser/render_widget_host_iterator.h" |
37 #include "content/public/browser/render_widget_host_view.h" | 37 #include "content/public/browser/render_widget_host_view.h" |
38 #include "content/public/browser/user_metrics.h" | 38 #include "content/public/browser/user_metrics.h" |
39 #include "content/public/browser/web_ui_controller.h" | 39 #include "content/public/browser/web_ui_controller.h" |
40 #include "content/public/common/content_switches.h" | 40 #include "content/public/common/content_switches.h" |
41 #include "content/public/common/url_constants.h" | 41 #include "content/public/common/url_constants.h" |
42 | 42 |
43 namespace content { | 43 namespace content { |
44 | 44 |
45 RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams( | |
46 const GlobalRequestID& global_request_id, | |
47 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, | |
48 const std::vector<GURL>& transfer_url_chain, | |
49 Referrer referrer, | |
50 PageTransition page_transition, | |
51 int render_frame_id, | |
52 bool should_replace_current_entry) | |
53 : global_request_id(global_request_id), | |
54 cross_site_transferring_request(cross_site_transferring_request.Pass()), | |
55 transfer_url_chain(transfer_url_chain), | |
56 referrer(referrer), | |
57 page_transition(page_transition), | |
58 render_frame_id(render_frame_id), | |
59 should_replace_current_entry(should_replace_current_entry) { | |
60 } | |
61 | |
62 RenderFrameHostManager::PendingNavigationParams::~PendingNavigationParams() {} | |
63 | |
64 bool RenderFrameHostManager::ClearRFHsPendingShutdown(FrameTreeNode* node) { | 45 bool RenderFrameHostManager::ClearRFHsPendingShutdown(FrameTreeNode* node) { |
65 node->render_manager()->pending_delete_hosts_.clear(); | 46 node->render_manager()->pending_delete_hosts_.clear(); |
66 return true; | 47 return true; |
67 } | 48 } |
68 | 49 |
69 RenderFrameHostManager::RenderFrameHostManager( | 50 RenderFrameHostManager::RenderFrameHostManager( |
70 FrameTreeNode* frame_tree_node, | 51 FrameTreeNode* frame_tree_node, |
71 RenderFrameHostDelegate* render_frame_delegate, | 52 RenderFrameHostDelegate* render_frame_delegate, |
72 RenderViewHostDelegate* render_view_delegate, | 53 RenderViewHostDelegate* render_view_delegate, |
73 RenderWidgetHostDelegate* render_widget_delegate, | 54 RenderWidgetHostDelegate* render_widget_delegate, |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 // Notify here as we won't be calling CommitPending (which does the | 195 // Notify here as we won't be calling CommitPending (which does the |
215 // notify). | 196 // notify). |
216 delegate_->NotifySwappedFromRenderManager( | 197 delegate_->NotifySwappedFromRenderManager( |
217 NULL, render_frame_host_.get(), frame_tree_node_->IsMainFrame()); | 198 NULL, render_frame_host_.get(), frame_tree_node_->IsMainFrame()); |
218 } | 199 } |
219 } | 200 } |
220 | 201 |
221 // If entry includes the request ID of a request that is being transferred, | 202 // If entry includes the request ID of a request that is being transferred, |
222 // the destination render frame will take ownership, so release ownership of | 203 // the destination render frame will take ownership, so release ownership of |
223 // the request. | 204 // the request. |
224 if (pending_nav_params_ && | 205 if (cross_site_transferring_request_.get() && |
225 pending_nav_params_->global_request_id == | 206 cross_site_transferring_request_->request_id() == |
226 entry.transferred_global_request_id()) { | 207 entry.transferred_global_request_id()) { |
227 pending_nav_params_->cross_site_transferring_request->ReleaseRequest(); | 208 cross_site_transferring_request_->ReleaseRequest(); |
228 } | 209 } |
229 | 210 |
230 return dest_render_frame_host; | 211 return dest_render_frame_host; |
231 } | 212 } |
232 | 213 |
233 void RenderFrameHostManager::Stop() { | 214 void RenderFrameHostManager::Stop() { |
234 render_frame_host_->render_view_host()->Stop(); | 215 render_frame_host_->render_view_host()->Stop(); |
235 | 216 |
236 // If we are cross-navigating, we should stop the pending renderers. This | 217 // If we are cross-navigating, we should stop the pending renderers. This |
237 // will lead to a DidFailProvisionalLoad, which will properly destroy them. | 218 // will lead to a DidFailProvisionalLoad, which will properly destroy them. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
328 } | 309 } |
329 | 310 |
330 void RenderFrameHostManager::OnCrossSiteResponse( | 311 void RenderFrameHostManager::OnCrossSiteResponse( |
331 RenderFrameHostImpl* pending_render_frame_host, | 312 RenderFrameHostImpl* pending_render_frame_host, |
332 const GlobalRequestID& global_request_id, | 313 const GlobalRequestID& global_request_id, |
333 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, | 314 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, |
334 const std::vector<GURL>& transfer_url_chain, | 315 const std::vector<GURL>& transfer_url_chain, |
335 const Referrer& referrer, | 316 const Referrer& referrer, |
336 PageTransition page_transition, | 317 PageTransition page_transition, |
337 bool should_replace_current_entry) { | 318 bool should_replace_current_entry) { |
338 // This should be called either when the pending RFH is ready to commit or | 319 // We should only get here for transfer navigations. Most cross-process |
339 // when we realize that the current RFH's request requires a transfer. | 320 // navigations can just continue and wait to run the unload handler (by |
321 // swapping out) when the new navigation commits. | |
322 CHECK(cross_site_transferring_request.get()); | |
323 | |
324 // A transfer should only have come from our pending or current RFH. | |
325 // TODO(creis): We need to handle the case that the pending RFH has changed | |
326 // in the mean time, while this was being posted from the IO thread. We | |
327 // should probably cancel the request in that case. | |
340 DCHECK(pending_render_frame_host == pending_render_frame_host_ || | 328 DCHECK(pending_render_frame_host == pending_render_frame_host_ || |
341 pending_render_frame_host == render_frame_host_); | 329 pending_render_frame_host == render_frame_host_); |
342 | 330 |
343 // TODO(creis): Eventually we will want to check all navigation responses | 331 // Store the transferring request so that we can release it if the transfer |
344 // here, but currently we pass information for a transfer if | 332 // navigation matches. |
345 // ShouldSwapProcessesForRedirect returned true in the network stack. | 333 cross_site_transferring_request_ = cross_site_transferring_request.Pass(); |
346 // In that case, we should set up a transfer after the unload handler runs. | |
347 // If |cross_site_transferring_request| is NULL, we will just run the unload | |
348 // handler and resume. | |
349 pending_nav_params_.reset(new PendingNavigationParams( | |
350 global_request_id, cross_site_transferring_request.Pass(), | |
351 transfer_url_chain, referrer, page_transition, | |
352 pending_render_frame_host->GetRoutingID(), | |
353 should_replace_current_entry)); | |
354 | 334 |
355 // Run the unload handler of the current page. | 335 // Sanity check that the params are for the correct frame and process. |
356 SwapOutOldPage(); | 336 // These should match the RenderFrameHost that made the request. |
337 // If it started as a cross-process navigation via OpenURL, this is the | |
338 // pending one. If it wasn't cross-process until the transfer, this is the | |
339 // current one. | |
340 int render_frame_id = pending_render_frame_host_ ? | |
341 pending_render_frame_host_->GetRoutingID() : | |
342 render_frame_host_->GetRoutingID(); | |
343 DCHECK_EQ(render_frame_id, pending_render_frame_host->GetRoutingID()); | |
344 int process_id = pending_render_frame_host_ ? | |
345 pending_render_frame_host_->GetProcess()->GetID() : | |
346 render_frame_host_->GetProcess()->GetID(); | |
347 DCHECK_EQ(process_id, global_request_id.child_id); | |
348 | |
349 // Treat the last URL in the chain as the destination and the remainder as | |
350 // the redirect chain. | |
351 CHECK(transfer_url_chain.size()); | |
352 GURL transfer_url = transfer_url_chain.back(); | |
353 std::vector<GURL> rest_of_chain = transfer_url_chain; | |
354 rest_of_chain.pop_back(); | |
355 | |
356 // We don't know whether the original request had |user_action| set to true. | |
357 // However, since we force the navigation to be in the current tab, it | |
358 // doesn't matter. | |
359 pending_render_frame_host->frame_tree_node()->navigator()->RequestTransferURL( | |
360 pending_render_frame_host, | |
361 transfer_url, | |
362 rest_of_chain, | |
363 referrer, | |
364 page_transition, | |
365 CURRENT_TAB, | |
366 global_request_id, | |
367 should_replace_current_entry, | |
368 true); | |
369 cross_site_transferring_request_.reset(); | |
clamy
2014/08/19 14:59:05
Why do you reset cross_site_transferring_request_
Charlie Reis
2014/08/19 16:26:04
It's only needed during the RequestTransferURL cal
| |
357 } | 370 } |
358 | 371 |
359 void RenderFrameHostManager::OnDeferredAfterResponseStarted( | 372 void RenderFrameHostManager::OnDeferredAfterResponseStarted( |
360 const GlobalRequestID& global_request_id, | 373 const GlobalRequestID& global_request_id, |
361 RenderFrameHostImpl* pending_render_frame_host) { | 374 RenderFrameHostImpl* pending_render_frame_host) { |
362 DCHECK(!response_started_id_.get()); | 375 DCHECK(!response_started_id_.get()); |
363 | 376 |
364 response_started_id_.reset(new GlobalRequestID(global_request_id)); | 377 response_started_id_.reset(new GlobalRequestID(global_request_id)); |
365 } | 378 } |
366 | 379 |
367 void RenderFrameHostManager::ResumeResponseDeferredAtStart() { | 380 void RenderFrameHostManager::ResumeResponseDeferredAtStart() { |
368 DCHECK(response_started_id_.get()); | 381 DCHECK(response_started_id_.get()); |
369 | 382 |
370 RenderProcessHostImpl* process = | 383 RenderProcessHostImpl* process = |
371 static_cast<RenderProcessHostImpl*>(render_frame_host_->GetProcess()); | 384 static_cast<RenderProcessHostImpl*>(render_frame_host_->GetProcess()); |
372 process->ResumeResponseDeferredAtStart(*response_started_id_); | 385 process->ResumeResponseDeferredAtStart(*response_started_id_); |
373 | 386 |
374 render_frame_host_->ClearPendingTransitionRequestData(); | 387 render_frame_host_->ClearPendingTransitionRequestData(); |
375 | 388 |
376 response_started_id_.reset(); | 389 response_started_id_.reset(); |
377 } | 390 } |
378 | 391 |
379 void RenderFrameHostManager::SwappedOut( | |
380 RenderFrameHostImpl* render_frame_host) { | |
381 // Make sure this is from our current RFH, and that we have a pending | |
382 // navigation from OnCrossSiteResponse. (There may be no pending navigation | |
383 // for data URLs that don't make network requests, for example.) If not, | |
384 // just return early and ignore. | |
385 if (render_frame_host != render_frame_host_ || !pending_nav_params_.get()) { | |
386 pending_nav_params_.reset(); | |
387 return; | |
388 } | |
389 | |
390 // Now that the unload handler has run, we need to either initiate the | |
391 // pending transfer (if there is one) or resume the paused response (if not). | |
392 // TODO(creis): The blank swapped out page is visible during this time, but | |
393 // we can shorten this by delivering the response directly, rather than | |
394 // forcing an identical request to be made. | |
395 if (pending_nav_params_->cross_site_transferring_request) { | |
396 // Sanity check that the params are for the correct frame and process. | |
397 // These should match the RenderFrameHost that made the request. | |
398 // If it started as a cross-process navigation via OpenURL, this is the | |
399 // pending one. If it wasn't cross-process until the transfer, this is the | |
400 // current one. | |
401 int render_frame_id = pending_render_frame_host_ ? | |
402 pending_render_frame_host_->GetRoutingID() : | |
403 render_frame_host_->GetRoutingID(); | |
404 DCHECK_EQ(render_frame_id, pending_nav_params_->render_frame_id); | |
405 int process_id = pending_render_frame_host_ ? | |
406 pending_render_frame_host_->GetProcess()->GetID() : | |
407 render_frame_host_->GetProcess()->GetID(); | |
408 DCHECK_EQ(process_id, pending_nav_params_->global_request_id.child_id); | |
409 | |
410 // Treat the last URL in the chain as the destination and the remainder as | |
411 // the redirect chain. | |
412 CHECK(pending_nav_params_->transfer_url_chain.size()); | |
413 GURL transfer_url = pending_nav_params_->transfer_url_chain.back(); | |
414 pending_nav_params_->transfer_url_chain.pop_back(); | |
415 | |
416 // We don't know whether the original request had |user_action| set to true. | |
417 // However, since we force the navigation to be in the current tab, it | |
418 // doesn't matter. | |
419 render_frame_host->frame_tree_node()->navigator()->RequestTransferURL( | |
420 render_frame_host, | |
421 transfer_url, | |
422 pending_nav_params_->transfer_url_chain, | |
423 pending_nav_params_->referrer, | |
424 pending_nav_params_->page_transition, | |
425 CURRENT_TAB, | |
426 pending_nav_params_->global_request_id, | |
427 pending_nav_params_->should_replace_current_entry, | |
428 true); | |
429 } else if (pending_render_frame_host_) { | |
430 RenderProcessHostImpl* pending_process = | |
431 static_cast<RenderProcessHostImpl*>( | |
432 pending_render_frame_host_->GetProcess()); | |
433 pending_process->ResumeDeferredNavigation( | |
434 pending_nav_params_->global_request_id); | |
435 } | |
436 pending_nav_params_.reset(); | |
437 } | |
438 | |
439 void RenderFrameHostManager::DidNavigateFrame( | 392 void RenderFrameHostManager::DidNavigateFrame( |
440 RenderFrameHostImpl* render_frame_host) { | 393 RenderFrameHostImpl* render_frame_host) { |
441 if (!cross_navigation_pending_) { | 394 if (!cross_navigation_pending_) { |
442 DCHECK(!pending_render_frame_host_); | 395 DCHECK(!pending_render_frame_host_); |
443 | 396 |
444 // We should only hear this from our current renderer. | 397 // We should only hear this from our current renderer. |
445 DCHECK_EQ(render_frame_host_, render_frame_host); | 398 DCHECK_EQ(render_frame_host_, render_frame_host); |
446 | 399 |
447 // Even when there is no pending RVH, there may be a pending Web UI. | 400 // Even when there is no pending RVH, there may be a pending Web UI. |
448 if (pending_web_ui()) | 401 if (pending_web_ui()) |
449 CommitPending(); | 402 CommitPending(); |
450 return; | 403 return; |
451 } | 404 } |
452 | 405 |
453 if (render_frame_host == pending_render_frame_host_) { | 406 if (render_frame_host == pending_render_frame_host_) { |
454 // The pending cross-site navigation completed, so show the renderer. | 407 // The pending cross-site navigation completed, so show the renderer. |
455 // If it committed without sending network requests (e.g., data URLs), | |
456 // then we still need to swap out the old RFH first and run its unload | |
457 // handler, only if it hasn't happened yet. OK for that to happen in the | |
458 // background. | |
459 if (pending_render_frame_host_->HasPendingCrossSiteRequest() && | |
460 pending_render_frame_host_->render_view_host()->rvh_state() == | |
461 RenderViewHostImpl::STATE_DEFAULT) { | |
462 SwapOutOldPage(); | |
463 } | |
464 | |
465 CommitPending(); | 408 CommitPending(); |
466 cross_navigation_pending_ = false; | 409 cross_navigation_pending_ = false; |
467 } else if (render_frame_host == render_frame_host_) { | 410 } else if (render_frame_host == render_frame_host_) { |
468 // A navigation in the original page has taken place. Cancel the pending | 411 // A navigation in the original page has taken place. Cancel the pending |
469 // one. | 412 // one. |
470 CancelPending(); | 413 CancelPending(); |
471 cross_navigation_pending_ = false; | 414 cross_navigation_pending_ = false; |
472 } else { | 415 } else { |
473 // No one else should be sending us DidNavigate in this state. | 416 // No one else should be sending us DidNavigate in this state. |
474 DCHECK(false); | 417 DCHECK(false); |
(...skipping 26 matching lines...) Expand all Loading... | |
501 } | 444 } |
502 | 445 |
503 // Now delete them. | 446 // Now delete them. |
504 while (!ids_to_remove.empty()) { | 447 while (!ids_to_remove.empty()) { |
505 delete proxy_hosts_[ids_to_remove.back()]; | 448 delete proxy_hosts_[ids_to_remove.back()]; |
506 proxy_hosts_.erase(ids_to_remove.back()); | 449 proxy_hosts_.erase(ids_to_remove.back()); |
507 ids_to_remove.pop_back(); | 450 ids_to_remove.pop_back(); |
508 } | 451 } |
509 } | 452 } |
510 | 453 |
511 void RenderFrameHostManager::SwapOutOldPage() { | 454 void RenderFrameHostManager::SwapOutOldPage( |
512 // Should only see this while we have a pending renderer or transfer. | 455 RenderFrameHostImpl* old_render_frame_host) { |
513 CHECK(cross_navigation_pending_ || pending_nav_params_.get()); | 456 // Should only see this while we have a pending renderer. |
457 CHECK(cross_navigation_pending_); | |
514 | 458 |
515 // Tell the renderer to suppress any further modal dialogs so that we can swap | 459 // Tell the renderer to suppress any further modal dialogs so that we can swap |
516 // it out. This must be done before canceling any current dialog, in case | 460 // it out. This must be done before canceling any current dialog, in case |
517 // there is a loop creating additional dialogs. | 461 // there is a loop creating additional dialogs. |
518 // TODO(creis): Handle modal dialogs in subframe processes. | 462 // TODO(creis): Handle modal dialogs in subframe processes. |
519 render_frame_host_->render_view_host()->SuppressDialogsUntilSwapOut(); | 463 old_render_frame_host->render_view_host()->SuppressDialogsUntilSwapOut(); |
520 | 464 |
521 // Now close any modal dialogs that would prevent us from swapping out. This | 465 // Now close any modal dialogs that would prevent us from swapping out. This |
522 // must be done separately from SwapOut, so that the PageGroupLoadDeferrer is | 466 // must be done separately from SwapOut, so that the PageGroupLoadDeferrer is |
523 // no longer on the stack when we send the SwapOut message. | 467 // no longer on the stack when we send the SwapOut message. |
524 delegate_->CancelModalDialogsForRenderManager(); | 468 delegate_->CancelModalDialogsForRenderManager(); |
525 | 469 |
526 // Create the RenderFrameProxyHost that will replace the | 470 // Create the RenderFrameProxyHost that will replace the |
527 // RenderFrameHost which is swapping out. If one exists, ensure it is deleted | 471 // RenderFrameHost which is swapping out. If one exists, ensure it is deleted |
528 // from the map and not leaked. | 472 // from the map and not leaked. |
529 DeleteRenderFrameProxyHost(render_frame_host_->GetSiteInstance()); | 473 DeleteRenderFrameProxyHost(old_render_frame_host->GetSiteInstance()); |
530 | 474 |
531 RenderFrameProxyHost* proxy = new RenderFrameProxyHost( | 475 RenderFrameProxyHost* proxy = new RenderFrameProxyHost( |
532 render_frame_host_->GetSiteInstance(), frame_tree_node_); | 476 old_render_frame_host->GetSiteInstance(), frame_tree_node_); |
533 std::pair<RenderFrameProxyHostMap::iterator, bool> result = | 477 std::pair<RenderFrameProxyHostMap::iterator, bool> result = |
534 proxy_hosts_.insert(std::make_pair( | 478 proxy_hosts_.insert(std::make_pair( |
535 render_frame_host_->GetSiteInstance()->GetId(), proxy)); | 479 old_render_frame_host->GetSiteInstance()->GetId(), proxy)); |
536 CHECK(result.second) << "Inserting a duplicate item."; | 480 CHECK(result.second) << "Inserting a duplicate item."; |
537 | 481 |
538 // Tell the old frame it is being swapped out. This will fire the unload | 482 // Tell the old frame it is being swapped out. This will fire the unload |
539 // handler in the background (without firing the beforeunload handler a second | 483 // handler in the background (without firing the beforeunload handler a second |
540 // time). When the navigation completes, we will send a message to the | 484 // time). This is done right after we commit the new RenderFrameHost. |
541 // ResourceDispatcherHost, allowing the pending RVH's response to resume. | 485 old_render_frame_host->SwapOut(proxy); |
542 render_frame_host_->SwapOut(proxy); | |
543 | |
544 // ResourceDispatcherHost has told us to run the onunload handler, which | |
545 // means it is not a download or unsafe page, and we are going to perform the | |
546 // navigation. Thus, we no longer need to remember that the RenderFrameHost | |
547 // is part of a pending cross-site request. | |
548 if (pending_render_frame_host_) { | |
549 pending_render_frame_host_->SetHasPendingCrossSiteRequest(false); | |
550 } | |
551 } | 486 } |
552 | 487 |
553 void RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance( | 488 void RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance( |
554 int32 site_instance_id, | 489 int32 site_instance_id, |
555 RenderFrameHostImpl* rfh) { | 490 RenderFrameHostImpl* rfh) { |
556 RFHPendingDeleteMap::iterator iter = | 491 RFHPendingDeleteMap::iterator iter = |
557 pending_delete_hosts_.find(site_instance_id); | 492 pending_delete_hosts_.find(site_instance_id); |
558 if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh) | 493 if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh) |
559 pending_delete_hosts_.erase(site_instance_id); | 494 pending_delete_hosts_.erase(site_instance_id); |
560 } | 495 } |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1100 return MSG_ROUTING_NONE; | 1035 return MSG_ROUTING_NONE; |
1101 } | 1036 } |
1102 | 1037 |
1103 void RenderFrameHostManager::CommitPending() { | 1038 void RenderFrameHostManager::CommitPending() { |
1104 // First check whether we're going to want to focus the location bar after | 1039 // First check whether we're going to want to focus the location bar after |
1105 // this commit. We do this now because the navigation hasn't formally | 1040 // this commit. We do this now because the navigation hasn't formally |
1106 // committed yet, so if we've already cleared |pending_web_ui_| the call chain | 1041 // committed yet, so if we've already cleared |pending_web_ui_| the call chain |
1107 // this triggers won't be able to figure out what's going on. | 1042 // this triggers won't be able to figure out what's going on. |
1108 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); | 1043 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); |
1109 | 1044 |
1110 // We expect SwapOutOldPage to have canceled any modal dialogs and told the | |
1111 // renderer to suppress any further dialogs until it is swapped out. However, | |
1112 // crash reports indicate that it's still possible for modal dialogs to exist | |
1113 // at this point, which poses a risk if we delete their RenderViewHost below. | |
1114 // Cancel them again to be safe. http://crbug.com/324320. | |
1115 delegate_->CancelModalDialogsForRenderManager(); | |
1116 | |
1117 // Next commit the Web UI, if any. Either replace |web_ui_| with | 1045 // Next commit the Web UI, if any. Either replace |web_ui_| with |
1118 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or | 1046 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or |
1119 // leave |web_ui_| as is if reusing it. | 1047 // leave |web_ui_| as is if reusing it. |
1120 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); | 1048 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); |
1121 if (pending_web_ui_) { | 1049 if (pending_web_ui_) { |
1122 web_ui_.reset(pending_web_ui_.release()); | 1050 web_ui_.reset(pending_web_ui_.release()); |
1123 } else if (!pending_and_current_web_ui_.get()) { | 1051 } else if (!pending_and_current_web_ui_.get()) { |
1124 web_ui_.reset(); | 1052 web_ui_.reset(); |
1125 } else { | 1053 } else { |
1126 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); | 1054 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1159 // If the view is gone, then this RenderViewHost died while it was hidden. | 1087 // If the view is gone, then this RenderViewHost died while it was hidden. |
1160 // We ignored the RenderProcessGone call at the time, so we should send it now | 1088 // We ignored the RenderProcessGone call at the time, so we should send it now |
1161 // to make sure the sad tab shows up, etc. | 1089 // to make sure the sad tab shows up, etc. |
1162 if (!render_frame_host_->render_view_host()->GetView()) { | 1090 if (!render_frame_host_->render_view_host()->GetView()) { |
1163 delegate_->RenderProcessGoneFromRenderManager( | 1091 delegate_->RenderProcessGoneFromRenderManager( |
1164 render_frame_host_->render_view_host()); | 1092 render_frame_host_->render_view_host()); |
1165 } else if (!delegate_->IsHidden()) { | 1093 } else if (!delegate_->IsHidden()) { |
1166 render_frame_host_->render_view_host()->GetView()->Show(); | 1094 render_frame_host_->render_view_host()->GetView()->Show(); |
1167 } | 1095 } |
1168 | 1096 |
1169 // If the old view is live and top-level, hide it now that the new one is | 1097 // If the old frame is live, swap it out now that the new frame is visible. |
1170 // visible. | |
1171 int32 old_site_instance_id = | 1098 int32 old_site_instance_id = |
1172 old_render_frame_host->GetSiteInstance()->GetId(); | 1099 old_render_frame_host->GetSiteInstance()->GetId(); |
1173 if (old_render_frame_host->render_view_host()->GetView()) { | 1100 if (old_render_frame_host->render_view_host()->IsRenderViewLive()) { |
1174 if (is_main_frame) { | 1101 SwapOutOldPage(old_render_frame_host.get()); |
1175 old_render_frame_host->render_view_host()->GetView()->Hide(); | 1102 |
1176 old_render_frame_host->render_view_host()->WasSwappedOut(base::Bind( | 1103 // Schedule the old frame to shut down after it swaps out, if there are no |
1104 // other active views in its SiteInstance. | |
1105 if (!static_cast<SiteInstanceImpl*>( | |
1106 old_render_frame_host->GetSiteInstance())->active_view_count()) { | |
1107 old_render_frame_host->render_view_host()->SetPendingShutdown(base::Bind( | |
1177 &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance, | 1108 &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance, |
1178 weak_factory_.GetWeakPtr(), | 1109 weak_factory_.GetWeakPtr(), |
1179 old_site_instance_id, | 1110 old_site_instance_id, |
1180 old_render_frame_host.get())); | 1111 old_render_frame_host.get())); |
1181 } else { | |
1182 // TODO(creis): We'll need to set this back to false if we navigate back. | |
1183 old_render_frame_host->set_swapped_out(true); | |
1184 } | 1112 } |
1185 } | 1113 } |
1186 | 1114 |
1115 // For top-level frames, also hide the old RenderViewHost's view. | |
1116 if (is_main_frame && old_render_frame_host->render_view_host()->GetView()) | |
1117 old_render_frame_host->render_view_host()->GetView()->Hide(); | |
1118 | |
1187 // Make sure the size is up to date. (Fix for bug 1079768.) | 1119 // Make sure the size is up to date. (Fix for bug 1079768.) |
1188 delegate_->UpdateRenderViewSizeForRenderManager(); | 1120 delegate_->UpdateRenderViewSizeForRenderManager(); |
1189 | 1121 |
1190 if (will_focus_location_bar) { | 1122 if (will_focus_location_bar) { |
1191 delegate_->SetFocusToLocationBar(false); | 1123 delegate_->SetFocusToLocationBar(false); |
1192 } else if (focus_render_view && | 1124 } else if (focus_render_view && |
1193 render_frame_host_->render_view_host()->GetView()) { | 1125 render_frame_host_->render_view_host()->GetView()) { |
1194 render_frame_host_->render_view_host()->GetView()->Focus(); | 1126 render_frame_host_->render_view_host()->GetView()->Focus(); |
1195 } | 1127 } |
1196 | 1128 |
1197 // Notify that we've swapped RenderFrameHosts. We do this before shutting down | 1129 // Notify that we've swapped RenderFrameHosts. We do this before shutting down |
1198 // the RFH so that we can clean up RendererResources related to the RFH first. | 1130 // the RFH so that we can clean up RendererResources related to the RFH first. |
1199 delegate_->NotifySwappedFromRenderManager( | 1131 delegate_->NotifySwappedFromRenderManager( |
1200 old_render_frame_host.get(), render_frame_host_.get(), is_main_frame); | 1132 old_render_frame_host.get(), render_frame_host_.get(), is_main_frame); |
1201 | 1133 |
1202 // If the old RFH is not live, just return as there is no work to do. | 1134 // If the old RFH is not live, just return as there is no further work to do. |
1203 if (!old_render_frame_host->render_view_host()->IsRenderViewLive()) { | 1135 if (!old_render_frame_host->render_view_host()->IsRenderViewLive()) |
1204 return; | 1136 return; |
1205 } | |
1206 | 1137 |
1207 // If the old RFH is live, we are swapping it out and should keep track of | 1138 // If the old RFH is live, we are swapping it out and should keep track of |
1208 // it in case we navigate back to it, or it is waiting for the unload event | 1139 // it in case we navigate back to it, or it is waiting for the unload event |
1209 // to execute in the background. | 1140 // to execute in the background. |
1210 // TODO(creis): Swap out the subframe in --site-per-process. | 1141 // TODO(creis): Swap out the subframe in --site-per-process. |
1211 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) | 1142 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { |
1212 DCHECK(old_render_frame_host->is_swapped_out() || | 1143 DCHECK(old_render_frame_host->is_swapped_out() || |
1213 !RenderViewHostImpl::IsRVHStateActive( | 1144 !RenderViewHostImpl::IsRVHStateActive( |
1214 old_render_frame_host->render_view_host()->rvh_state())); | 1145 old_render_frame_host->render_view_host()->rvh_state())); |
1146 } | |
1215 | 1147 |
1216 // If the RenderViewHost backing the RenderFrameHost is pending shutdown, | 1148 // If the RenderViewHost backing the RenderFrameHost is pending shutdown, |
1217 // the RenderFrameHost should be put in the map of RenderFrameHosts pending | 1149 // the RenderFrameHost should be put in the map of RenderFrameHosts pending |
1218 // shutdown. Otherwise, it is stored in the map of proxy hosts. | 1150 // shutdown. Otherwise, it is stored in the map of proxy hosts. |
1219 if (old_render_frame_host->render_view_host()->rvh_state() == | 1151 if (old_render_frame_host->render_view_host()->rvh_state() == |
1220 RenderViewHostImpl::STATE_PENDING_SHUTDOWN) { | 1152 RenderViewHostImpl::STATE_PENDING_SHUTDOWN) { |
1221 // The proxy for this RenderFrameHost is created when sending the | 1153 // The proxy for this RenderFrameHost is created when sending the |
1222 // SwapOut message, so check if it already exists and delete it. | 1154 // SwapOut message, so check if it already exists and delete it. |
1223 RenderFrameProxyHostMap::iterator iter = | 1155 RenderFrameProxyHostMap::iterator iter = |
1224 proxy_hosts_.find(old_site_instance_id); | 1156 proxy_hosts_.find(old_site_instance_id); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1416 // Suspend the new render view (i.e., don't let it send the cross-site | 1348 // Suspend the new render view (i.e., don't let it send the cross-site |
1417 // Navigate message) until we hear back from the old renderer's | 1349 // Navigate message) until we hear back from the old renderer's |
1418 // beforeunload handler. If the handler returns false, we'll have to | 1350 // beforeunload handler. If the handler returns false, we'll have to |
1419 // cancel the request. | 1351 // cancel the request. |
1420 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); | 1352 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); |
1421 bool is_transfer = | 1353 bool is_transfer = |
1422 entry.transferred_global_request_id() != GlobalRequestID(); | 1354 entry.transferred_global_request_id() != GlobalRequestID(); |
1423 if (is_transfer) { | 1355 if (is_transfer) { |
1424 // We don't need to stop the old renderer or run beforeunload/unload | 1356 // We don't need to stop the old renderer or run beforeunload/unload |
1425 // handlers, because those have already been done. | 1357 // handlers, because those have already been done. |
1426 DCHECK(pending_nav_params_->global_request_id == | 1358 DCHECK(cross_site_transferring_request_->request_id() == |
1427 entry.transferred_global_request_id()); | 1359 entry.transferred_global_request_id()); |
1428 } else { | 1360 } else { |
1429 // Also make sure the old render view stops, in case a load is in | 1361 // Also make sure the old render view stops, in case a load is in |
1430 // progress. (We don't want to do this for transfers, since it will | 1362 // progress. (We don't want to do this for transfers, since it will |
1431 // interrupt the transfer with an unexpected DidStopLoading.) | 1363 // interrupt the transfer with an unexpected DidStopLoading.) |
1432 render_frame_host_->render_view_host()->Send(new ViewMsg_Stop( | 1364 render_frame_host_->render_view_host()->Send(new ViewMsg_Stop( |
1433 render_frame_host_->render_view_host()->GetRoutingID())); | 1365 render_frame_host_->render_view_host()->GetRoutingID())); |
1434 | 1366 |
1435 pending_render_frame_host_->SetNavigationsSuspended(true, | 1367 pending_render_frame_host_->SetNavigationsSuspended(true, |
1436 base::TimeTicks()); | 1368 base::TimeTicks()); |
1437 | |
1438 // Tell the CrossSiteRequestManager that this RFH has a pending cross-site | |
1439 // request, so that ResourceDispatcherHost will know to tell us to run the | |
1440 // old page's unload handler before it sends the response. | |
1441 pending_render_frame_host_->SetHasPendingCrossSiteRequest(true); | |
1442 } | 1369 } |
1443 | 1370 |
1444 // We now have a pending RFH. | 1371 // We now have a pending RFH. |
1445 DCHECK(!cross_navigation_pending_); | 1372 DCHECK(!cross_navigation_pending_); |
1446 cross_navigation_pending_ = true; | 1373 cross_navigation_pending_ = true; |
1447 | 1374 |
1448 // Unless we are transferring an existing request, we should now | 1375 // Unless we are transferring an existing request, we should now |
1449 // tell the old render view to run its beforeunload handler, since it | 1376 // tell the old render view to run its beforeunload handler, since it |
1450 // doesn't otherwise know that the cross-site request is happening. This | 1377 // doesn't otherwise know that the cross-site request is happening. This |
1451 // will trigger a call to OnBeforeUnloadACK with the reply. | 1378 // will trigger a call to OnBeforeUnloadACK with the reply. |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1602 void RenderFrameHostManager::DeleteRenderFrameProxyHost( | 1529 void RenderFrameHostManager::DeleteRenderFrameProxyHost( |
1603 SiteInstance* instance) { | 1530 SiteInstance* instance) { |
1604 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId()); | 1531 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId()); |
1605 if (iter != proxy_hosts_.end()) { | 1532 if (iter != proxy_hosts_.end()) { |
1606 delete iter->second; | 1533 delete iter->second; |
1607 proxy_hosts_.erase(iter); | 1534 proxy_hosts_.erase(iter); |
1608 } | 1535 } |
1609 } | 1536 } |
1610 | 1537 |
1611 } // namespace content | 1538 } // namespace content |
OLD | NEW |