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