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/logging.h" | 10 #include "base/logging.h" |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 pending_render_view_host_->SetIsLoading(is_loading); | 182 pending_render_view_host_->SetIsLoading(is_loading); |
183 } | 183 } |
184 | 184 |
185 bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() { | 185 bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() { |
186 if (!cross_navigation_pending_) | 186 if (!cross_navigation_pending_) |
187 return true; | 187 return true; |
188 | 188 |
189 // If the tab becomes unresponsive during unload while doing a | 189 // If the tab becomes unresponsive during unload while doing a |
190 // cross-site navigation, proceed with the navigation. (This assumes that | 190 // cross-site navigation, proceed with the navigation. (This assumes that |
191 // the pending RenderViewHost is still responsive.) | 191 // the pending RenderViewHost is still responsive.) |
192 int pending_request_id = pending_render_view_host_->GetPendingRequestId(); | 192 bool waiting_for_beforeunload = |
193 if (pending_request_id == -1) { | 193 render_view_host_->is_waiting_for_beforeunload_ack(); |
nasko
2013/06/05 18:17:07
Why is this checking for beforeunload handler, whe
Charlie Reis
2013/06/05 23:03:34
Hmm, this old logic may have been buggy. It assum
| |
194 if (waiting_for_beforeunload) { | |
194 // Haven't gotten around to starting the request, because we're still | 195 // 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 | 196 // 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 | 197 // did finish, to let the navigation proceed. Note that there's a danger |
197 // that the beforeunload handler will later finish and possibly return | 198 // that the beforeunload handler will later finish and possibly return |
198 // false (meaning the navigation should not proceed), but we'll ignore it | 199 // false (meaning the navigation should not proceed), but we'll ignore it |
199 // in this case because it took too long. | 200 // in this case because it took too long. |
200 if (pending_render_view_host_->are_navigations_suspended()) | 201 if (pending_render_view_host_->are_navigations_suspended()) |
201 pending_render_view_host_->SetNavigationsSuspended( | 202 pending_render_view_host_->SetNavigationsSuspended( |
202 false, base::TimeTicks::Now()); | 203 false, base::TimeTicks::Now()); |
203 } else { | 204 } else { |
204 // The request has been started and paused while we're waiting for the | 205 // 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 // unload handler to finish. We'll pretend that it did. The pending |
206 // IO thread to let the response continue. The pending renderer will then | 207 // renderer will then be swapped in as part of the usual DidNavigate logic. |
207 // be swapped in as part of the usual DidNavigate logic. (If the unload | 208 // (If the unload handler later finishes, this call will be ignored because |
208 // handler later finishes, this call will be ignored because the state in | 209 // the pending_nav_params_ state in WebContents will already be cleaned up.) |
209 // CrossSiteResourceHandler will already be cleaned up.) | 210 current_host()->OnSwappedOut(true); |
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 } | 211 } |
218 return false; | 212 return false; |
219 } | 213 } |
220 | 214 |
221 void RenderViewHostManager::DidNavigateMainFrame( | 215 void RenderViewHostManager::DidNavigateMainFrame( |
222 RenderViewHost* render_view_host) { | 216 RenderViewHost* render_view_host) { |
223 if (!cross_navigation_pending_) { | 217 if (!cross_navigation_pending_) { |
224 DCHECK(!pending_render_view_host_); | 218 DCHECK(!pending_render_view_host_); |
225 | 219 |
226 // We should only hear this from our current renderer. | 220 // We should only hear this from our current renderer. |
227 DCHECK(render_view_host == render_view_host_); | 221 DCHECK(render_view_host == render_view_host_); |
228 | 222 |
229 // Even when there is no pending RVH, there may be a pending Web UI. | 223 // Even when there is no pending RVH, there may be a pending Web UI. |
230 if (pending_web_ui()) | 224 if (pending_web_ui()) |
231 CommitPending(); | 225 CommitPending(); |
232 return; | 226 return; |
233 } | 227 } |
234 | 228 |
235 if (render_view_host == pending_render_view_host_) { | 229 if (render_view_host == pending_render_view_host_) { |
236 // The pending cross-site navigation completed, so show the renderer. | 230 // The pending cross-site navigation completed, so show the renderer. |
237 // If it committed without sending network requests (e.g., data URLs), | 231 // 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 | 232 // 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. | 233 // handler. OK for that to happen in the background. |
240 if (pending_render_view_host_->GetPendingRequestId() == -1) { | 234 if (pending_render_view_host_->HasPendingCrossSiteRequest()) |
241 OnCrossSiteResponse(pending_render_view_host_->GetProcess()->GetID(), | 235 SwapOutOldPage(); |
242 pending_render_view_host_->GetRoutingID()); | |
243 } | |
244 | 236 |
245 CommitPending(); | 237 CommitPending(); |
246 cross_navigation_pending_ = false; | 238 cross_navigation_pending_ = false; |
247 } else if (render_view_host == render_view_host_) { | 239 } else if (render_view_host == render_view_host_) { |
248 // A navigation in the original page has taken place. Cancel the pending | 240 // A navigation in the original page has taken place. Cancel the pending |
249 // one. | 241 // one. |
250 CancelPending(); | 242 CancelPending(); |
251 cross_navigation_pending_ = false; | 243 cross_navigation_pending_ = false; |
252 } else { | 244 } else { |
253 // No one else should be sending us DidNavigate in this state. | 245 // No one else should be sending us DidNavigate in this state. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
331 delegate_->BeforeUnloadFiredFromRenderManager(proceed, proceed_time, | 323 delegate_->BeforeUnloadFiredFromRenderManager(proceed, proceed_time, |
332 &proceed_to_fire_unload); | 324 &proceed_to_fire_unload); |
333 | 325 |
334 if (proceed_to_fire_unload) { | 326 if (proceed_to_fire_unload) { |
335 // This is not a cross-site navigation, the tab is being closed. | 327 // This is not a cross-site navigation, the tab is being closed. |
336 render_view_host_->ClosePage(); | 328 render_view_host_->ClosePage(); |
337 } | 329 } |
338 } | 330 } |
339 } | 331 } |
340 | 332 |
341 void RenderViewHostManager::OnCrossSiteResponse(int new_render_process_host_id, | 333 void RenderViewHostManager::SwapOutOldPage() { |
342 int new_request_id) { | |
343 // Should only see this while we have a pending renderer. | 334 // Should only see this while we have a pending renderer. |
344 if (!cross_navigation_pending_) | 335 if (!cross_navigation_pending_) |
345 return; | 336 return; |
346 DCHECK(pending_render_view_host_); | 337 DCHECK(pending_render_view_host_); |
347 | 338 |
348 // Tell the old renderer it is being swapped out. This will fire the unload | 339 // 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 | 340 // handler (without firing the beforeunload handler a second time). When the |
350 // unload handler finishes and the navigation completes, we will send a | 341 // unload handler finishes and the navigation completes, we will send a |
351 // message to the ResourceDispatcherHost with the given pending request IDs, | 342 // message to the ResourceDispatcherHost, allowing the pending RVH's response |
352 // allowing the pending RVH's response to resume. | 343 // to resume. |
353 render_view_host_->SwapOut(new_render_process_host_id, new_request_id); | 344 render_view_host_->SwapOut(); |
354 | 345 |
355 // ResourceDispatcherHost has told us to run the onunload handler, which | 346 // 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 | 347 // 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 | 348 // navigation. Thus, we no longer need to remember that the RenderViewHost |
358 // is part of a pending cross-site request. | 349 // is part of a pending cross-site request. |
359 pending_render_view_host_->SetHasPendingCrossSiteRequest(false, | 350 pending_render_view_host_->SetHasPendingCrossSiteRequest(false); |
360 new_request_id); | |
361 } | 351 } |
362 | 352 |
363 void RenderViewHostManager::Observe( | 353 void RenderViewHostManager::Observe( |
364 int type, | 354 int type, |
365 const NotificationSource& source, | 355 const NotificationSource& source, |
366 const NotificationDetails& details) { | 356 const NotificationDetails& details) { |
367 switch (type) { | 357 switch (type) { |
368 case NOTIFICATION_RENDERER_PROCESS_CLOSING: | 358 case NOTIFICATION_RENDERER_PROCESS_CLOSING: |
369 RendererProcessClosing( | 359 RendererProcessClosing( |
370 Source<RenderProcessHost>(source).ptr()); | 360 Source<RenderProcessHost>(source).ptr()); |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
849 render_view_host_->Send( | 839 render_view_host_->Send( |
850 new ViewMsg_Stop(render_view_host_->GetRoutingID())); | 840 new ViewMsg_Stop(render_view_host_->GetRoutingID())); |
851 | 841 |
852 pending_render_view_host_->SetNavigationsSuspended(true, | 842 pending_render_view_host_->SetNavigationsSuspended(true, |
853 base::TimeTicks()); | 843 base::TimeTicks()); |
854 } | 844 } |
855 | 845 |
856 // Tell the CrossSiteRequestManager that this RVH has a pending cross-site | 846 // Tell the CrossSiteRequestManager that this RVH has a pending cross-site |
857 // request, so that ResourceDispatcherHost will know to tell us to run the | 847 // request, so that ResourceDispatcherHost will know to tell us to run the |
858 // old page's unload handler before it sends the response. | 848 // old page's unload handler before it sends the response. |
859 pending_render_view_host_->SetHasPendingCrossSiteRequest(true, -1); | 849 pending_render_view_host_->SetHasPendingCrossSiteRequest(true); |
860 | 850 |
861 // We now have a pending RVH. | 851 // We now have a pending RVH. |
862 DCHECK(!cross_navigation_pending_); | 852 DCHECK(!cross_navigation_pending_); |
863 cross_navigation_pending_ = true; | 853 cross_navigation_pending_ = true; |
864 | 854 |
865 // Unless we are transferring an existing request, we should now | 855 // Unless we are transferring an existing request, we should now |
866 // tell the old render view to run its beforeunload handler, since it | 856 // 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 | 857 // doesn't otherwise know that the cross-site request is happening. This |
868 // will trigger a call to ShouldClosePage with the reply. | 858 // will trigger a call to ShouldClosePage with the reply. |
869 if (!is_transfer) | 859 if (!is_transfer) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
911 pending_render_view_host->GetProcess()->RemovePendingView(); | 901 pending_render_view_host->GetProcess()->RemovePendingView(); |
912 | 902 |
913 // The pending RVH may already be on the swapped out list if we started to | 903 // 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 | 904 // 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 | 905 // again. If it's not on the swapped out list (e.g., aborting a pending |
916 // load), then it's safe to shut down. | 906 // load), then it's safe to shut down. |
917 if (IsOnSwappedOutList(pending_render_view_host)) { | 907 if (IsOnSwappedOutList(pending_render_view_host)) { |
918 // Any currently suspended navigations are no longer needed. | 908 // Any currently suspended navigations are no longer needed. |
919 pending_render_view_host->CancelSuspendedNavigations(); | 909 pending_render_view_host->CancelSuspendedNavigations(); |
920 | 910 |
921 // We can pass -1,-1 because there is no pending response in the | 911 pending_render_view_host->SwapOut(); |
922 // ResourceDispatcherHost to unpause. | |
923 pending_render_view_host->SwapOut(-1, -1); | |
924 } else { | 912 } else { |
925 // We won't be coming back, so shut this one down. | 913 // We won't be coming back, so shut this one down. |
926 pending_render_view_host->Shutdown(); | 914 pending_render_view_host->Shutdown(); |
927 } | 915 } |
928 | 916 |
929 pending_web_ui_.reset(); | 917 pending_web_ui_.reset(); |
930 pending_and_current_web_ui_.reset(); | 918 pending_and_current_web_ui_.reset(); |
931 } | 919 } |
932 | 920 |
933 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) { | 921 void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
973 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost( | 961 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost( |
974 SiteInstance* instance) { | 962 SiteInstance* instance) { |
975 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); | 963 RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); |
976 if (iter != swapped_out_hosts_.end()) | 964 if (iter != swapped_out_hosts_.end()) |
977 return iter->second; | 965 return iter->second; |
978 | 966 |
979 return NULL; | 967 return NULL; |
980 } | 968 } |
981 | 969 |
982 } // namespace content | 970 } // namespace content |
OLD | NEW |