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 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
275 // RenderFrameHostManager are completely initialized. This should be | 274 // RenderFrameHostManager are completely initialized. This should be |
276 // removed once the process manager moves away from NotificationService. | 275 // removed once the process manager moves away from NotificationService. |
277 // See https://crbug.com/462682. | 276 // See https://crbug.com/462682. |
278 delegate_->NotifyMainFrameSwappedFromRenderManager( | 277 delegate_->NotifyMainFrameSwappedFromRenderManager( |
279 nullptr, render_frame_host_->render_view_host()); | 278 nullptr, render_frame_host_->render_view_host()); |
280 } | 279 } |
281 } | 280 } |
282 | 281 |
283 // If entry includes the request ID of a request that is being transferred, | 282 // If entry includes the request ID of a request that is being transferred, |
284 // the destination render frame will take ownership, so release ownership of | 283 // the destination render frame will take ownership, so release ownership of |
285 // the request. | 284 // the transferring NavigationHandle. |
286 if (cross_site_transferring_request_.get() && | 285 if (transfer_navigation_handle_.get() && |
287 cross_site_transferring_request_->request_id() == | 286 transfer_navigation_handle_->request_id() == |
288 entry.transferred_global_request_id()) { | 287 entry.transferred_global_request_id()) { |
289 cross_site_transferring_request_->ReleaseRequest(); | |
290 | |
291 DCHECK(transfer_navigation_handle_); | |
292 | |
293 // Update the pending NavigationEntry ID on the transferring handle. | 288 // Update the pending NavigationEntry ID on the transferring handle. |
294 // TODO(creis): Make this line unnecessary by avoiding having a pending | 289 // TODO(creis): Make this line unnecessary by avoiding having a pending |
295 // entry for transfer navigations. See https://crbug.com/495161. | 290 // entry for transfer navigations. See https://crbug.com/495161. |
nasko
2016/09/08 23:45:39
Charlie has fixed https://crbug.com/495161 and we
clamy
2016/09/09 15:06:41
Done.
| |
296 transfer_navigation_handle_->update_entry_id_for_transfer( | 291 transfer_navigation_handle_->update_entry_id_for_transfer( |
297 entry.GetUniqueID()); | 292 entry.GetUniqueID()); |
298 | 293 |
299 // The navigating RenderFrameHost should take ownership of the | 294 // The navigating RenderFrameHost should take ownership of the |
300 // NavigationHandle that came from the transferring RenderFrameHost. | 295 // NavigationHandle that came from the transferring RenderFrameHost. |
301 dest_render_frame_host->SetNavigationHandle( | 296 dest_render_frame_host->SetNavigationHandle( |
302 std::move(transfer_navigation_handle_)); | 297 std::move(transfer_navigation_handle_)); |
298 | |
299 dest_render_frame_host->navigation_handle()->TransferredToRenderFrameHost( | |
300 dest_render_frame_host); | |
303 } | 301 } |
304 DCHECK(!transfer_navigation_handle_); | |
305 | 302 |
306 return dest_render_frame_host; | 303 return dest_render_frame_host; |
307 } | 304 } |
308 | 305 |
309 void RenderFrameHostManager::Stop() { | 306 void RenderFrameHostManager::Stop() { |
310 render_frame_host_->Stop(); | 307 render_frame_host_->Stop(); |
311 | 308 |
312 // If a cross-process navigation is happening, the pending RenderFrameHost | 309 // If a cross-process navigation is happening, the pending RenderFrameHost |
313 // should stop. This will lead to a DidFailProvisionalLoad, which will | 310 // should stop. This will lead to a DidFailProvisionalLoad, which will |
314 // properly destroy it. | 311 // properly destroy it. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 | 413 |
417 // This is not a cross-process navigation; the tab is being closed. | 414 // This is not a cross-process navigation; the tab is being closed. |
418 render_frame_host_->render_view_host()->ClosePage(); | 415 render_frame_host_->render_view_host()->ClosePage(); |
419 } | 416 } |
420 } | 417 } |
421 } | 418 } |
422 | 419 |
423 void RenderFrameHostManager::OnCrossSiteResponse( | 420 void RenderFrameHostManager::OnCrossSiteResponse( |
424 RenderFrameHostImpl* transferring_render_frame_host, | 421 RenderFrameHostImpl* transferring_render_frame_host, |
425 const GlobalRequestID& global_request_id, | 422 const GlobalRequestID& global_request_id, |
426 std::unique_ptr<CrossSiteTransferringRequest> | |
427 cross_site_transferring_request, | |
428 const std::vector<GURL>& transfer_url_chain, | 423 const std::vector<GURL>& transfer_url_chain, |
429 const Referrer& referrer, | 424 const Referrer& referrer, |
430 ui::PageTransition page_transition, | 425 ui::PageTransition page_transition, |
431 bool should_replace_current_entry) { | 426 bool should_replace_current_entry) { |
432 // We should only get here for transfer navigations. Most cross-process | |
433 // navigations can just continue and wait to run the unload handler (by | |
434 // swapping out) when the new navigation commits. | |
435 CHECK(cross_site_transferring_request); | |
436 | |
437 // A transfer should only have come from our pending or current RFH. If it | 427 // A transfer should only have come from our pending or current RFH. If it |
438 // started as a cross-process navigation via OpenURL, this is the pending | 428 // started as a cross-process navigation via OpenURL, this is the pending |
439 // one. If it wasn't cross-process until the transfer, this is the current | 429 // one. If it wasn't cross-process until the transfer, this is the current |
440 // one. | 430 // one. |
441 // | 431 // |
442 // Note that having a pending RFH does not imply that it was the one that | 432 // Note that having a pending RFH does not imply that it was the one that |
443 // made the request. Suppose that during a pending cross-site navigation, | 433 // made the request. Suppose that during a pending cross-site navigation, |
444 // the frame performs a different same-site navigation which redirects | 434 // the frame performs a different same-site navigation which redirects |
445 // cross-site. In this case, there will be a pending RFH, but this request | 435 // cross-site. In this case, there will be a pending RFH, but this request |
446 // is made by the current RFH. Later, this will create a new pending RFH and | 436 // is made by the current RFH. Later, this will create a new pending RFH and |
447 // clean up the old one. | 437 // clean up the old one. |
448 // | 438 // |
449 // TODO(creis): We need to handle the case that the pending RFH has changed | 439 // TODO(creis): We need to handle the case that the pending RFH has changed |
450 // in the mean time, while this was being posted from the IO thread. We | 440 // in the mean time, while this was being posted from the IO thread. We |
451 // should probably cancel the request in that case. | 441 // should probably cancel the request in that case. |
452 DCHECK(transferring_render_frame_host == pending_render_frame_host_.get() || | 442 DCHECK(transferring_render_frame_host == pending_render_frame_host_.get() || |
453 transferring_render_frame_host == render_frame_host_.get()); | 443 transferring_render_frame_host == render_frame_host_.get()); |
454 | 444 |
455 // Check if the FrameTreeNode is loading. This will be used later to notify | 445 // Check if the FrameTreeNode is loading. This will be used later to notify |
456 // the FrameTreeNode that the load stop if the transfer fails. | 446 // the FrameTreeNode that the load stop if the transfer fails. |
457 bool frame_tree_node_was_loading = frame_tree_node_->IsLoading(); | 447 bool frame_tree_node_was_loading = frame_tree_node_->IsLoading(); |
458 | 448 |
459 // Store the NavigationHandle to give it to the appropriate RenderFrameHost | 449 // Store the NavigationHandle to give it to the appropriate RenderFrameHost |
460 // after it started navigating. | 450 // after it started navigating. |
461 transfer_navigation_handle_ = | 451 transfer_navigation_handle_ = |
462 transferring_render_frame_host->PassNavigationHandleOwnership(); | 452 transferring_render_frame_host->PassNavigationHandleOwnership(); |
463 | 453 CHECK(transfer_navigation_handle_); |
464 // If something caused the cancellation of this navigation on the UI thread | |
465 // (possibly for security reasons) the navigation should not be allowed to | |
466 // proceed. | |
467 if (!transfer_navigation_handle_) | |
468 return; | |
469 | |
470 // Store the transferring request so that we can release it if the transfer | |
471 // navigation matches. | |
472 cross_site_transferring_request_ = std::move(cross_site_transferring_request); | |
473 | 454 |
474 // Set the transferring RenderFrameHost as not loading, so that it does not | 455 // Set the transferring RenderFrameHost as not loading, so that it does not |
475 // emit a DidStopLoading notification if it is destroyed when creating the | 456 // emit a DidStopLoading notification if it is destroyed when creating the |
476 // new navigating RenderFrameHost. | 457 // new navigating RenderFrameHost. |
477 transferring_render_frame_host->set_is_loading(false); | 458 transferring_render_frame_host->set_is_loading(false); |
478 | 459 |
479 // Treat the last URL in the chain as the destination and the remainder as | 460 // Treat the last URL in the chain as the destination and the remainder as |
480 // the redirect chain. | 461 // the redirect chain. |
481 CHECK(transfer_url_chain.size()); | 462 CHECK(transfer_url_chain.size()); |
482 GURL transfer_url = transfer_url_chain.back(); | 463 GURL transfer_url = transfer_url_chain.back(); |
483 std::vector<GURL> rest_of_chain = transfer_url_chain; | 464 std::vector<GURL> rest_of_chain = transfer_url_chain; |
484 rest_of_chain.pop_back(); | 465 rest_of_chain.pop_back(); |
485 | 466 |
486 transferring_render_frame_host->frame_tree_node() | 467 transferring_render_frame_host->frame_tree_node() |
487 ->navigator() | 468 ->navigator() |
488 ->RequestTransferURL( | 469 ->RequestTransferURL( |
489 transferring_render_frame_host, transfer_url, nullptr, rest_of_chain, | 470 transferring_render_frame_host, transfer_url, nullptr, rest_of_chain, |
490 referrer, page_transition, global_request_id, | 471 referrer, page_transition, global_request_id, |
491 should_replace_current_entry, | 472 should_replace_current_entry, |
492 transfer_navigation_handle_->IsPost() ? "POST" : "GET", | 473 transfer_navigation_handle_->IsPost() ? "POST" : "GET", |
493 transfer_navigation_handle_->resource_request_body()); | 474 transfer_navigation_handle_->resource_request_body()); |
494 | 475 |
495 // The transferring request was only needed during the RequestTransferURL | |
496 // call, so it is safe to clear at this point. | |
497 cross_site_transferring_request_.reset(); | |
498 | |
499 // If the navigation continued, the NavigationHandle should have been | 476 // If the navigation continued, the NavigationHandle should have been |
500 // transfered to a RenderFrameHost. In the other cases, it should be cleared. | 477 // transfered to a RenderFrameHost. In the other cases, it should be cleared. |
478 // If the NavigationHandle wasn't claimed, this will lead to the cancelation | |
479 // of the request in the network stack. | |
501 transfer_navigation_handle_.reset(); | 480 transfer_navigation_handle_.reset(); |
502 | 481 |
503 // If the navigation in the new renderer did not start, inform the | 482 // If the navigation in the new renderer did not start, inform the |
504 // FrameTreeNode that it stopped loading. | 483 // FrameTreeNode that it stopped loading. |
505 if (!frame_tree_node_->IsLoading() && frame_tree_node_was_loading) | 484 if (!frame_tree_node_->IsLoading() && frame_tree_node_was_loading) |
506 frame_tree_node_->DidStopLoading(); | 485 frame_tree_node_->DidStopLoading(); |
507 } | 486 } |
508 | 487 |
509 void RenderFrameHostManager::DidNavigateFrame( | 488 void RenderFrameHostManager::DidNavigateFrame( |
510 RenderFrameHostImpl* render_frame_host, | 489 RenderFrameHostImpl* render_frame_host, |
(...skipping 1782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2293 // RFH isn't live.) | 2272 // RFH isn't live.) |
2294 CommitPending(); | 2273 CommitPending(); |
2295 return render_frame_host_.get(); | 2274 return render_frame_host_.get(); |
2296 } | 2275 } |
2297 // Otherwise, it's safe to treat this as a pending cross-process transition. | 2276 // Otherwise, it's safe to treat this as a pending cross-process transition. |
2298 | 2277 |
2299 bool is_transfer = transferred_request_id != GlobalRequestID(); | 2278 bool is_transfer = transferred_request_id != GlobalRequestID(); |
2300 if (is_transfer) { | 2279 if (is_transfer) { |
2301 // We don't need to stop the old renderer or run beforeunload/unload | 2280 // We don't need to stop the old renderer or run beforeunload/unload |
2302 // handlers, because those have already been done. | 2281 // handlers, because those have already been done. |
2303 DCHECK(cross_site_transferring_request_->request_id() == | 2282 DCHECK(transfer_navigation_handle_ && |
2304 transferred_request_id); | 2283 transfer_navigation_handle_->request_id() == |
2284 transferred_request_id); | |
2305 } else if (!pending_render_frame_host_->are_navigations_suspended()) { | 2285 } else if (!pending_render_frame_host_->are_navigations_suspended()) { |
2306 // If the pending RFH hasn't already been suspended from a previous | 2286 // If the pending RFH hasn't already been suspended from a previous |
2307 // attempt to navigate it, then we need to wait for the beforeunload | 2287 // attempt to navigate it, then we need to wait for the beforeunload |
2308 // handler to run. Suspend navigations in the pending RFH until we hear | 2288 // handler to run. Suspend navigations in the pending RFH until we hear |
2309 // back from the old RFH's beforeunload handler (via OnBeforeUnloadACK or | 2289 // back from the old RFH's beforeunload handler (via OnBeforeUnloadACK or |
2310 // a timeout). If the handler returns false, we'll have to cancel the | 2290 // a timeout). If the handler returns false, we'll have to cancel the |
2311 // request. | 2291 // request. |
2312 // | 2292 // |
2313 // Also make sure the old RenderFrame stops, in case a load is in | 2293 // Also make sure the old RenderFrame stops, in case a load is in |
2314 // progress. (We don't want to do this for transfers, since it will | 2294 // 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... | |
2679 resolved_url)) { | 2659 resolved_url)) { |
2680 DCHECK(!dest_instance || | 2660 DCHECK(!dest_instance || |
2681 dest_instance == render_frame_host_->GetSiteInstance()); | 2661 dest_instance == render_frame_host_->GetSiteInstance()); |
2682 return false; | 2662 return false; |
2683 } | 2663 } |
2684 | 2664 |
2685 return true; | 2665 return true; |
2686 } | 2666 } |
2687 | 2667 |
2688 } // namespace content | 2668 } // namespace content |
OLD | NEW |