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

Side by Side Diff: content/browser/web_contents/render_view_host_manager.cc

Issue 15682009: Eliminate SwapOut message parameters, keeping state in RVHM instead. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase to get Android build fix Created 7 years, 6 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 (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
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() {
36 }
37
38 RenderViewHostManager::PendingNavigationParams::PendingNavigationParams(
39 const GlobalRequestID& global_request_id)
40 : global_request_id(global_request_id) {
41 }
42
35 RenderViewHostManager::RenderViewHostManager( 43 RenderViewHostManager::RenderViewHostManager(
36 RenderViewHostDelegate* render_view_delegate, 44 RenderViewHostDelegate* render_view_delegate,
37 RenderWidgetHostDelegate* render_widget_delegate, 45 RenderWidgetHostDelegate* render_widget_delegate,
38 Delegate* delegate) 46 Delegate* delegate)
39 : delegate_(delegate), 47 : delegate_(delegate),
40 cross_navigation_pending_(false), 48 cross_navigation_pending_(false),
41 render_view_delegate_(render_view_delegate), 49 render_view_delegate_(render_view_delegate),
42 render_widget_delegate_(render_widget_delegate), 50 render_widget_delegate_(render_widget_delegate),
43 render_view_host_(NULL), 51 render_view_host_(NULL),
44 pending_render_view_host_(NULL), 52 pending_render_view_host_(NULL),
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 void RenderViewHostManager::SetIsLoading(bool is_loading) { 189 void RenderViewHostManager::SetIsLoading(bool is_loading) {
182 render_view_host_->SetIsLoading(is_loading); 190 render_view_host_->SetIsLoading(is_loading);
183 if (pending_render_view_host_) 191 if (pending_render_view_host_)
184 pending_render_view_host_->SetIsLoading(is_loading); 192 pending_render_view_host_->SetIsLoading(is_loading);
185 } 193 }
186 194
187 bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() { 195 bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() {
188 if (!cross_navigation_pending_) 196 if (!cross_navigation_pending_)
189 return true; 197 return true;
190 198
191 // If the tab becomes unresponsive during unload while doing a 199 // If the tab becomes unresponsive during {before}unload while doing a
192 // cross-site navigation, proceed with the navigation. (This assumes that 200 // cross-site navigation, proceed with the navigation. (This assumes that
193 // the pending RenderViewHost is still responsive.) 201 // the pending RenderViewHost is still responsive.)
194 int pending_request_id = pending_render_view_host_->GetPendingRequestId(); 202 if (render_view_host_->is_waiting_for_unload_ack()) {
195 if (pending_request_id == -1) { 203 // The request has been started and paused while we're waiting for the
204 // unload handler to finish. We'll pretend that it did. The pending
205 // renderer will then be swapped in as part of the usual DidNavigate logic.
206 // (If the unload handler later finishes, this call will be ignored because
207 // the pending_nav_params_ state will already be cleaned up.)
208 current_host()->OnSwappedOut(true);
209 } else if (render_view_host_->is_waiting_for_beforeunload_ack()) {
196 // Haven't gotten around to starting the request, because we're still 210 // Haven't gotten around to starting the request, because we're still
197 // waiting for the beforeunload handler to finish. We'll pretend that it 211 // waiting for the beforeunload handler to finish. We'll pretend that it
198 // did finish, to let the navigation proceed. Note that there's a danger 212 // did finish, to let the navigation proceed. Note that there's a danger
199 // that the beforeunload handler will later finish and possibly return 213 // that the beforeunload handler will later finish and possibly return
200 // false (meaning the navigation should not proceed), but we'll ignore it 214 // false (meaning the navigation should not proceed), but we'll ignore it
201 // in this case because it took too long. 215 // in this case because it took too long.
202 if (pending_render_view_host_->are_navigations_suspended()) 216 if (pending_render_view_host_->are_navigations_suspended())
203 pending_render_view_host_->SetNavigationsSuspended( 217 pending_render_view_host_->SetNavigationsSuspended(
204 false, base::TimeTicks::Now()); 218 false, base::TimeTicks::Now());
205 } else {
206 // The request has been started and paused while we're waiting for the
207 // unload handler to finish. We'll pretend that it did, by notifying the
208 // IO thread to let the response continue. The pending renderer will then
209 // be swapped in as part of the usual DidNavigate logic. (If the unload
210 // handler later finishes, this call will be ignored because the state in
211 // CrossSiteResourceHandler will already be cleaned up.)
212 ViewMsg_SwapOut_Params params;
213 params.closing_process_id = render_view_host_->GetProcess()->GetID();
214 params.closing_route_id = render_view_host_->GetRoutingID();
215 params.new_render_process_host_id =
216 pending_render_view_host_->GetProcess()->GetID();
217 params.new_request_id = pending_request_id;
218 current_host()->GetProcess()->SimulateSwapOutACK(params);
219 } 219 }
220 return false; 220 return false;
221 } 221 }
222 222
223 void RenderViewHostManager::SwappedOut(RenderViewHost* render_view_host) {
224 // Make sure this is from our current RVH, and that we have a pending
225 // navigation from OnCrossSiteResponse. (There may be no pending navigation
226 // for data URLs that don't make network requests, for example.) If not,
227 // just return early and ignore.
228 if (render_view_host != render_view_host_ || !pending_nav_params_.get()) {
229 pending_nav_params_.reset();
230 return;
231 }
232
233 // Now that the unload handler has run, we need to resume the paused response.
234 if (pending_render_view_host_) {
235 RenderProcessHostImpl* pending_process =
236 static_cast<RenderProcessHostImpl*>(
237 pending_render_view_host_->GetProcess());
238 pending_process->ResumeDeferredNavigation(
239 pending_nav_params_->global_request_id);
240 }
241 pending_nav_params_.reset();
242 }
243
223 void RenderViewHostManager::DidNavigateMainFrame( 244 void RenderViewHostManager::DidNavigateMainFrame(
224 RenderViewHost* render_view_host) { 245 RenderViewHost* render_view_host) {
225 if (!cross_navigation_pending_) { 246 if (!cross_navigation_pending_) {
226 DCHECK(!pending_render_view_host_); 247 DCHECK(!pending_render_view_host_);
227 248
228 // We should only hear this from our current renderer. 249 // We should only hear this from our current renderer.
229 DCHECK(render_view_host == render_view_host_); 250 DCHECK(render_view_host == render_view_host_);
230 251
231 // Even when there is no pending RVH, there may be a pending Web UI. 252 // Even when there is no pending RVH, there may be a pending Web UI.
232 if (pending_web_ui()) 253 if (pending_web_ui())
233 CommitPending(); 254 CommitPending();
234 return; 255 return;
235 } 256 }
236 257
237 if (render_view_host == pending_render_view_host_) { 258 if (render_view_host == pending_render_view_host_) {
238 // The pending cross-site navigation completed, so show the renderer. 259 // The pending cross-site navigation completed, so show the renderer.
239 // If it committed without sending network requests (e.g., data URLs), 260 // If it committed without sending network requests (e.g., data URLs),
240 // then we still need to swap out the old RVH first and run its unload 261 // then we still need to swap out the old RVH first and run its unload
241 // handler. OK for that to happen in the background. 262 // handler. OK for that to happen in the background.
242 if (pending_render_view_host_->GetPendingRequestId() == -1) { 263 if (pending_render_view_host_->HasPendingCrossSiteRequest())
243 OnCrossSiteResponse(pending_render_view_host_->GetProcess()->GetID(), 264 SwapOutOldPage();
244 pending_render_view_host_->GetRoutingID());
245 }
246 265
247 CommitPending(); 266 CommitPending();
248 cross_navigation_pending_ = false; 267 cross_navigation_pending_ = false;
249 } else if (render_view_host == render_view_host_) { 268 } else if (render_view_host == render_view_host_) {
250 // A navigation in the original page has taken place. Cancel the pending 269 // A navigation in the original page has taken place. Cancel the pending
251 // one. 270 // one.
252 CancelPending(); 271 CancelPending();
253 cross_navigation_pending_ = false; 272 cross_navigation_pending_ = false;
254 } else { 273 } else {
255 // No one else should be sending us DidNavigate in this state. 274 // No one else should be sending us DidNavigate in this state.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 delegate_->BeforeUnloadFiredFromRenderManager(proceed, proceed_time, 352 delegate_->BeforeUnloadFiredFromRenderManager(proceed, proceed_time,
334 &proceed_to_fire_unload); 353 &proceed_to_fire_unload);
335 354
336 if (proceed_to_fire_unload) { 355 if (proceed_to_fire_unload) {
337 // This is not a cross-site navigation, the tab is being closed. 356 // This is not a cross-site navigation, the tab is being closed.
338 render_view_host_->ClosePage(); 357 render_view_host_->ClosePage();
339 } 358 }
340 } 359 }
341 } 360 }
342 361
343 void RenderViewHostManager::OnCrossSiteResponse(int new_render_process_host_id, 362 void RenderViewHostManager::OnCrossSiteResponse(
344 int new_request_id) { 363 RenderViewHost* pending_render_view_host,
364 const GlobalRequestID& global_request_id) {
365 // This should be called when the pending RVH is ready to commit.
366 DCHECK_EQ(pending_render_view_host_, pending_render_view_host);
367
368 // Remember the request ID until the unload handler has run.
369 pending_nav_params_.reset(new PendingNavigationParams(global_request_id));
370
371 // Run the unload handler of the current page.
372 SwapOutOldPage();
373 }
374
375 void RenderViewHostManager::SwapOutOldPage() {
345 // Should only see this while we have a pending renderer. 376 // Should only see this while we have a pending renderer.
346 if (!cross_navigation_pending_) 377 if (!cross_navigation_pending_)
347 return; 378 return;
348 DCHECK(pending_render_view_host_); 379 DCHECK(pending_render_view_host_);
349 380
350 // Tell the old renderer it is being swapped out. This will fire the unload 381 // Tell the old renderer it is being swapped out. This will fire the unload
351 // handler (without firing the beforeunload handler a second time). When the 382 // handler (without firing the beforeunload handler a second time). When the
352 // unload handler finishes and the navigation completes, we will send a 383 // unload handler finishes and the navigation completes, we will send a
353 // message to the ResourceDispatcherHost with the given pending request IDs, 384 // message to the ResourceDispatcherHost, allowing the pending RVH's response
354 // allowing the pending RVH's response to resume. 385 // to resume.
355 render_view_host_->SwapOut(new_render_process_host_id, new_request_id); 386 render_view_host_->SwapOut();
356 387
357 // ResourceDispatcherHost has told us to run the onunload handler, which 388 // ResourceDispatcherHost has told us to run the onunload handler, which
358 // means it is not a download or unsafe page, and we are going to perform the 389 // means it is not a download or unsafe page, and we are going to perform the
359 // navigation. Thus, we no longer need to remember that the RenderViewHost 390 // navigation. Thus, we no longer need to remember that the RenderViewHost
360 // is part of a pending cross-site request. 391 // is part of a pending cross-site request.
361 pending_render_view_host_->SetHasPendingCrossSiteRequest(false, 392 pending_render_view_host_->SetHasPendingCrossSiteRequest(false);
362 new_request_id);
363 } 393 }
364 394
365 void RenderViewHostManager::Observe( 395 void RenderViewHostManager::Observe(
366 int type, 396 int type,
367 const NotificationSource& source, 397 const NotificationSource& source,
368 const NotificationDetails& details) { 398 const NotificationDetails& details) {
369 switch (type) { 399 switch (type) {
370 case NOTIFICATION_RENDERER_PROCESS_CLOSING: 400 case NOTIFICATION_RENDERER_PROCESS_CLOSING:
371 RendererProcessClosing( 401 RendererProcessClosing(
372 Source<RenderProcessHost>(source).ptr()); 402 Source<RenderProcessHost>(source).ptr());
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 render_view_host_->Send( 881 render_view_host_->Send(
852 new ViewMsg_Stop(render_view_host_->GetRoutingID())); 882 new ViewMsg_Stop(render_view_host_->GetRoutingID()));
853 883
854 pending_render_view_host_->SetNavigationsSuspended(true, 884 pending_render_view_host_->SetNavigationsSuspended(true,
855 base::TimeTicks()); 885 base::TimeTicks());
856 } 886 }
857 887
858 // Tell the CrossSiteRequestManager that this RVH has a pending cross-site 888 // Tell the CrossSiteRequestManager that this RVH has a pending cross-site
859 // request, so that ResourceDispatcherHost will know to tell us to run the 889 // request, so that ResourceDispatcherHost will know to tell us to run the
860 // old page's unload handler before it sends the response. 890 // old page's unload handler before it sends the response.
861 pending_render_view_host_->SetHasPendingCrossSiteRequest(true, -1); 891 pending_render_view_host_->SetHasPendingCrossSiteRequest(true);
862 892
863 // We now have a pending RVH. 893 // We now have a pending RVH.
864 DCHECK(!cross_navigation_pending_); 894 DCHECK(!cross_navigation_pending_);
865 cross_navigation_pending_ = true; 895 cross_navigation_pending_ = true;
866 896
867 // Unless we are transferring an existing request, we should now 897 // Unless we are transferring an existing request, we should now
868 // tell the old render view to run its beforeunload handler, since it 898 // tell the old render view to run its beforeunload handler, since it
869 // doesn't otherwise know that the cross-site request is happening. This 899 // doesn't otherwise know that the cross-site request is happening. This
870 // will trigger a call to ShouldClosePage with the reply. 900 // will trigger a call to ShouldClosePage with the reply.
871 if (!is_transfer) 901 if (!is_transfer)
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 pending_render_view_host->GetProcess()->RemovePendingView(); 943 pending_render_view_host->GetProcess()->RemovePendingView();
914 944
915 // The pending RVH may already be on the swapped out list if we started to 945 // The pending RVH may already be on the swapped out list if we started to
916 // swap it back in and then canceled. If so, make sure it gets swapped out 946 // swap it back in and then canceled. If so, make sure it gets swapped out
917 // again. If it's not on the swapped out list (e.g., aborting a pending 947 // again. If it's not on the swapped out list (e.g., aborting a pending
918 // load), then it's safe to shut down. 948 // load), then it's safe to shut down.
919 if (IsOnSwappedOutList(pending_render_view_host)) { 949 if (IsOnSwappedOutList(pending_render_view_host)) {
920 // Any currently suspended navigations are no longer needed. 950 // Any currently suspended navigations are no longer needed.
921 pending_render_view_host->CancelSuspendedNavigations(); 951 pending_render_view_host->CancelSuspendedNavigations();
922 952
923 // We can pass -1,-1 because there is no pending response in the 953 pending_render_view_host->SwapOut();
924 // ResourceDispatcherHost to unpause.
925 pending_render_view_host->SwapOut(-1, -1);
926 } else { 954 } else {
927 // We won't be coming back, so shut this one down. 955 // We won't be coming back, so shut this one down.
928 pending_render_view_host->Shutdown(); 956 pending_render_view_host->Shutdown();
929 } 957 }
930 958
931 pending_web_ui_.reset(); 959 pending_web_ui_.reset();
932 pending_and_current_web_ui_.reset(); 960 pending_and_current_web_ui_.reset();
933 } 961 }
934 962
935 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) { 963 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost( 1003 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost(
976 SiteInstance* instance) { 1004 SiteInstance* instance) {
977 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); 1005 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId());
978 if (iter != swapped_out_hosts_.end()) 1006 if (iter != swapped_out_hosts_.end())
979 return iter->second; 1007 return iter->second;
980 1008
981 return NULL; 1009 return NULL;
982 } 1010 }
983 1011
984 } // namespace content 1012 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698