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

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

Powered by Google App Engine
This is Rietveld 408576698