| 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 15 matching lines...) Expand all Loading... |
| 26 #include "content/public/browser/notification_types.h" | 26 #include "content/public/browser/notification_types.h" |
| 27 #include "content/public/browser/render_widget_host_iterator.h" | 27 #include "content/public/browser/render_widget_host_iterator.h" |
| 28 #include "content/public/browser/user_metrics.h" | 28 #include "content/public/browser/user_metrics.h" |
| 29 #include "content/public/browser/web_contents_view.h" | 29 #include "content/public/browser/web_contents_view.h" |
| 30 #include "content/public/browser/web_ui_controller.h" | 30 #include "content/public/browser/web_ui_controller.h" |
| 31 #include "content/public/common/content_switches.h" | 31 #include "content/public/common/content_switches.h" |
| 32 #include "content/public/common/url_constants.h" | 32 #include "content/public/common/url_constants.h" |
| 33 | 33 |
| 34 namespace content { | 34 namespace content { |
| 35 | 35 |
| 36 RenderViewHostManager::PendingNavigationParams::PendingNavigationParams() { | 36 RenderViewHostManager::PendingNavigationParams::PendingNavigationParams() |
| 37 : is_transfer(false), frame_id(-1) { |
| 37 } | 38 } |
| 38 | 39 |
| 39 RenderViewHostManager::PendingNavigationParams::PendingNavigationParams( | 40 RenderViewHostManager::PendingNavigationParams::PendingNavigationParams( |
| 40 const GlobalRequestID& global_request_id) | 41 const GlobalRequestID& global_request_id, |
| 41 : global_request_id(global_request_id) { | 42 bool is_transfer, |
| 43 const GURL& transfer_url, |
| 44 Referrer referrer, |
| 45 int64 frame_id) |
| 46 : global_request_id(global_request_id), |
| 47 is_transfer(is_transfer), |
| 48 transfer_url(transfer_url), |
| 49 referrer(referrer), |
| 50 frame_id(frame_id) { |
| 42 } | 51 } |
| 43 | 52 |
| 44 RenderViewHostManager::RenderViewHostManager( | 53 RenderViewHostManager::RenderViewHostManager( |
| 45 RenderViewHostDelegate* render_view_delegate, | 54 RenderViewHostDelegate* render_view_delegate, |
| 46 RenderWidgetHostDelegate* render_widget_delegate, | 55 RenderWidgetHostDelegate* render_widget_delegate, |
| 47 Delegate* delegate) | 56 Delegate* delegate) |
| 48 : delegate_(delegate), | 57 : delegate_(delegate), |
| 49 cross_navigation_pending_(false), | 58 cross_navigation_pending_(false), |
| 50 render_view_delegate_(render_view_delegate), | 59 render_view_delegate_(render_view_delegate), |
| 51 render_widget_delegate_(render_widget_delegate), | 60 render_widget_delegate_(render_widget_delegate), |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 void RenderViewHostManager::SwappedOut(RenderViewHost* render_view_host) { | 241 void RenderViewHostManager::SwappedOut(RenderViewHost* render_view_host) { |
| 233 // Make sure this is from our current RVH, and that we have a pending | 242 // Make sure this is from our current RVH, and that we have a pending |
| 234 // navigation from OnCrossSiteResponse. (There may be no pending navigation | 243 // navigation from OnCrossSiteResponse. (There may be no pending navigation |
| 235 // for data URLs that don't make network requests, for example.) If not, | 244 // for data URLs that don't make network requests, for example.) If not, |
| 236 // just return early and ignore. | 245 // just return early and ignore. |
| 237 if (render_view_host != render_view_host_ || !pending_nav_params_.get()) { | 246 if (render_view_host != render_view_host_ || !pending_nav_params_.get()) { |
| 238 pending_nav_params_.reset(); | 247 pending_nav_params_.reset(); |
| 239 return; | 248 return; |
| 240 } | 249 } |
| 241 | 250 |
| 242 // Now that the unload handler has run, we need to resume the paused response. | 251 // Now that the unload handler has run, we need to either initiate the |
| 243 if (pending_render_view_host_) { | 252 // pending transfer (if there is one) or resume the paused response (if not). |
| 253 // TODO(creis): The blank swapped out page is visible during this time, but |
| 254 // we can shorten this by delivering the response directly, rather than |
| 255 // forcing an identical request to be made. |
| 256 if (pending_nav_params_->is_transfer) { |
| 257 // We don't know whether the original request had |user_action| set to true. |
| 258 // However, since we force the navigation to be in the current tab, it |
| 259 // doesn't matter. |
| 260 render_view_host->GetDelegate()->RequestTransferURL( |
| 261 pending_nav_params_->transfer_url, |
| 262 pending_nav_params_->referrer, |
| 263 CURRENT_TAB, |
| 264 pending_nav_params_->frame_id, |
| 265 pending_nav_params_->global_request_id, |
| 266 false, |
| 267 true); |
| 268 } else if (pending_render_view_host_) { |
| 244 RenderProcessHostImpl* pending_process = | 269 RenderProcessHostImpl* pending_process = |
| 245 static_cast<RenderProcessHostImpl*>( | 270 static_cast<RenderProcessHostImpl*>( |
| 246 pending_render_view_host_->GetProcess()); | 271 pending_render_view_host_->GetProcess()); |
| 247 pending_process->ResumeDeferredNavigation( | 272 pending_process->ResumeDeferredNavigation( |
| 248 pending_nav_params_->global_request_id); | 273 pending_nav_params_->global_request_id); |
| 249 } | 274 } |
| 250 pending_nav_params_.reset(); | 275 pending_nav_params_.reset(); |
| 251 } | 276 } |
| 252 | 277 |
| 253 void RenderViewHostManager::DidNavigateMainFrame( | 278 void RenderViewHostManager::DidNavigateMainFrame( |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 | 388 |
| 364 if (proceed_to_fire_unload) { | 389 if (proceed_to_fire_unload) { |
| 365 // This is not a cross-site navigation, the tab is being closed. | 390 // This is not a cross-site navigation, the tab is being closed. |
| 366 render_view_host_->ClosePage(); | 391 render_view_host_->ClosePage(); |
| 367 } | 392 } |
| 368 } | 393 } |
| 369 } | 394 } |
| 370 | 395 |
| 371 void RenderViewHostManager::OnCrossSiteResponse( | 396 void RenderViewHostManager::OnCrossSiteResponse( |
| 372 RenderViewHost* pending_render_view_host, | 397 RenderViewHost* pending_render_view_host, |
| 373 const GlobalRequestID& global_request_id) { | 398 const GlobalRequestID& global_request_id, |
| 374 // This should be called when the pending RVH is ready to commit. | 399 bool is_transfer, |
| 375 DCHECK_EQ(pending_render_view_host_, pending_render_view_host); | 400 const GURL& transfer_url, |
| 401 const Referrer& referrer, |
| 402 int64 frame_id) { |
| 403 // This should be called either when the pending RVH is ready to commit or |
| 404 // when we realize that the current RVH's request requires a transfer. |
| 405 DCHECK( |
| 406 pending_render_view_host == pending_render_view_host_ || |
| 407 pending_render_view_host == render_view_host_); |
| 376 | 408 |
| 377 // Remember the request ID until the unload handler has run. | 409 // TODO(creis): Eventually we will want to check all navigation responses |
| 378 pending_nav_params_.reset(new PendingNavigationParams(global_request_id)); | 410 // here, but currently we pass information for a transfer if |
| 411 // ShouldSwapProcessesForRedirect returned true in the network stack. |
| 412 // In that case, we should set up a transfer after the unload handler runs. |
| 413 // If is_transfer is false, we will just run the unload handler and resume. |
| 414 pending_nav_params_.reset(new PendingNavigationParams( |
| 415 global_request_id, is_transfer, transfer_url, referrer, frame_id)); |
| 379 | 416 |
| 380 // Run the unload handler of the current page. | 417 // Run the unload handler of the current page. |
| 381 SwapOutOldPage(); | 418 SwapOutOldPage(); |
| 382 } | 419 } |
| 383 | 420 |
| 384 void RenderViewHostManager::SwapOutOldPage() { | 421 void RenderViewHostManager::SwapOutOldPage() { |
| 385 // Should only see this while we have a pending renderer. | 422 // Should only see this while we have a pending renderer or transfer. |
| 386 if (!cross_navigation_pending_) | 423 CHECK(cross_navigation_pending_ || pending_nav_params_.get()); |
| 387 return; | |
| 388 DCHECK(pending_render_view_host_); | |
| 389 | 424 |
| 390 // Tell the old renderer it is being swapped out. This will fire the unload | 425 // Tell the old renderer it is being swapped out. This will fire the unload |
| 391 // handler (without firing the beforeunload handler a second time). When the | 426 // handler (without firing the beforeunload handler a second time). When the |
| 392 // unload handler finishes and the navigation completes, we will send a | 427 // unload handler finishes and the navigation completes, we will send a |
| 393 // message to the ResourceDispatcherHost, allowing the pending RVH's response | 428 // message to the ResourceDispatcherHost, allowing the pending RVH's response |
| 394 // to resume. | 429 // to resume. |
| 395 render_view_host_->SwapOut(); | 430 render_view_host_->SwapOut(); |
| 396 | 431 |
| 397 // ResourceDispatcherHost has told us to run the onunload handler, which | 432 // ResourceDispatcherHost has told us to run the onunload handler, which |
| 398 // means it is not a download or unsafe page, and we are going to perform the | 433 // means it is not a download or unsafe page, and we are going to perform the |
| 399 // navigation. Thus, we no longer need to remember that the RenderViewHost | 434 // navigation. Thus, we no longer need to remember that the RenderViewHost |
| 400 // is part of a pending cross-site request. | 435 // is part of a pending cross-site request. |
| 401 pending_render_view_host_->SetHasPendingCrossSiteRequest(false); | 436 if (pending_render_view_host_) |
| 437 pending_render_view_host_->SetHasPendingCrossSiteRequest(false); |
| 402 } | 438 } |
| 403 | 439 |
| 404 void RenderViewHostManager::Observe( | 440 void RenderViewHostManager::Observe( |
| 405 int type, | 441 int type, |
| 406 const NotificationSource& source, | 442 const NotificationSource& source, |
| 407 const NotificationDetails& details) { | 443 const NotificationDetails& details) { |
| 408 switch (type) { | 444 switch (type) { |
| 409 case NOTIFICATION_RENDERER_PROCESS_CLOSED: | 445 case NOTIFICATION_RENDERER_PROCESS_CLOSED: |
| 410 case NOTIFICATION_RENDERER_PROCESS_CLOSING: | 446 case NOTIFICATION_RENDERER_PROCESS_CLOSING: |
| 411 RendererProcessClosing( | 447 RendererProcessClosing( |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 | 945 |
| 910 // We need to wait until the beforeunload handler has run, unless we are | 946 // We need to wait until the beforeunload handler has run, unless we are |
| 911 // transferring an existing request (in which case it has already run). | 947 // transferring an existing request (in which case it has already run). |
| 912 // Suspend the new render view (i.e., don't let it send the cross-site | 948 // Suspend the new render view (i.e., don't let it send the cross-site |
| 913 // Navigate message) until we hear back from the old renderer's | 949 // Navigate message) until we hear back from the old renderer's |
| 914 // beforeunload handler. If the handler returns false, we'll have to | 950 // beforeunload handler. If the handler returns false, we'll have to |
| 915 // cancel the request. | 951 // cancel the request. |
| 916 DCHECK(!pending_render_view_host_->are_navigations_suspended()); | 952 DCHECK(!pending_render_view_host_->are_navigations_suspended()); |
| 917 bool is_transfer = | 953 bool is_transfer = |
| 918 entry.transferred_global_request_id() != GlobalRequestID(); | 954 entry.transferred_global_request_id() != GlobalRequestID(); |
| 919 if (!is_transfer) { | 955 if (is_transfer) { |
| 956 // We don't need to stop the old renderer or run beforeunload/unload |
| 957 // handlers, because those have already been done. |
| 958 DCHECK(pending_nav_params_->global_request_id == |
| 959 entry.transferred_global_request_id()); |
| 960 } else { |
| 920 // Also make sure the old render view stops, in case a load is in | 961 // Also make sure the old render view stops, in case a load is in |
| 921 // progress. (We don't want to do this for transfers, since it will | 962 // progress. (We don't want to do this for transfers, since it will |
| 922 // interrupt the transfer with an unexpected DidStopLoading.) | 963 // interrupt the transfer with an unexpected DidStopLoading.) |
| 923 render_view_host_->Send( | 964 render_view_host_->Send( |
| 924 new ViewMsg_Stop(render_view_host_->GetRoutingID())); | 965 new ViewMsg_Stop(render_view_host_->GetRoutingID())); |
| 925 | 966 |
| 926 pending_render_view_host_->SetNavigationsSuspended(true, | 967 pending_render_view_host_->SetNavigationsSuspended(true, |
| 927 base::TimeTicks()); | 968 base::TimeTicks()); |
| 969 |
| 970 // Tell the CrossSiteRequestManager that this RVH has a pending cross-site |
| 971 // request, so that ResourceDispatcherHost will know to tell us to run the |
| 972 // old page's unload handler before it sends the response. |
| 973 pending_render_view_host_->SetHasPendingCrossSiteRequest(true); |
| 928 } | 974 } |
| 929 | 975 |
| 930 // Tell the CrossSiteRequestManager that this RVH has a pending cross-site | |
| 931 // request, so that ResourceDispatcherHost will know to tell us to run the | |
| 932 // old page's unload handler before it sends the response. | |
| 933 pending_render_view_host_->SetHasPendingCrossSiteRequest(true); | |
| 934 | |
| 935 // We now have a pending RVH. | 976 // We now have a pending RVH. |
| 936 DCHECK(!cross_navigation_pending_); | 977 DCHECK(!cross_navigation_pending_); |
| 937 cross_navigation_pending_ = true; | 978 cross_navigation_pending_ = true; |
| 938 | 979 |
| 939 // Unless we are transferring an existing request, we should now | 980 // Unless we are transferring an existing request, we should now |
| 940 // tell the old render view to run its beforeunload handler, since it | 981 // tell the old render view to run its beforeunload handler, since it |
| 941 // doesn't otherwise know that the cross-site request is happening. This | 982 // doesn't otherwise know that the cross-site request is happening. This |
| 942 // will trigger a call to ShouldClosePage with the reply. | 983 // will trigger a call to ShouldClosePage with the reply. |
| 943 if (!is_transfer) | 984 if (!is_transfer) |
| 944 render_view_host_->FirePageBeforeUnload(true); | 985 render_view_host_->FirePageBeforeUnload(true); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1045 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost( | 1086 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost( |
| 1046 SiteInstance* instance) { | 1087 SiteInstance* instance) { |
| 1047 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); | 1088 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); |
| 1048 if (iter != swapped_out_hosts_.end()) | 1089 if (iter != swapped_out_hosts_.end()) |
| 1049 return iter->second; | 1090 return iter->second; |
| 1050 | 1091 |
| 1051 return NULL; | 1092 return NULL; |
| 1052 } | 1093 } |
| 1053 | 1094 |
| 1054 } // namespace content | 1095 } // namespace content |
| OLD | NEW |