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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 begin_navigation_params.transition_type = navigate_params.transition; | 68 begin_navigation_params.transition_type = navigate_params.transition; |
69 begin_navigation_params.should_replace_current_entry = | 69 begin_navigation_params.should_replace_current_entry = |
70 navigate_params.should_replace_current_entry; | 70 navigate_params.should_replace_current_entry; |
71 begin_navigation_params.allow_download = | 71 begin_navigation_params.allow_download = |
72 navigate_params.allow_download; | 72 navigate_params.allow_download; |
73 return begin_navigation_params; | 73 return begin_navigation_params; |
74 } | 74 } |
75 | 75 |
76 } // namespace | 76 } // namespace |
77 | 77 |
78 RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams( | |
79 const GlobalRequestID& global_request_id, | |
80 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, | |
81 const std::vector<GURL>& transfer_url_chain, | |
82 Referrer referrer, | |
83 PageTransition page_transition, | |
84 int render_frame_id, | |
85 bool should_replace_current_entry) | |
86 : global_request_id(global_request_id), | |
87 cross_site_transferring_request(cross_site_transferring_request.Pass()), | |
88 transfer_url_chain(transfer_url_chain), | |
89 referrer(referrer), | |
90 page_transition(page_transition), | |
91 render_frame_id(render_frame_id), | |
92 should_replace_current_entry(should_replace_current_entry) { | |
93 } | |
94 | |
95 RenderFrameHostManager::PendingNavigationParams::~PendingNavigationParams() {} | |
96 | |
97 bool RenderFrameHostManager::ClearRFHsPendingShutdown(FrameTreeNode* node) { | 78 bool RenderFrameHostManager::ClearRFHsPendingShutdown(FrameTreeNode* node) { |
98 node->render_manager()->pending_delete_hosts_.clear(); | 79 node->render_manager()->pending_delete_hosts_.clear(); |
99 return true; | 80 return true; |
100 } | 81 } |
101 | 82 |
102 RenderFrameHostManager::RenderFrameHostManager( | 83 RenderFrameHostManager::RenderFrameHostManager( |
103 FrameTreeNode* frame_tree_node, | 84 FrameTreeNode* frame_tree_node, |
104 RenderFrameHostDelegate* render_frame_delegate, | 85 RenderFrameHostDelegate* render_frame_delegate, |
105 RenderViewHostDelegate* render_view_delegate, | 86 RenderViewHostDelegate* render_view_delegate, |
106 RenderWidgetHostDelegate* render_widget_delegate, | 87 RenderWidgetHostDelegate* render_widget_delegate, |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 // Notify here as we won't be calling CommitPending (which does the | 228 // Notify here as we won't be calling CommitPending (which does the |
248 // notify). | 229 // notify). |
249 delegate_->NotifySwappedFromRenderManager( | 230 delegate_->NotifySwappedFromRenderManager( |
250 NULL, render_frame_host_.get(), frame_tree_node_->IsMainFrame()); | 231 NULL, render_frame_host_.get(), frame_tree_node_->IsMainFrame()); |
251 } | 232 } |
252 } | 233 } |
253 | 234 |
254 // If entry includes the request ID of a request that is being transferred, | 235 // If entry includes the request ID of a request that is being transferred, |
255 // the destination render frame will take ownership, so release ownership of | 236 // the destination render frame will take ownership, so release ownership of |
256 // the request. | 237 // the request. |
257 if (pending_nav_params_ && | 238 if (cross_site_transferring_request_.get() && |
258 pending_nav_params_->global_request_id == | 239 cross_site_transferring_request_->request_id() == |
259 entry.transferred_global_request_id()) { | 240 entry.transferred_global_request_id()) { |
260 pending_nav_params_->cross_site_transferring_request->ReleaseRequest(); | 241 cross_site_transferring_request_->ReleaseRequest(); |
261 } | 242 } |
262 | 243 |
263 return dest_render_frame_host; | 244 return dest_render_frame_host; |
264 } | 245 } |
265 | 246 |
266 void RenderFrameHostManager::Stop() { | 247 void RenderFrameHostManager::Stop() { |
267 render_frame_host_->render_view_host()->Stop(); | 248 render_frame_host_->render_view_host()->Stop(); |
268 | 249 |
269 // If we are cross-navigating, we should stop the pending renderers. This | 250 // If we are cross-navigating, we should stop the pending renderers. This |
270 // will lead to a DidFailProvisionalLoad, which will properly destroy them. | 251 // will lead to a DidFailProvisionalLoad, which will properly destroy them. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 } | 342 } |
362 | 343 |
363 void RenderFrameHostManager::OnCrossSiteResponse( | 344 void RenderFrameHostManager::OnCrossSiteResponse( |
364 RenderFrameHostImpl* pending_render_frame_host, | 345 RenderFrameHostImpl* pending_render_frame_host, |
365 const GlobalRequestID& global_request_id, | 346 const GlobalRequestID& global_request_id, |
366 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, | 347 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, |
367 const std::vector<GURL>& transfer_url_chain, | 348 const std::vector<GURL>& transfer_url_chain, |
368 const Referrer& referrer, | 349 const Referrer& referrer, |
369 PageTransition page_transition, | 350 PageTransition page_transition, |
370 bool should_replace_current_entry) { | 351 bool should_replace_current_entry) { |
371 // This should be called either when the pending RFH is ready to commit or | 352 // We should only get here for transfer navigations. Most cross-process |
372 // when we realize that the current RFH's request requires a transfer. | 353 // navigations can just continue and wait to run the unload handler (by |
| 354 // swapping out) when the new navigation commits. |
| 355 CHECK(cross_site_transferring_request.get()); |
| 356 |
| 357 // A transfer should only have come from our pending or current RFH. |
| 358 // TODO(creis): We need to handle the case that the pending RFH has changed |
| 359 // in the mean time, while this was being posted from the IO thread. We |
| 360 // should probably cancel the request in that case. |
373 DCHECK(pending_render_frame_host == pending_render_frame_host_ || | 361 DCHECK(pending_render_frame_host == pending_render_frame_host_ || |
374 pending_render_frame_host == render_frame_host_); | 362 pending_render_frame_host == render_frame_host_); |
375 | 363 |
376 // TODO(creis): Eventually we will want to check all navigation responses | 364 // Store the transferring request so that we can release it if the transfer |
377 // here, but currently we pass information for a transfer if | 365 // navigation matches. |
378 // ShouldSwapProcessesForRedirect returned true in the network stack. | 366 cross_site_transferring_request_ = cross_site_transferring_request.Pass(); |
379 // In that case, we should set up a transfer after the unload handler runs. | |
380 // If |cross_site_transferring_request| is NULL, we will just run the unload | |
381 // handler and resume. | |
382 pending_nav_params_.reset(new PendingNavigationParams( | |
383 global_request_id, cross_site_transferring_request.Pass(), | |
384 transfer_url_chain, referrer, page_transition, | |
385 pending_render_frame_host->GetRoutingID(), | |
386 should_replace_current_entry)); | |
387 | 367 |
388 // Run the unload handler of the current page. | 368 // Sanity check that the params are for the correct frame and process. |
389 SwapOutOldPage(); | 369 // These should match the RenderFrameHost that made the request. |
| 370 // If it started as a cross-process navigation via OpenURL, this is the |
| 371 // pending one. If it wasn't cross-process until the transfer, this is the |
| 372 // current one. |
| 373 int render_frame_id = pending_render_frame_host_ ? |
| 374 pending_render_frame_host_->GetRoutingID() : |
| 375 render_frame_host_->GetRoutingID(); |
| 376 DCHECK_EQ(render_frame_id, pending_render_frame_host->GetRoutingID()); |
| 377 int process_id = pending_render_frame_host_ ? |
| 378 pending_render_frame_host_->GetProcess()->GetID() : |
| 379 render_frame_host_->GetProcess()->GetID(); |
| 380 DCHECK_EQ(process_id, global_request_id.child_id); |
| 381 |
| 382 // Treat the last URL in the chain as the destination and the remainder as |
| 383 // the redirect chain. |
| 384 CHECK(transfer_url_chain.size()); |
| 385 GURL transfer_url = transfer_url_chain.back(); |
| 386 std::vector<GURL> rest_of_chain = transfer_url_chain; |
| 387 rest_of_chain.pop_back(); |
| 388 |
| 389 // We don't know whether the original request had |user_action| set to true. |
| 390 // However, since we force the navigation to be in the current tab, it |
| 391 // doesn't matter. |
| 392 pending_render_frame_host->frame_tree_node()->navigator()->RequestTransferURL( |
| 393 pending_render_frame_host, |
| 394 transfer_url, |
| 395 rest_of_chain, |
| 396 referrer, |
| 397 page_transition, |
| 398 CURRENT_TAB, |
| 399 global_request_id, |
| 400 should_replace_current_entry, |
| 401 true); |
| 402 |
| 403 // The transferring request was only needed during the RequestTransferURL |
| 404 // call, so it is safe to clear at this point. |
| 405 cross_site_transferring_request_.reset(); |
390 } | 406 } |
391 | 407 |
392 void RenderFrameHostManager::OnDeferredAfterResponseStarted( | 408 void RenderFrameHostManager::OnDeferredAfterResponseStarted( |
393 const GlobalRequestID& global_request_id, | 409 const GlobalRequestID& global_request_id, |
394 RenderFrameHostImpl* pending_render_frame_host) { | 410 RenderFrameHostImpl* pending_render_frame_host) { |
395 DCHECK(!response_started_id_.get()); | 411 DCHECK(!response_started_id_.get()); |
396 | 412 |
397 response_started_id_.reset(new GlobalRequestID(global_request_id)); | 413 response_started_id_.reset(new GlobalRequestID(global_request_id)); |
398 } | 414 } |
399 | 415 |
400 void RenderFrameHostManager::ResumeResponseDeferredAtStart() { | 416 void RenderFrameHostManager::ResumeResponseDeferredAtStart() { |
401 DCHECK(response_started_id_.get()); | 417 DCHECK(response_started_id_.get()); |
402 | 418 |
403 RenderProcessHostImpl* process = | 419 RenderProcessHostImpl* process = |
404 static_cast<RenderProcessHostImpl*>(render_frame_host_->GetProcess()); | 420 static_cast<RenderProcessHostImpl*>(render_frame_host_->GetProcess()); |
405 process->ResumeResponseDeferredAtStart(*response_started_id_); | 421 process->ResumeResponseDeferredAtStart(*response_started_id_); |
406 | 422 |
407 render_frame_host_->ClearPendingTransitionRequestData(); | 423 render_frame_host_->ClearPendingTransitionRequestData(); |
408 | 424 |
409 response_started_id_.reset(); | 425 response_started_id_.reset(); |
410 } | 426 } |
411 | 427 |
412 void RenderFrameHostManager::SwappedOut( | |
413 RenderFrameHostImpl* render_frame_host) { | |
414 // Make sure this is from our current RFH, and that we have a pending | |
415 // navigation from OnCrossSiteResponse. (There may be no pending navigation | |
416 // for data URLs that don't make network requests, for example.) If not, | |
417 // just return early and ignore. | |
418 if (render_frame_host != render_frame_host_ || !pending_nav_params_.get()) { | |
419 pending_nav_params_.reset(); | |
420 return; | |
421 } | |
422 | |
423 // Now that the unload handler has run, we need to either initiate the | |
424 // pending transfer (if there is one) or resume the paused response (if not). | |
425 // TODO(creis): The blank swapped out page is visible during this time, but | |
426 // we can shorten this by delivering the response directly, rather than | |
427 // forcing an identical request to be made. | |
428 if (pending_nav_params_->cross_site_transferring_request) { | |
429 // Sanity check that the params are for the correct frame and process. | |
430 // These should match the RenderFrameHost that made the request. | |
431 // If it started as a cross-process navigation via OpenURL, this is the | |
432 // pending one. If it wasn't cross-process until the transfer, this is the | |
433 // current one. | |
434 int render_frame_id = pending_render_frame_host_ ? | |
435 pending_render_frame_host_->GetRoutingID() : | |
436 render_frame_host_->GetRoutingID(); | |
437 DCHECK_EQ(render_frame_id, pending_nav_params_->render_frame_id); | |
438 int process_id = pending_render_frame_host_ ? | |
439 pending_render_frame_host_->GetProcess()->GetID() : | |
440 render_frame_host_->GetProcess()->GetID(); | |
441 DCHECK_EQ(process_id, pending_nav_params_->global_request_id.child_id); | |
442 | |
443 // Treat the last URL in the chain as the destination and the remainder as | |
444 // the redirect chain. | |
445 CHECK(pending_nav_params_->transfer_url_chain.size()); | |
446 GURL transfer_url = pending_nav_params_->transfer_url_chain.back(); | |
447 pending_nav_params_->transfer_url_chain.pop_back(); | |
448 | |
449 // We don't know whether the original request had |user_action| set to true. | |
450 // However, since we force the navigation to be in the current tab, it | |
451 // doesn't matter. | |
452 render_frame_host->frame_tree_node()->navigator()->RequestTransferURL( | |
453 render_frame_host, | |
454 transfer_url, | |
455 pending_nav_params_->transfer_url_chain, | |
456 pending_nav_params_->referrer, | |
457 pending_nav_params_->page_transition, | |
458 CURRENT_TAB, | |
459 pending_nav_params_->global_request_id, | |
460 pending_nav_params_->should_replace_current_entry, | |
461 true); | |
462 } else if (pending_render_frame_host_) { | |
463 RenderProcessHostImpl* pending_process = | |
464 static_cast<RenderProcessHostImpl*>( | |
465 pending_render_frame_host_->GetProcess()); | |
466 pending_process->ResumeDeferredNavigation( | |
467 pending_nav_params_->global_request_id); | |
468 } | |
469 pending_nav_params_.reset(); | |
470 } | |
471 | |
472 void RenderFrameHostManager::DidNavigateFrame( | 428 void RenderFrameHostManager::DidNavigateFrame( |
473 RenderFrameHostImpl* render_frame_host) { | 429 RenderFrameHostImpl* render_frame_host) { |
474 if (!cross_navigation_pending_) { | 430 if (!cross_navigation_pending_) { |
475 DCHECK(!pending_render_frame_host_); | 431 DCHECK(!pending_render_frame_host_); |
476 | 432 |
477 // We should only hear this from our current renderer. | 433 // We should only hear this from our current renderer. |
478 DCHECK_EQ(render_frame_host_, render_frame_host); | 434 DCHECK_EQ(render_frame_host_, render_frame_host); |
479 | 435 |
480 // Even when there is no pending RVH, there may be a pending Web UI. | 436 // Even when there is no pending RVH, there may be a pending Web UI. |
481 if (pending_web_ui()) | 437 if (pending_web_ui()) |
482 CommitPending(); | 438 CommitPending(); |
483 return; | 439 return; |
484 } | 440 } |
485 | 441 |
486 if (render_frame_host == pending_render_frame_host_) { | 442 if (render_frame_host == pending_render_frame_host_) { |
487 // The pending cross-site navigation completed, so show the renderer. | 443 // The pending cross-site navigation completed, so show the renderer. |
488 // If it committed without sending network requests (e.g., data URLs), | |
489 // then we still need to swap out the old RFH first and run its unload | |
490 // handler, only if it hasn't happened yet. OK for that to happen in the | |
491 // background. | |
492 if (pending_render_frame_host_->HasPendingCrossSiteRequest() && | |
493 pending_render_frame_host_->render_view_host()->rvh_state() == | |
494 RenderViewHostImpl::STATE_DEFAULT) { | |
495 SwapOutOldPage(); | |
496 } | |
497 | |
498 CommitPending(); | 444 CommitPending(); |
499 cross_navigation_pending_ = false; | 445 cross_navigation_pending_ = false; |
500 } else if (render_frame_host == render_frame_host_) { | 446 } else if (render_frame_host == render_frame_host_) { |
501 // A navigation in the original page has taken place. Cancel the pending | 447 // A navigation in the original page has taken place. Cancel the pending |
502 // one. | 448 // one. |
503 CancelPending(); | 449 CancelPending(); |
504 cross_navigation_pending_ = false; | 450 cross_navigation_pending_ = false; |
505 } else { | 451 } else { |
506 // No one else should be sending us DidNavigate in this state. | 452 // No one else should be sending us DidNavigate in this state. |
507 DCHECK(false); | 453 DCHECK(false); |
(...skipping 26 matching lines...) Expand all Loading... |
534 } | 480 } |
535 | 481 |
536 // Now delete them. | 482 // Now delete them. |
537 while (!ids_to_remove.empty()) { | 483 while (!ids_to_remove.empty()) { |
538 delete proxy_hosts_[ids_to_remove.back()]; | 484 delete proxy_hosts_[ids_to_remove.back()]; |
539 proxy_hosts_.erase(ids_to_remove.back()); | 485 proxy_hosts_.erase(ids_to_remove.back()); |
540 ids_to_remove.pop_back(); | 486 ids_to_remove.pop_back(); |
541 } | 487 } |
542 } | 488 } |
543 | 489 |
544 void RenderFrameHostManager::SwapOutOldPage() { | 490 void RenderFrameHostManager::SwapOutOldPage( |
545 // Should only see this while we have a pending renderer or transfer. | 491 RenderFrameHostImpl* old_render_frame_host) { |
546 CHECK(cross_navigation_pending_ || pending_nav_params_.get()); | 492 // Should only see this while we have a pending renderer. |
| 493 CHECK(cross_navigation_pending_); |
547 | 494 |
548 // Tell the renderer to suppress any further modal dialogs so that we can swap | 495 // Tell the renderer to suppress any further modal dialogs so that we can swap |
549 // it out. This must be done before canceling any current dialog, in case | 496 // it out. This must be done before canceling any current dialog, in case |
550 // there is a loop creating additional dialogs. | 497 // there is a loop creating additional dialogs. |
551 // TODO(creis): Handle modal dialogs in subframe processes. | 498 // TODO(creis): Handle modal dialogs in subframe processes. |
552 render_frame_host_->render_view_host()->SuppressDialogsUntilSwapOut(); | 499 old_render_frame_host->render_view_host()->SuppressDialogsUntilSwapOut(); |
553 | 500 |
554 // Now close any modal dialogs that would prevent us from swapping out. This | 501 // Now close any modal dialogs that would prevent us from swapping out. This |
555 // must be done separately from SwapOut, so that the PageGroupLoadDeferrer is | 502 // must be done separately from SwapOut, so that the PageGroupLoadDeferrer is |
556 // no longer on the stack when we send the SwapOut message. | 503 // no longer on the stack when we send the SwapOut message. |
557 delegate_->CancelModalDialogsForRenderManager(); | 504 delegate_->CancelModalDialogsForRenderManager(); |
558 | 505 |
559 // Create the RenderFrameProxyHost that will replace the | 506 // Create the RenderFrameProxyHost that will replace the |
560 // RenderFrameHost which is swapping out. If one exists, ensure it is deleted | 507 // RenderFrameHost which is swapping out. If one exists, ensure it is deleted |
561 // from the map and not leaked. | 508 // from the map and not leaked. |
562 DeleteRenderFrameProxyHost(render_frame_host_->GetSiteInstance()); | 509 DeleteRenderFrameProxyHost(old_render_frame_host->GetSiteInstance()); |
563 | 510 |
564 RenderFrameProxyHost* proxy = new RenderFrameProxyHost( | 511 RenderFrameProxyHost* proxy = new RenderFrameProxyHost( |
565 render_frame_host_->GetSiteInstance(), frame_tree_node_); | 512 old_render_frame_host->GetSiteInstance(), frame_tree_node_); |
566 std::pair<RenderFrameProxyHostMap::iterator, bool> result = | 513 std::pair<RenderFrameProxyHostMap::iterator, bool> result = |
567 proxy_hosts_.insert(std::make_pair( | 514 proxy_hosts_.insert(std::make_pair( |
568 render_frame_host_->GetSiteInstance()->GetId(), proxy)); | 515 old_render_frame_host->GetSiteInstance()->GetId(), proxy)); |
569 CHECK(result.second) << "Inserting a duplicate item."; | 516 CHECK(result.second) << "Inserting a duplicate item."; |
570 | 517 |
571 // Tell the old frame it is being swapped out. This will fire the unload | 518 // Tell the old frame it is being swapped out. This will fire the unload |
572 // handler in the background (without firing the beforeunload handler a second | 519 // handler in the background (without firing the beforeunload handler a second |
573 // time). When the navigation completes, we will send a message to the | 520 // time). This is done right after we commit the new RenderFrameHost. |
574 // ResourceDispatcherHost, allowing the pending RVH's response to resume. | 521 old_render_frame_host->SwapOut(proxy); |
575 render_frame_host_->SwapOut(proxy); | |
576 | |
577 // ResourceDispatcherHost has told us to run the onunload handler, which | |
578 // means it is not a download or unsafe page, and we are going to perform the | |
579 // navigation. Thus, we no longer need to remember that the RenderFrameHost | |
580 // is part of a pending cross-site request. | |
581 if (pending_render_frame_host_) { | |
582 pending_render_frame_host_->SetHasPendingCrossSiteRequest(false); | |
583 } | |
584 } | 522 } |
585 | 523 |
586 void RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance( | 524 void RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance( |
587 int32 site_instance_id, | 525 int32 site_instance_id, |
588 RenderFrameHostImpl* rfh) { | 526 RenderFrameHostImpl* rfh) { |
589 RFHPendingDeleteMap::iterator iter = | 527 RFHPendingDeleteMap::iterator iter = |
590 pending_delete_hosts_.find(site_instance_id); | 528 pending_delete_hosts_.find(site_instance_id); |
591 if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh) | 529 if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh) |
592 pending_delete_hosts_.erase(site_instance_id); | 530 pending_delete_hosts_.erase(site_instance_id); |
593 } | 531 } |
(...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1273 return MSG_ROUTING_NONE; | 1211 return MSG_ROUTING_NONE; |
1274 } | 1212 } |
1275 | 1213 |
1276 void RenderFrameHostManager::CommitPending() { | 1214 void RenderFrameHostManager::CommitPending() { |
1277 // First check whether we're going to want to focus the location bar after | 1215 // First check whether we're going to want to focus the location bar after |
1278 // this commit. We do this now because the navigation hasn't formally | 1216 // this commit. We do this now because the navigation hasn't formally |
1279 // committed yet, so if we've already cleared |pending_web_ui_| the call chain | 1217 // committed yet, so if we've already cleared |pending_web_ui_| the call chain |
1280 // this triggers won't be able to figure out what's going on. | 1218 // this triggers won't be able to figure out what's going on. |
1281 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); | 1219 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); |
1282 | 1220 |
1283 // We expect SwapOutOldPage to have canceled any modal dialogs and told the | |
1284 // renderer to suppress any further dialogs until it is swapped out. However, | |
1285 // crash reports indicate that it's still possible for modal dialogs to exist | |
1286 // at this point, which poses a risk if we delete their RenderViewHost below. | |
1287 // Cancel them again to be safe. http://crbug.com/324320. | |
1288 delegate_->CancelModalDialogsForRenderManager(); | |
1289 | |
1290 // Next commit the Web UI, if any. Either replace |web_ui_| with | 1221 // Next commit the Web UI, if any. Either replace |web_ui_| with |
1291 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or | 1222 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or |
1292 // leave |web_ui_| as is if reusing it. | 1223 // leave |web_ui_| as is if reusing it. |
1293 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); | 1224 DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); |
1294 if (pending_web_ui_) { | 1225 if (pending_web_ui_) { |
1295 web_ui_.reset(pending_web_ui_.release()); | 1226 web_ui_.reset(pending_web_ui_.release()); |
1296 } else if (!pending_and_current_web_ui_.get()) { | 1227 } else if (!pending_and_current_web_ui_.get()) { |
1297 web_ui_.reset(); | 1228 web_ui_.reset(); |
1298 } else { | 1229 } else { |
1299 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); | 1230 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1332 // If the view is gone, then this RenderViewHost died while it was hidden. | 1263 // If the view is gone, then this RenderViewHost died while it was hidden. |
1333 // We ignored the RenderProcessGone call at the time, so we should send it now | 1264 // We ignored the RenderProcessGone call at the time, so we should send it now |
1334 // to make sure the sad tab shows up, etc. | 1265 // to make sure the sad tab shows up, etc. |
1335 if (!render_frame_host_->render_view_host()->GetView()) { | 1266 if (!render_frame_host_->render_view_host()->GetView()) { |
1336 delegate_->RenderProcessGoneFromRenderManager( | 1267 delegate_->RenderProcessGoneFromRenderManager( |
1337 render_frame_host_->render_view_host()); | 1268 render_frame_host_->render_view_host()); |
1338 } else if (!delegate_->IsHidden()) { | 1269 } else if (!delegate_->IsHidden()) { |
1339 render_frame_host_->render_view_host()->GetView()->Show(); | 1270 render_frame_host_->render_view_host()->GetView()->Show(); |
1340 } | 1271 } |
1341 | 1272 |
1342 // If the old view is live and top-level, hide it now that the new one is | 1273 // If the old frame is live, swap it out now that the new frame is visible. |
1343 // visible. | |
1344 int32 old_site_instance_id = | 1274 int32 old_site_instance_id = |
1345 old_render_frame_host->GetSiteInstance()->GetId(); | 1275 old_render_frame_host->GetSiteInstance()->GetId(); |
1346 if (old_render_frame_host->render_view_host()->GetView()) { | 1276 if (old_render_frame_host->render_view_host()->IsRenderViewLive()) { |
1347 if (is_main_frame) { | 1277 SwapOutOldPage(old_render_frame_host.get()); |
1348 old_render_frame_host->render_view_host()->GetView()->Hide(); | 1278 |
1349 old_render_frame_host->render_view_host()->WasSwappedOut(base::Bind( | 1279 // Schedule the old frame to shut down after it swaps out, if there are no |
| 1280 // other active views in its SiteInstance. |
| 1281 if (!static_cast<SiteInstanceImpl*>( |
| 1282 old_render_frame_host->GetSiteInstance())->active_view_count()) { |
| 1283 old_render_frame_host->render_view_host()->SetPendingShutdown(base::Bind( |
1350 &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance, | 1284 &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance, |
1351 weak_factory_.GetWeakPtr(), | 1285 weak_factory_.GetWeakPtr(), |
1352 old_site_instance_id, | 1286 old_site_instance_id, |
1353 old_render_frame_host.get())); | 1287 old_render_frame_host.get())); |
1354 } else { | |
1355 // TODO(creis): We'll need to set this back to false if we navigate back. | |
1356 old_render_frame_host->set_swapped_out(true); | |
1357 } | 1288 } |
1358 } | 1289 } |
1359 | 1290 |
| 1291 // For top-level frames, also hide the old RenderViewHost's view. |
| 1292 if (is_main_frame && old_render_frame_host->render_view_host()->GetView()) |
| 1293 old_render_frame_host->render_view_host()->GetView()->Hide(); |
| 1294 |
1360 // Make sure the size is up to date. (Fix for bug 1079768.) | 1295 // Make sure the size is up to date. (Fix for bug 1079768.) |
1361 delegate_->UpdateRenderViewSizeForRenderManager(); | 1296 delegate_->UpdateRenderViewSizeForRenderManager(); |
1362 | 1297 |
1363 if (will_focus_location_bar) { | 1298 if (will_focus_location_bar) { |
1364 delegate_->SetFocusToLocationBar(false); | 1299 delegate_->SetFocusToLocationBar(false); |
1365 } else if (focus_render_view && | 1300 } else if (focus_render_view && |
1366 render_frame_host_->render_view_host()->GetView()) { | 1301 render_frame_host_->render_view_host()->GetView()) { |
1367 render_frame_host_->render_view_host()->GetView()->Focus(); | 1302 render_frame_host_->render_view_host()->GetView()->Focus(); |
1368 } | 1303 } |
1369 | 1304 |
1370 // Notify that we've swapped RenderFrameHosts. We do this before shutting down | 1305 // Notify that we've swapped RenderFrameHosts. We do this before shutting down |
1371 // the RFH so that we can clean up RendererResources related to the RFH first. | 1306 // the RFH so that we can clean up RendererResources related to the RFH first. |
1372 delegate_->NotifySwappedFromRenderManager( | 1307 delegate_->NotifySwappedFromRenderManager( |
1373 old_render_frame_host.get(), render_frame_host_.get(), is_main_frame); | 1308 old_render_frame_host.get(), render_frame_host_.get(), is_main_frame); |
1374 | 1309 |
1375 // If the old RFH is not live, just return as there is no work to do. | 1310 // If the old RFH is not live, just return as there is no further work to do. |
1376 if (!old_render_frame_host->render_view_host()->IsRenderViewLive()) { | 1311 if (!old_render_frame_host->render_view_host()->IsRenderViewLive()) |
1377 return; | 1312 return; |
1378 } | |
1379 | 1313 |
1380 // If the old RFH is live, we are swapping it out and should keep track of | 1314 // If the old RFH is live, we are swapping it out and should keep track of |
1381 // it in case we navigate back to it, or it is waiting for the unload event | 1315 // it in case we navigate back to it, or it is waiting for the unload event |
1382 // to execute in the background. | 1316 // to execute in the background. |
1383 // TODO(creis): Swap out the subframe in --site-per-process. | 1317 // TODO(creis): Swap out the subframe in --site-per-process. |
1384 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) | 1318 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { |
1385 DCHECK(old_render_frame_host->is_swapped_out() || | 1319 DCHECK(old_render_frame_host->is_swapped_out() || |
1386 !RenderViewHostImpl::IsRVHStateActive( | 1320 !RenderViewHostImpl::IsRVHStateActive( |
1387 old_render_frame_host->render_view_host()->rvh_state())); | 1321 old_render_frame_host->render_view_host()->rvh_state())); |
| 1322 } |
1388 | 1323 |
1389 // If the RenderViewHost backing the RenderFrameHost is pending shutdown, | 1324 // If the RenderViewHost backing the RenderFrameHost is pending shutdown, |
1390 // the RenderFrameHost should be put in the map of RenderFrameHosts pending | 1325 // the RenderFrameHost should be put in the map of RenderFrameHosts pending |
1391 // shutdown. Otherwise, it is stored in the map of proxy hosts. | 1326 // shutdown. Otherwise, it is stored in the map of proxy hosts. |
1392 if (old_render_frame_host->render_view_host()->rvh_state() == | 1327 if (old_render_frame_host->render_view_host()->rvh_state() == |
1393 RenderViewHostImpl::STATE_PENDING_SHUTDOWN) { | 1328 RenderViewHostImpl::STATE_PENDING_SHUTDOWN) { |
1394 // The proxy for this RenderFrameHost is created when sending the | 1329 // The proxy for this RenderFrameHost is created when sending the |
1395 // SwapOut message, so check if it already exists and delete it. | 1330 // SwapOut message, so check if it already exists and delete it. |
1396 RenderFrameProxyHostMap::iterator iter = | 1331 RenderFrameProxyHostMap::iterator iter = |
1397 proxy_hosts_.find(old_site_instance_id); | 1332 proxy_hosts_.find(old_site_instance_id); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1534 // Suspend the new render view (i.e., don't let it send the cross-site | 1469 // Suspend the new render view (i.e., don't let it send the cross-site |
1535 // Navigate message) until we hear back from the old renderer's | 1470 // Navigate message) until we hear back from the old renderer's |
1536 // beforeunload handler. If the handler returns false, we'll have to | 1471 // beforeunload handler. If the handler returns false, we'll have to |
1537 // cancel the request. | 1472 // cancel the request. |
1538 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); | 1473 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); |
1539 bool is_transfer = | 1474 bool is_transfer = |
1540 entry.transferred_global_request_id() != GlobalRequestID(); | 1475 entry.transferred_global_request_id() != GlobalRequestID(); |
1541 if (is_transfer) { | 1476 if (is_transfer) { |
1542 // We don't need to stop the old renderer or run beforeunload/unload | 1477 // We don't need to stop the old renderer or run beforeunload/unload |
1543 // handlers, because those have already been done. | 1478 // handlers, because those have already been done. |
1544 DCHECK(pending_nav_params_->global_request_id == | 1479 DCHECK(cross_site_transferring_request_->request_id() == |
1545 entry.transferred_global_request_id()); | 1480 entry.transferred_global_request_id()); |
1546 } else { | 1481 } else { |
1547 // Also make sure the old render view stops, in case a load is in | 1482 // Also make sure the old render view stops, in case a load is in |
1548 // progress. (We don't want to do this for transfers, since it will | 1483 // progress. (We don't want to do this for transfers, since it will |
1549 // interrupt the transfer with an unexpected DidStopLoading.) | 1484 // interrupt the transfer with an unexpected DidStopLoading.) |
1550 render_frame_host_->render_view_host()->Send(new ViewMsg_Stop( | 1485 render_frame_host_->render_view_host()->Send(new ViewMsg_Stop( |
1551 render_frame_host_->render_view_host()->GetRoutingID())); | 1486 render_frame_host_->render_view_host()->GetRoutingID())); |
1552 | 1487 |
1553 pending_render_frame_host_->SetNavigationsSuspended(true, | 1488 pending_render_frame_host_->SetNavigationsSuspended(true, |
1554 base::TimeTicks()); | 1489 base::TimeTicks()); |
1555 | |
1556 // Tell the CrossSiteRequestManager that this RFH has a pending cross-site | |
1557 // request, so that ResourceDispatcherHost will know to tell us to run the | |
1558 // old page's unload handler before it sends the response. | |
1559 pending_render_frame_host_->SetHasPendingCrossSiteRequest(true); | |
1560 } | 1490 } |
1561 | 1491 |
1562 // We now have a pending RFH. | 1492 // We now have a pending RFH. |
1563 DCHECK(!cross_navigation_pending_); | 1493 DCHECK(!cross_navigation_pending_); |
1564 cross_navigation_pending_ = true; | 1494 cross_navigation_pending_ = true; |
1565 | 1495 |
1566 // Unless we are transferring an existing request, we should now | 1496 // Unless we are transferring an existing request, we should now |
1567 // tell the old render view to run its beforeunload handler, since it | 1497 // tell the old render view to run its beforeunload handler, since it |
1568 // doesn't otherwise know that the cross-site request is happening. This | 1498 // doesn't otherwise know that the cross-site request is happening. This |
1569 // will trigger a call to OnBeforeUnloadACK with the reply. | 1499 // will trigger a call to OnBeforeUnloadACK with the reply. |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1720 void RenderFrameHostManager::DeleteRenderFrameProxyHost( | 1650 void RenderFrameHostManager::DeleteRenderFrameProxyHost( |
1721 SiteInstance* instance) { | 1651 SiteInstance* instance) { |
1722 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId()); | 1652 RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId()); |
1723 if (iter != proxy_hosts_.end()) { | 1653 if (iter != proxy_hosts_.end()) { |
1724 delete iter->second; | 1654 delete iter->second; |
1725 proxy_hosts_.erase(iter); | 1655 proxy_hosts_.erase(iter); |
1726 } | 1656 } |
1727 } | 1657 } |
1728 | 1658 |
1729 } // namespace content | 1659 } // namespace content |
OLD | NEW |