Chromium Code Reviews| 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 |