OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/frame_host/render_frame_host_manager.h" | 5 #include "content/browser/frame_host/render_frame_host_manager.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/debug/crash_logging.h" | 13 #include "base/debug/crash_logging.h" |
14 #include "base/debug/dump_without_crashing.h" | 14 #include "base/debug/dump_without_crashing.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
18 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
19 #include "content/browser/child_process_security_policy_impl.h" | 19 #include "content/browser/child_process_security_policy_impl.h" |
20 #include "content/browser/devtools/render_frame_devtools_agent_host.h" | 20 #include "content/browser/devtools/render_frame_devtools_agent_host.h" |
21 #include "content/browser/frame_host/cross_site_transferring_request.h" | |
22 #include "content/browser/frame_host/debug_urls.h" | 21 #include "content/browser/frame_host/debug_urls.h" |
23 #include "content/browser/frame_host/frame_navigation_entry.h" | 22 #include "content/browser/frame_host/frame_navigation_entry.h" |
24 #include "content/browser/frame_host/interstitial_page_impl.h" | 23 #include "content/browser/frame_host/interstitial_page_impl.h" |
25 #include "content/browser/frame_host/navigation_controller_impl.h" | 24 #include "content/browser/frame_host/navigation_controller_impl.h" |
26 #include "content/browser/frame_host/navigation_entry_impl.h" | 25 #include "content/browser/frame_host/navigation_entry_impl.h" |
27 #include "content/browser/frame_host/navigation_handle_impl.h" | 26 #include "content/browser/frame_host/navigation_handle_impl.h" |
28 #include "content/browser/frame_host/navigation_request.h" | 27 #include "content/browser/frame_host/navigation_request.h" |
29 #include "content/browser/frame_host/navigator.h" | 28 #include "content/browser/frame_host/navigator.h" |
30 #include "content/browser/frame_host/render_frame_host_factory.h" | 29 #include "content/browser/frame_host/render_frame_host_factory.h" |
31 #include "content/browser/frame_host/render_frame_host_impl.h" | 30 #include "content/browser/frame_host/render_frame_host_impl.h" |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 // RenderFrameHostManager are completely initialized. This should be | 272 // RenderFrameHostManager are completely initialized. This should be |
274 // removed once the process manager moves away from NotificationService. | 273 // removed once the process manager moves away from NotificationService. |
275 // See https://crbug.com/462682. | 274 // See https://crbug.com/462682. |
276 delegate_->NotifyMainFrameSwappedFromRenderManager( | 275 delegate_->NotifyMainFrameSwappedFromRenderManager( |
277 nullptr, render_frame_host_->render_view_host()); | 276 nullptr, render_frame_host_->render_view_host()); |
278 } | 277 } |
279 } | 278 } |
280 | 279 |
281 // If entry includes the request ID of a request that is being transferred, | 280 // If entry includes the request ID of a request that is being transferred, |
282 // the destination render frame will take ownership, so release ownership of | 281 // the destination render frame will take ownership, so release ownership of |
283 // the request. | 282 // the transferring NavigationHandle. |
284 if (cross_site_transferring_request_.get() && | 283 if (transfer_navigation_handle_.get() && |
285 cross_site_transferring_request_->request_id() == | 284 transfer_navigation_handle_->request_id() == |
286 entry.transferred_global_request_id()) { | 285 entry.transferred_global_request_id()) { |
287 cross_site_transferring_request_->ReleaseRequest(); | |
288 | |
289 DCHECK(transfer_navigation_handle_); | |
290 | |
291 // Update the pending NavigationEntry ID on the transferring handle. | |
292 // TODO(creis): Make this line unnecessary by avoiding having a pending | |
293 // entry for transfer navigations. See https://crbug.com/495161. | |
294 transfer_navigation_handle_->update_entry_id_for_transfer( | |
295 entry.GetUniqueID()); | |
296 | |
297 // The navigating RenderFrameHost should take ownership of the | 286 // The navigating RenderFrameHost should take ownership of the |
298 // NavigationHandle that came from the transferring RenderFrameHost. | 287 // NavigationHandle that came from the transferring RenderFrameHost. |
299 dest_render_frame_host->SetNavigationHandle( | 288 dest_render_frame_host->SetNavigationHandle( |
300 std::move(transfer_navigation_handle_)); | 289 std::move(transfer_navigation_handle_)); |
| 290 |
| 291 dest_render_frame_host->navigation_handle()->set_render_frame_host( |
| 292 dest_render_frame_host); |
301 } | 293 } |
302 DCHECK(!transfer_navigation_handle_); | |
303 | 294 |
304 return dest_render_frame_host; | 295 return dest_render_frame_host; |
305 } | 296 } |
306 | 297 |
307 void RenderFrameHostManager::Stop() { | 298 void RenderFrameHostManager::Stop() { |
308 render_frame_host_->Stop(); | 299 render_frame_host_->Stop(); |
309 | 300 |
310 // If a cross-process navigation is happening, the pending RenderFrameHost | 301 // If a cross-process navigation is happening, the pending RenderFrameHost |
311 // should stop. This will lead to a DidFailProvisionalLoad, which will | 302 // should stop. This will lead to a DidFailProvisionalLoad, which will |
312 // properly destroy it. | 303 // properly destroy it. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 | 405 |
415 // This is not a cross-process navigation; the tab is being closed. | 406 // This is not a cross-process navigation; the tab is being closed. |
416 render_frame_host_->render_view_host()->ClosePage(); | 407 render_frame_host_->render_view_host()->ClosePage(); |
417 } | 408 } |
418 } | 409 } |
419 } | 410 } |
420 | 411 |
421 void RenderFrameHostManager::OnCrossSiteResponse( | 412 void RenderFrameHostManager::OnCrossSiteResponse( |
422 RenderFrameHostImpl* transferring_render_frame_host, | 413 RenderFrameHostImpl* transferring_render_frame_host, |
423 const GlobalRequestID& global_request_id, | 414 const GlobalRequestID& global_request_id, |
424 std::unique_ptr<CrossSiteTransferringRequest> | |
425 cross_site_transferring_request, | |
426 const std::vector<GURL>& transfer_url_chain, | 415 const std::vector<GURL>& transfer_url_chain, |
427 const Referrer& referrer, | 416 const Referrer& referrer, |
428 ui::PageTransition page_transition, | 417 ui::PageTransition page_transition, |
429 bool should_replace_current_entry) { | 418 bool should_replace_current_entry) { |
430 // We should only get here for transfer navigations. Most cross-process | |
431 // navigations can just continue and wait to run the unload handler (by | |
432 // swapping out) when the new navigation commits. | |
433 CHECK(cross_site_transferring_request); | |
434 | |
435 // A transfer should only have come from our pending or current RFH. If it | 419 // A transfer should only have come from our pending or current RFH. If it |
436 // started as a cross-process navigation via OpenURL, this is the pending | 420 // started as a cross-process navigation via OpenURL, this is the pending |
437 // one. If it wasn't cross-process until the transfer, this is the current | 421 // one. If it wasn't cross-process until the transfer, this is the current |
438 // one. | 422 // one. |
439 // | 423 // |
440 // Note that having a pending RFH does not imply that it was the one that | 424 // Note that having a pending RFH does not imply that it was the one that |
441 // made the request. Suppose that during a pending cross-site navigation, | 425 // made the request. Suppose that during a pending cross-site navigation, |
442 // the frame performs a different same-site navigation which redirects | 426 // the frame performs a different same-site navigation which redirects |
443 // cross-site. In this case, there will be a pending RFH, but this request | 427 // cross-site. In this case, there will be a pending RFH, but this request |
444 // is made by the current RFH. Later, this will create a new pending RFH and | 428 // is made by the current RFH. Later, this will create a new pending RFH and |
445 // clean up the old one. | 429 // clean up the old one. |
446 // | 430 // |
447 // TODO(creis): We need to handle the case that the pending RFH has changed | 431 // TODO(creis): We need to handle the case that the pending RFH has changed |
448 // in the mean time, while this was being posted from the IO thread. We | 432 // in the mean time, while this was being posted from the IO thread. We |
449 // should probably cancel the request in that case. | 433 // should probably cancel the request in that case. |
450 DCHECK(transferring_render_frame_host == pending_render_frame_host_.get() || | 434 DCHECK(transferring_render_frame_host == pending_render_frame_host_.get() || |
451 transferring_render_frame_host == render_frame_host_.get()); | 435 transferring_render_frame_host == render_frame_host_.get()); |
452 | 436 |
453 // Check if the FrameTreeNode is loading. This will be used later to notify | 437 // Check if the FrameTreeNode is loading. This will be used later to notify |
454 // the FrameTreeNode that the load stop if the transfer fails. | 438 // the FrameTreeNode that the load stop if the transfer fails. |
455 bool frame_tree_node_was_loading = frame_tree_node_->IsLoading(); | 439 bool frame_tree_node_was_loading = frame_tree_node_->IsLoading(); |
456 | 440 |
457 // Store the NavigationHandle to give it to the appropriate RenderFrameHost | 441 // Store the NavigationHandle to give it to the appropriate RenderFrameHost |
458 // after it started navigating. | 442 // after it started navigating. |
459 transfer_navigation_handle_ = | 443 transfer_navigation_handle_ = |
460 transferring_render_frame_host->PassNavigationHandleOwnership(); | 444 transferring_render_frame_host->PassNavigationHandleOwnership(); |
461 | 445 CHECK(transfer_navigation_handle_); |
462 // If something caused the cancellation of this navigation on the UI thread | |
463 // (possibly for security reasons) the navigation should not be allowed to | |
464 // proceed. | |
465 if (!transfer_navigation_handle_) | |
466 return; | |
467 | |
468 // Store the transferring request so that we can release it if the transfer | |
469 // navigation matches. | |
470 cross_site_transferring_request_ = std::move(cross_site_transferring_request); | |
471 | 446 |
472 // Set the transferring RenderFrameHost as not loading, so that it does not | 447 // Set the transferring RenderFrameHost as not loading, so that it does not |
473 // emit a DidStopLoading notification if it is destroyed when creating the | 448 // emit a DidStopLoading notification if it is destroyed when creating the |
474 // new navigating RenderFrameHost. | 449 // new navigating RenderFrameHost. |
475 transferring_render_frame_host->set_is_loading(false); | 450 transferring_render_frame_host->set_is_loading(false); |
476 | 451 |
477 // Treat the last URL in the chain as the destination and the remainder as | 452 // Treat the last URL in the chain as the destination and the remainder as |
478 // the redirect chain. | 453 // the redirect chain. |
479 CHECK(transfer_url_chain.size()); | 454 CHECK(transfer_url_chain.size()); |
480 GURL transfer_url = transfer_url_chain.back(); | 455 GURL transfer_url = transfer_url_chain.back(); |
481 std::vector<GURL> rest_of_chain = transfer_url_chain; | 456 std::vector<GURL> rest_of_chain = transfer_url_chain; |
482 rest_of_chain.pop_back(); | 457 rest_of_chain.pop_back(); |
483 | 458 |
484 transferring_render_frame_host->frame_tree_node() | 459 transferring_render_frame_host->frame_tree_node() |
485 ->navigator() | 460 ->navigator() |
486 ->RequestTransferURL( | 461 ->RequestTransferURL( |
487 transferring_render_frame_host, transfer_url, nullptr, rest_of_chain, | 462 transferring_render_frame_host, transfer_url, nullptr, rest_of_chain, |
488 referrer, page_transition, global_request_id, | 463 referrer, page_transition, global_request_id, |
489 should_replace_current_entry, | 464 should_replace_current_entry, |
490 transfer_navigation_handle_->IsPost() ? "POST" : "GET", | 465 transfer_navigation_handle_->IsPost() ? "POST" : "GET", |
491 transfer_navigation_handle_->resource_request_body()); | 466 transfer_navigation_handle_->resource_request_body()); |
492 | 467 |
493 // The transferring request was only needed during the RequestTransferURL | |
494 // call, so it is safe to clear at this point. | |
495 cross_site_transferring_request_.reset(); | |
496 | |
497 // If the navigation continued, the NavigationHandle should have been | 468 // If the navigation continued, the NavigationHandle should have been |
498 // transfered to a RenderFrameHost. In the other cases, it should be cleared. | 469 // transfered to a RenderFrameHost. In the other cases, it should be cleared. |
| 470 // If the NavigationHandle wasn't claimed, this will lead to the cancelation |
| 471 // of the request in the network stack. |
499 transfer_navigation_handle_.reset(); | 472 transfer_navigation_handle_.reset(); |
500 | 473 |
501 // If the navigation in the new renderer did not start, inform the | 474 // If the navigation in the new renderer did not start, inform the |
502 // FrameTreeNode that it stopped loading. | 475 // FrameTreeNode that it stopped loading. |
503 if (!frame_tree_node_->IsLoading() && frame_tree_node_was_loading) | 476 if (!frame_tree_node_->IsLoading() && frame_tree_node_was_loading) |
504 frame_tree_node_->DidStopLoading(); | 477 frame_tree_node_->DidStopLoading(); |
505 } | 478 } |
506 | 479 |
507 void RenderFrameHostManager::DidNavigateFrame( | 480 void RenderFrameHostManager::DidNavigateFrame( |
508 RenderFrameHostImpl* render_frame_host, | 481 RenderFrameHostImpl* render_frame_host, |
(...skipping 1727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2236 // Note: Do not add code here to determine whether the subframe should swap | 2209 // Note: Do not add code here to determine whether the subframe should swap |
2237 // or not. Add it to CanSubframeSwapProcess instead. | 2210 // or not. Add it to CanSubframeSwapProcess instead. |
2238 return render_frame_host_.get(); | 2211 return render_frame_host_.get(); |
2239 } | 2212 } |
2240 | 2213 |
2241 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); | 2214 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
2242 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( | 2215 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( |
2243 dest_url, source_instance, dest_instance, nullptr, transition, | 2216 dest_url, source_instance, dest_instance, nullptr, transition, |
2244 dest_is_restore, dest_is_view_source_mode); | 2217 dest_is_restore, dest_is_view_source_mode); |
2245 | 2218 |
| 2219 // Inform the transferring NavigationHandle of a transfer to a different |
| 2220 // SiteInstance. It is important do so now, in order to mark the request as |
| 2221 // transferring on the IO thread before attempting to destroy the pending RFH. |
| 2222 // This ensures the network request will not be destroyed along the pending |
| 2223 // RFH but will persist until it is picked up by the new RFH. |
| 2224 if (transfer_navigation_handle_.get() && |
| 2225 transfer_navigation_handle_->request_id() == transferred_request_id && |
| 2226 new_instance.get() != |
| 2227 transfer_navigation_handle_->GetRenderFrameHost() |
| 2228 ->GetSiteInstance()) { |
| 2229 transfer_navigation_handle_->Transfer(); |
| 2230 } |
| 2231 |
2246 // If we are currently navigating cross-process to a pending RFH for a | 2232 // If we are currently navigating cross-process to a pending RFH for a |
2247 // different SiteInstance, we want to get back to normal and then navigate as | 2233 // different SiteInstance, we want to get back to normal and then navigate as |
2248 // usual. We will reuse the pending RFH below if it matches the destination | 2234 // usual. We will reuse the pending RFH below if it matches the destination |
2249 // SiteInstance. | 2235 // SiteInstance. |
2250 if (pending_render_frame_host_) { | 2236 if (pending_render_frame_host_) { |
2251 if (pending_render_frame_host_->GetSiteInstance() != new_instance) { | 2237 if (pending_render_frame_host_->GetSiteInstance() != new_instance) { |
2252 CancelPending(); | 2238 CancelPending(); |
2253 } else { | 2239 } else { |
2254 // When a pending RFH is reused, it should always be live, since it is | 2240 // When a pending RFH is reused, it should always be live, since it is |
2255 // cleared whenever a process dies. | 2241 // cleared whenever a process dies. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2295 // RFH isn't live.) | 2281 // RFH isn't live.) |
2296 CommitPending(); | 2282 CommitPending(); |
2297 return render_frame_host_.get(); | 2283 return render_frame_host_.get(); |
2298 } | 2284 } |
2299 // Otherwise, it's safe to treat this as a pending cross-process transition. | 2285 // Otherwise, it's safe to treat this as a pending cross-process transition. |
2300 | 2286 |
2301 bool is_transfer = transferred_request_id != GlobalRequestID(); | 2287 bool is_transfer = transferred_request_id != GlobalRequestID(); |
2302 if (is_transfer) { | 2288 if (is_transfer) { |
2303 // We don't need to stop the old renderer or run beforeunload/unload | 2289 // We don't need to stop the old renderer or run beforeunload/unload |
2304 // handlers, because those have already been done. | 2290 // handlers, because those have already been done. |
2305 DCHECK(cross_site_transferring_request_->request_id() == | 2291 DCHECK(transfer_navigation_handle_ && |
2306 transferred_request_id); | 2292 transfer_navigation_handle_->request_id() == |
| 2293 transferred_request_id); |
2307 } else if (!pending_render_frame_host_->are_navigations_suspended()) { | 2294 } else if (!pending_render_frame_host_->are_navigations_suspended()) { |
2308 // If the pending RFH hasn't already been suspended from a previous | 2295 // If the pending RFH hasn't already been suspended from a previous |
2309 // attempt to navigate it, then we need to wait for the beforeunload | 2296 // attempt to navigate it, then we need to wait for the beforeunload |
2310 // handler to run. Suspend navigations in the pending RFH until we hear | 2297 // handler to run. Suspend navigations in the pending RFH until we hear |
2311 // back from the old RFH's beforeunload handler (via OnBeforeUnloadACK or | 2298 // back from the old RFH's beforeunload handler (via OnBeforeUnloadACK or |
2312 // a timeout). If the handler returns false, we'll have to cancel the | 2299 // a timeout). If the handler returns false, we'll have to cancel the |
2313 // request. | 2300 // request. |
2314 // | 2301 // |
2315 // Also make sure the old RenderFrame stops, in case a load is in | 2302 // Also make sure the old RenderFrame stops, in case a load is in |
2316 // progress. (We don't want to do this for transfers, since it will | 2303 // progress. (We don't want to do this for transfers, since it will |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2681 resolved_url)) { | 2668 resolved_url)) { |
2682 DCHECK(!dest_instance || | 2669 DCHECK(!dest_instance || |
2683 dest_instance == render_frame_host_->GetSiteInstance()); | 2670 dest_instance == render_frame_host_->GetSiteInstance()); |
2684 return false; | 2671 return false; |
2685 } | 2672 } |
2686 | 2673 |
2687 return true; | 2674 return true; |
2688 } | 2675 } |
2689 | 2676 |
2690 } // namespace content | 2677 } // namespace content |
OLD | NEW |