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

Side by Side Diff: content/browser/frame_host/render_frame_host_manager.cc

Issue 464593003: Don't swap out the old RenderFrameHost until the new one commits. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase past PlzNavigate CL Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698