| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/web_contents/render_view_host_manager.h" | 5 #include "content/browser/web_contents/render_view_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 14 matching lines...) Expand all Loading... |
| 25 #include "content/public/browser/notification_service.h" | 25 #include "content/public/browser/notification_service.h" |
| 26 #include "content/public/browser/notification_types.h" | 26 #include "content/public/browser/notification_types.h" |
| 27 #include "content/public/browser/user_metrics.h" | 27 #include "content/public/browser/user_metrics.h" |
| 28 #include "content/public/browser/web_contents_view.h" | 28 #include "content/public/browser/web_contents_view.h" |
| 29 #include "content/public/browser/web_ui_controller.h" | 29 #include "content/public/browser/web_ui_controller.h" |
| 30 #include "content/public/common/content_switches.h" | 30 #include "content/public/common/content_switches.h" |
| 31 #include "content/public/common/url_constants.h" | 31 #include "content/public/common/url_constants.h" |
| 32 | 32 |
| 33 namespace content { | 33 namespace content { |
| 34 | 34 |
| 35 RenderViewHostManager::PendingNavigationParams::PendingNavigationParams() { | 35 RenderViewHostManager::PendingNavigationParams::PendingNavigationParams() |
| 36 : is_transfer(false), frame_id(-1) { |
| 36 } | 37 } |
| 37 | 38 |
| 38 RenderViewHostManager::PendingNavigationParams::PendingNavigationParams( | 39 RenderViewHostManager::PendingNavigationParams::PendingNavigationParams( |
| 39 const GlobalRequestID& global_request_id) | 40 const GlobalRequestID& global_request_id, |
| 40 : global_request_id(global_request_id) { | 41 bool is_transfer, |
| 42 const GURL& transfer_url, |
| 43 Referrer referrer, |
| 44 int64 frame_id) |
| 45 : global_request_id(global_request_id), |
| 46 is_transfer(is_transfer), |
| 47 transfer_url(transfer_url), |
| 48 referrer(referrer), |
| 49 frame_id(frame_id) { |
| 41 } | 50 } |
| 42 | 51 |
| 43 RenderViewHostManager::RenderViewHostManager( | 52 RenderViewHostManager::RenderViewHostManager( |
| 44 RenderViewHostDelegate* render_view_delegate, | 53 RenderViewHostDelegate* render_view_delegate, |
| 45 RenderWidgetHostDelegate* render_widget_delegate, | 54 RenderWidgetHostDelegate* render_widget_delegate, |
| 46 Delegate* delegate) | 55 Delegate* delegate) |
| 47 : delegate_(delegate), | 56 : delegate_(delegate), |
| 48 cross_navigation_pending_(false), | 57 cross_navigation_pending_(false), |
| 49 render_view_delegate_(render_view_delegate), | 58 render_view_delegate_(render_view_delegate), |
| 50 render_widget_delegate_(render_widget_delegate), | 59 render_widget_delegate_(render_widget_delegate), |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 void RenderViewHostManager::SwappedOut(RenderViewHost* render_view_host) { | 232 void RenderViewHostManager::SwappedOut(RenderViewHost* render_view_host) { |
| 224 // Make sure this is from our current RVH, and that we have a pending | 233 // Make sure this is from our current RVH, and that we have a pending |
| 225 // navigation from OnCrossSiteResponse. (There may be no pending navigation | 234 // navigation from OnCrossSiteResponse. (There may be no pending navigation |
| 226 // for data URLs that don't make network requests, for example.) If not, | 235 // for data URLs that don't make network requests, for example.) If not, |
| 227 // just return early and ignore. | 236 // just return early and ignore. |
| 228 if (render_view_host != render_view_host_ || !pending_nav_params_.get()) { | 237 if (render_view_host != render_view_host_ || !pending_nav_params_.get()) { |
| 229 pending_nav_params_.reset(); | 238 pending_nav_params_.reset(); |
| 230 return; | 239 return; |
| 231 } | 240 } |
| 232 | 241 |
| 233 // Now that the unload handler has run, we need to resume the paused response. | 242 // Now that the unload handler has run, we need to either initiate the |
| 234 if (pending_render_view_host_) { | 243 // pending transfer (if there is one) or resume the paused response (if not). |
| 244 // TODO(creis): The blank swapped out page is visible during this time, but |
| 245 // we can shorten this by delivering the response directly, rather than |
| 246 // forcing an identical request to be made. |
| 247 if (!pending_nav_params_->is_transfer) { |
| 248 render_view_host->GetDelegate()->RequestTransferURL( |
| 249 pending_nav_params_->transfer_url, |
| 250 pending_nav_params_->referrer, |
| 251 CURRENT_TAB, |
| 252 pending_nav_params_->frame_id, |
| 253 pending_nav_params_->global_request_id, |
| 254 false); |
| 255 } else if (pending_render_view_host_) { |
| 235 RenderProcessHostImpl* pending_process = | 256 RenderProcessHostImpl* pending_process = |
| 236 static_cast<RenderProcessHostImpl*>( | 257 static_cast<RenderProcessHostImpl*>( |
| 237 pending_render_view_host_->GetProcess()); | 258 pending_render_view_host_->GetProcess()); |
| 238 pending_process->ResumeDeferredNavigation( | 259 pending_process->ResumeDeferredNavigation( |
| 239 pending_nav_params_->global_request_id); | 260 pending_nav_params_->global_request_id); |
| 240 } | 261 } |
| 241 pending_nav_params_.reset(); | 262 pending_nav_params_.reset(); |
| 242 } | 263 } |
| 243 | 264 |
| 244 void RenderViewHostManager::DidNavigateMainFrame( | 265 void RenderViewHostManager::DidNavigateMainFrame( |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 | 375 |
| 355 if (proceed_to_fire_unload) { | 376 if (proceed_to_fire_unload) { |
| 356 // This is not a cross-site navigation, the tab is being closed. | 377 // This is not a cross-site navigation, the tab is being closed. |
| 357 render_view_host_->ClosePage(); | 378 render_view_host_->ClosePage(); |
| 358 } | 379 } |
| 359 } | 380 } |
| 360 } | 381 } |
| 361 | 382 |
| 362 void RenderViewHostManager::OnCrossSiteResponse( | 383 void RenderViewHostManager::OnCrossSiteResponse( |
| 363 RenderViewHost* pending_render_view_host, | 384 RenderViewHost* pending_render_view_host, |
| 364 const GlobalRequestID& global_request_id) { | 385 const GlobalRequestID& global_request_id, |
| 365 // This should be called when the pending RVH is ready to commit. | 386 bool is_transfer, |
| 366 DCHECK_EQ(pending_render_view_host_, pending_render_view_host); | 387 const GURL& transfer_url, |
| 388 const Referrer& referrer, |
| 389 int64 frame_id) { |
| 390 // This should be called either when the pending RVH is ready to commit or |
| 391 // when we realize that the current RVH's request requires a transfer. |
| 392 DCHECK( |
| 393 pending_render_view_host == pending_render_view_host_ || |
| 394 pending_render_view_host == render_view_host_); |
| 367 | 395 |
| 368 // Remember the request ID until the unload handler has run. | 396 // TODO(creis): Eventually we will want to check all navigation responses |
| 369 pending_nav_params_.reset(new PendingNavigationParams(global_request_id)); | 397 // here, but currently we pass information for a transfer if |
| 398 // ShouldSwapProcessesForRedirect returned true in the network stack. |
| 399 // In that case, we should set up a transfer after the unload handler runs. |
| 400 // If is_transfer is false, we will just run the unload handler and resume. |
| 401 pending_nav_params_.reset(new PendingNavigationParams( |
| 402 global_request_id, is_transfer, transfer_url, referrer, frame_id)); |
| 370 | 403 |
| 371 // Run the unload handler of the current page. | 404 // Run the unload handler of the current page. |
| 372 SwapOutOldPage(); | 405 SwapOutOldPage(); |
| 373 } | 406 } |
| 374 | 407 |
| 375 void RenderViewHostManager::SwapOutOldPage() { | 408 void RenderViewHostManager::SwapOutOldPage() { |
| 376 // Should only see this while we have a pending renderer. | 409 // Should only see this while we have a pending renderer or transfer. |
| 377 if (!cross_navigation_pending_) | 410 CHECK(cross_navigation_pending_ || pending_nav_params_.get()); |
| 378 return; | |
| 379 DCHECK(pending_render_view_host_); | |
| 380 | 411 |
| 381 // Tell the old renderer it is being swapped out. This will fire the unload | 412 // Tell the old renderer it is being swapped out. This will fire the unload |
| 382 // handler (without firing the beforeunload handler a second time). When the | 413 // handler (without firing the beforeunload handler a second time). When the |
| 383 // unload handler finishes and the navigation completes, we will send a | 414 // unload handler finishes and the navigation completes, we will send a |
| 384 // message to the ResourceDispatcherHost, allowing the pending RVH's response | 415 // message to the ResourceDispatcherHost, allowing the pending RVH's response |
| 385 // to resume. | 416 // to resume. |
| 386 render_view_host_->SwapOut(); | 417 render_view_host_->SwapOut(); |
| 387 | 418 |
| 388 // ResourceDispatcherHost has told us to run the onunload handler, which | 419 // ResourceDispatcherHost has told us to run the onunload handler, which |
| 389 // means it is not a download or unsafe page, and we are going to perform the | 420 // means it is not a download or unsafe page, and we are going to perform the |
| 390 // navigation. Thus, we no longer need to remember that the RenderViewHost | 421 // navigation. Thus, we no longer need to remember that the RenderViewHost |
| 391 // is part of a pending cross-site request. | 422 // is part of a pending cross-site request. |
| 392 pending_render_view_host_->SetHasPendingCrossSiteRequest(false); | 423 if (pending_render_view_host_) |
| 424 pending_render_view_host_->SetHasPendingCrossSiteRequest(false); |
| 393 } | 425 } |
| 394 | 426 |
| 395 void RenderViewHostManager::Observe( | 427 void RenderViewHostManager::Observe( |
| 396 int type, | 428 int type, |
| 397 const NotificationSource& source, | 429 const NotificationSource& source, |
| 398 const NotificationDetails& details) { | 430 const NotificationDetails& details) { |
| 399 switch (type) { | 431 switch (type) { |
| 400 case NOTIFICATION_RENDERER_PROCESS_CLOSING: | 432 case NOTIFICATION_RENDERER_PROCESS_CLOSING: |
| 401 RendererProcessClosing( | 433 RendererProcessClosing( |
| 402 Source<RenderProcessHost>(source).ptr()); | 434 Source<RenderProcessHost>(source).ptr()); |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 | 898 |
| 867 // We need to wait until the beforeunload handler has run, unless we are | 899 // We need to wait until the beforeunload handler has run, unless we are |
| 868 // transferring an existing request (in which case it has already run). | 900 // transferring an existing request (in which case it has already run). |
| 869 // Suspend the new render view (i.e., don't let it send the cross-site | 901 // Suspend the new render view (i.e., don't let it send the cross-site |
| 870 // Navigate message) until we hear back from the old renderer's | 902 // Navigate message) until we hear back from the old renderer's |
| 871 // beforeunload handler. If the handler returns false, we'll have to | 903 // beforeunload handler. If the handler returns false, we'll have to |
| 872 // cancel the request. | 904 // cancel the request. |
| 873 DCHECK(!pending_render_view_host_->are_navigations_suspended()); | 905 DCHECK(!pending_render_view_host_->are_navigations_suspended()); |
| 874 bool is_transfer = | 906 bool is_transfer = |
| 875 entry.transferred_global_request_id() != GlobalRequestID(); | 907 entry.transferred_global_request_id() != GlobalRequestID(); |
| 876 if (!is_transfer) { | 908 if (is_transfer) { |
| 909 // We don't need to stop the old renderer or run beforeunload/unload |
| 910 // handlers, because those have already been done. |
| 911 DCHECK(pending_nav_params_->global_request_id == |
| 912 entry.transferred_global_request_id()); |
| 913 } else { |
| 877 // Also make sure the old render view stops, in case a load is in | 914 // Also make sure the old render view stops, in case a load is in |
| 878 // progress. (We don't want to do this for transfers, since it will | 915 // progress. (We don't want to do this for transfers, since it will |
| 879 // interrupt the transfer with an unexpected DidStopLoading.) | 916 // interrupt the transfer with an unexpected DidStopLoading.) |
| 880 render_view_host_->Send( | 917 render_view_host_->Send( |
| 881 new ViewMsg_Stop(render_view_host_->GetRoutingID())); | 918 new ViewMsg_Stop(render_view_host_->GetRoutingID())); |
| 882 | 919 |
| 883 pending_render_view_host_->SetNavigationsSuspended(true, | 920 pending_render_view_host_->SetNavigationsSuspended(true, |
| 884 base::TimeTicks()); | 921 base::TimeTicks()); |
| 922 |
| 923 // Tell the CrossSiteRequestManager that this RVH has a pending cross-site |
| 924 // request, so that ResourceDispatcherHost will know to tell us to run the |
| 925 // old page's unload handler before it sends the response. |
| 926 pending_render_view_host_->SetHasPendingCrossSiteRequest(true); |
| 885 } | 927 } |
| 886 | 928 |
| 887 // Tell the CrossSiteRequestManager that this RVH has a pending cross-site | |
| 888 // request, so that ResourceDispatcherHost will know to tell us to run the | |
| 889 // old page's unload handler before it sends the response. | |
| 890 pending_render_view_host_->SetHasPendingCrossSiteRequest(true); | |
| 891 | |
| 892 // We now have a pending RVH. | 929 // We now have a pending RVH. |
| 893 DCHECK(!cross_navigation_pending_); | 930 DCHECK(!cross_navigation_pending_); |
| 894 cross_navigation_pending_ = true; | 931 cross_navigation_pending_ = true; |
| 895 | 932 |
| 896 // Unless we are transferring an existing request, we should now | 933 // Unless we are transferring an existing request, we should now |
| 897 // tell the old render view to run its beforeunload handler, since it | 934 // tell the old render view to run its beforeunload handler, since it |
| 898 // doesn't otherwise know that the cross-site request is happening. This | 935 // doesn't otherwise know that the cross-site request is happening. This |
| 899 // will trigger a call to ShouldClosePage with the reply. | 936 // will trigger a call to ShouldClosePage with the reply. |
| 900 if (!is_transfer) | 937 if (!is_transfer) |
| 901 render_view_host_->FirePageBeforeUnload(true); | 938 render_view_host_->FirePageBeforeUnload(true); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost( | 1039 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost( |
| 1003 SiteInstance* instance) { | 1040 SiteInstance* instance) { |
| 1004 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); | 1041 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); |
| 1005 if (iter != swapped_out_hosts_.end()) | 1042 if (iter != swapped_out_hosts_.end()) |
| 1006 return iter->second; | 1043 return iter->second; |
| 1007 | 1044 |
| 1008 return NULL; | 1045 return NULL; |
| 1009 } | 1046 } |
| 1010 | 1047 |
| 1011 } // namespace content | 1048 } // namespace content |
| OLD | NEW |