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

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: Major rebase 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 24 matching lines...) Expand all
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698