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/navigator_impl.h" | 5 #include "content/browser/frame_host/navigator_impl.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
| 9 #include "base/logging.h" |
9 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
10 #include "base/time/time.h" | 11 #include "base/time/time.h" |
11 #include "content/browser/frame_host/frame_tree.h" | 12 #include "content/browser/frame_host/frame_tree.h" |
12 #include "content/browser/frame_host/frame_tree_node.h" | 13 #include "content/browser/frame_host/frame_tree_node.h" |
13 #include "content/browser/frame_host/navigation_controller_impl.h" | 14 #include "content/browser/frame_host/navigation_controller_impl.h" |
14 #include "content/browser/frame_host/navigation_entry_impl.h" | 15 #include "content/browser/frame_host/navigation_entry_impl.h" |
15 #include "content/browser/frame_host/navigation_handle_impl.h" | 16 #include "content/browser/frame_host/navigation_handle_impl.h" |
16 #include "content/browser/frame_host/navigation_request.h" | 17 #include "content/browser/frame_host/navigation_request.h" |
17 #include "content/browser/frame_host/navigation_request_info.h" | 18 #include "content/browser/frame_host/navigation_request_info.h" |
18 #include "content/browser/frame_host/navigator_delegate.h" | 19 #include "content/browser/frame_host/navigator_delegate.h" |
(...skipping 16 matching lines...) Expand all Loading... |
35 #include "content/public/browser/render_view_host.h" | 36 #include "content/public/browser/render_view_host.h" |
36 #include "content/public/browser/stream_handle.h" | 37 #include "content/public/browser/stream_handle.h" |
37 #include "content/public/browser/user_metrics.h" | 38 #include "content/public/browser/user_metrics.h" |
38 #include "content/public/common/bindings_policy.h" | 39 #include "content/public/common/bindings_policy.h" |
39 #include "content/public/common/browser_side_navigation_policy.h" | 40 #include "content/public/common/browser_side_navigation_policy.h" |
40 #include "content/public/common/content_client.h" | 41 #include "content/public/common/content_client.h" |
41 #include "content/public/common/content_constants.h" | 42 #include "content/public/common/content_constants.h" |
42 #include "content/public/common/resource_response.h" | 43 #include "content/public/common/resource_response.h" |
43 #include "content/public/common/url_constants.h" | 44 #include "content/public/common/url_constants.h" |
44 #include "net/base/net_errors.h" | 45 #include "net/base/net_errors.h" |
| 46 #include "url/gurl.h" |
45 #include "url/url_constants.h" | 47 #include "url/url_constants.h" |
46 | 48 |
47 namespace content { | 49 namespace content { |
48 | 50 |
49 namespace { | 51 namespace { |
50 | 52 |
51 FrameMsg_Navigate_Type::Value GetNavigationType( | 53 FrameMsg_Navigate_Type::Value GetNavigationType( |
52 BrowserContext* browser_context, const NavigationEntryImpl& entry, | 54 BrowserContext* browser_context, const NavigationEntryImpl& entry, |
53 NavigationController::ReloadType reload_type) { | 55 NavigationController::ReloadType reload_type) { |
54 switch (reload_type) { | 56 switch (reload_type) { |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 error_description, was_ignored_by_handler); | 264 error_description, was_ignored_by_handler); |
263 } | 265 } |
264 } | 266 } |
265 | 267 |
266 bool NavigatorImpl::NavigateToEntry( | 268 bool NavigatorImpl::NavigateToEntry( |
267 FrameTreeNode* frame_tree_node, | 269 FrameTreeNode* frame_tree_node, |
268 const FrameNavigationEntry& frame_entry, | 270 const FrameNavigationEntry& frame_entry, |
269 const NavigationEntryImpl& entry, | 271 const NavigationEntryImpl& entry, |
270 NavigationController::ReloadType reload_type, | 272 NavigationController::ReloadType reload_type, |
271 bool is_same_document_history_load, | 273 bool is_same_document_history_load, |
272 bool is_pending_entry) { | 274 bool is_pending_entry, |
| 275 const scoped_refptr<ResourceRequestBody>& post_body) { |
273 TRACE_EVENT0("browser,navigation", "NavigatorImpl::NavigateToEntry"); | 276 TRACE_EVENT0("browser,navigation", "NavigatorImpl::NavigateToEntry"); |
274 | 277 |
275 GURL dest_url = frame_entry.url(); | 278 GURL dest_url = frame_entry.url(); |
276 Referrer dest_referrer = frame_entry.referrer(); | 279 Referrer dest_referrer = frame_entry.referrer(); |
277 if (reload_type == | 280 if (reload_type == |
278 NavigationController::ReloadType::RELOAD_ORIGINAL_REQUEST_URL && | 281 NavigationController::ReloadType::RELOAD_ORIGINAL_REQUEST_URL && |
279 entry.GetOriginalRequestURL().is_valid() && !entry.GetHasPostData()) { | 282 entry.GetOriginalRequestURL().is_valid() && !entry.GetHasPostData()) { |
280 // We may have been redirected when navigating to the current URL. | 283 // We may have been redirected when navigating to the current URL. |
281 // Use the URL the user originally intended to visit, if it's valid and if a | 284 // Use the URL the user originally intended to visit, if it's valid and if a |
282 // POST wasn't involved; the latter case avoids issues with sending data to | 285 // POST wasn't involved; the latter case avoids issues with sending data to |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 is_transfer && | 384 is_transfer && |
382 entry.transferred_global_request_id().child_id == | 385 entry.transferred_global_request_id().child_id == |
383 dest_render_frame_host->GetProcess()->GetID(); | 386 dest_render_frame_host->GetProcess()->GetID(); |
384 if (!is_transfer_to_same) { | 387 if (!is_transfer_to_same) { |
385 navigation_data_.reset(new NavigationMetricsData( | 388 navigation_data_.reset(new NavigationMetricsData( |
386 navigation_start, dest_url, entry.restore_type())); | 389 navigation_start, dest_url, entry.restore_type())); |
387 // Create the navigation parameters. | 390 // Create the navigation parameters. |
388 FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType( | 391 FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType( |
389 controller_->GetBrowserContext(), entry, reload_type); | 392 controller_->GetBrowserContext(), entry, reload_type); |
390 dest_render_frame_host->Navigate( | 393 dest_render_frame_host->Navigate( |
391 entry.ConstructCommonNavigationParams(frame_entry, nullptr, dest_url, | 394 entry.ConstructCommonNavigationParams( |
392 dest_referrer, navigation_type, | 395 frame_entry, post_body, dest_url, dest_referrer, navigation_type, |
393 lofi_state, navigation_start), | 396 lofi_state, navigation_start), |
394 entry.ConstructStartNavigationParams(), | 397 entry.ConstructStartNavigationParams(), |
395 entry.ConstructRequestNavigationParams( | 398 entry.ConstructRequestNavigationParams( |
396 frame_entry, is_same_document_history_load, | 399 frame_entry, is_same_document_history_load, |
397 frame_tree_node->has_committed_real_load(), | 400 frame_tree_node->has_committed_real_load(), |
398 controller_->GetPendingEntryIndex() == -1, | 401 controller_->GetPendingEntryIndex() == -1, |
399 controller_->GetIndexOfEntry(&entry), | 402 controller_->GetIndexOfEntry(&entry), |
400 controller_->GetLastCommittedEntryIndex(), | 403 controller_->GetLastCommittedEntryIndex(), |
401 controller_->GetEntryCount())); | 404 controller_->GetEntryCount())); |
402 } else { | 405 } else { |
403 // No need to navigate again. Just resume the deferred request. | 406 // No need to navigate again. Just resume the deferred request. |
(...skipping 26 matching lines...) Expand all Loading... |
430 return true; | 433 return true; |
431 } | 434 } |
432 | 435 |
433 bool NavigatorImpl::NavigateToPendingEntry( | 436 bool NavigatorImpl::NavigateToPendingEntry( |
434 FrameTreeNode* frame_tree_node, | 437 FrameTreeNode* frame_tree_node, |
435 const FrameNavigationEntry& frame_entry, | 438 const FrameNavigationEntry& frame_entry, |
436 NavigationController::ReloadType reload_type, | 439 NavigationController::ReloadType reload_type, |
437 bool is_same_document_history_load) { | 440 bool is_same_document_history_load) { |
438 return NavigateToEntry(frame_tree_node, frame_entry, | 441 return NavigateToEntry(frame_tree_node, frame_entry, |
439 *controller_->GetPendingEntry(), reload_type, | 442 *controller_->GetPendingEntry(), reload_type, |
440 is_same_document_history_load, true); | 443 is_same_document_history_load, true, nullptr); |
441 } | 444 } |
442 | 445 |
443 bool NavigatorImpl::NavigateNewChildFrame( | 446 bool NavigatorImpl::NavigateNewChildFrame( |
444 RenderFrameHostImpl* render_frame_host, | 447 RenderFrameHostImpl* render_frame_host, |
445 const std::string& unique_name) { | 448 const std::string& unique_name) { |
446 NavigationEntryImpl* entry = | 449 NavigationEntryImpl* entry = |
447 controller_->GetEntryWithUniqueID(render_frame_host->nav_entry_id()); | 450 controller_->GetEntryWithUniqueID(render_frame_host->nav_entry_id()); |
448 if (!entry) | 451 if (!entry) |
449 return false; | 452 return false; |
450 | 453 |
451 // TODO(creis): Remove unique_name from the IPC, now that we can rely on the | 454 // TODO(creis): Remove unique_name from the IPC, now that we can rely on the |
452 // replication state. | 455 // replication state. |
453 DCHECK_EQ(render_frame_host->frame_tree_node()->unique_name(), unique_name); | 456 DCHECK_EQ(render_frame_host->frame_tree_node()->unique_name(), unique_name); |
454 FrameNavigationEntry* frame_entry = | 457 FrameNavigationEntry* frame_entry = |
455 entry->GetFrameEntry(render_frame_host->frame_tree_node()); | 458 entry->GetFrameEntry(render_frame_host->frame_tree_node()); |
456 if (!frame_entry) | 459 if (!frame_entry) |
457 return false; | 460 return false; |
458 | 461 |
459 return NavigateToEntry(render_frame_host->frame_tree_node(), *frame_entry, | 462 return NavigateToEntry(render_frame_host->frame_tree_node(), *frame_entry, |
460 *entry, NavigationControllerImpl::NO_RELOAD, false, | 463 *entry, NavigationControllerImpl::NO_RELOAD, false, |
461 false); | 464 false, nullptr); |
462 } | 465 } |
463 | 466 |
464 void NavigatorImpl::DidNavigate( | 467 void NavigatorImpl::DidNavigate( |
465 RenderFrameHostImpl* render_frame_host, | 468 RenderFrameHostImpl* render_frame_host, |
466 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { | 469 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { |
467 FrameTree* frame_tree = render_frame_host->frame_tree_node()->frame_tree(); | 470 FrameTree* frame_tree = render_frame_host->frame_tree_node()->frame_tree(); |
468 bool oopifs_possible = SiteIsolationPolicy::AreCrossProcessFramesPossible(); | 471 bool oopifs_possible = SiteIsolationPolicy::AreCrossProcessFramesPossible(); |
469 | 472 |
470 bool has_embedded_credentials = | 473 bool has_embedded_credentials = |
471 params.url.has_username() || params.url.has_password(); | 474 params.url.has_username() || params.url.has_password(); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 } | 721 } |
719 | 722 |
720 void NavigatorImpl::RequestTransferURL( | 723 void NavigatorImpl::RequestTransferURL( |
721 RenderFrameHostImpl* render_frame_host, | 724 RenderFrameHostImpl* render_frame_host, |
722 const GURL& url, | 725 const GURL& url, |
723 SiteInstance* source_site_instance, | 726 SiteInstance* source_site_instance, |
724 const std::vector<GURL>& redirect_chain, | 727 const std::vector<GURL>& redirect_chain, |
725 const Referrer& referrer, | 728 const Referrer& referrer, |
726 ui::PageTransition page_transition, | 729 ui::PageTransition page_transition, |
727 const GlobalRequestID& transferred_global_request_id, | 730 const GlobalRequestID& transferred_global_request_id, |
728 bool should_replace_current_entry) { | 731 bool should_replace_current_entry, |
| 732 const std::string& method, |
| 733 scoped_refptr<ResourceRequestBody> post_body) { |
| 734 // |method != "POST"| should imply absence of |post_body|. |
| 735 if (method != "POST" && post_body) { |
| 736 NOTREACHED(); |
| 737 post_body = nullptr; |
| 738 } |
| 739 |
729 // This call only makes sense for subframes if OOPIFs are possible. | 740 // This call only makes sense for subframes if OOPIFs are possible. |
730 DCHECK(!render_frame_host->GetParent() || | 741 DCHECK(!render_frame_host->GetParent() || |
731 SiteIsolationPolicy::AreCrossProcessFramesPossible()); | 742 SiteIsolationPolicy::AreCrossProcessFramesPossible()); |
732 | 743 |
733 // Allow the delegate to cancel the transfer. | 744 // Allow the delegate to cancel the transfer. |
734 if (!delegate_->ShouldTransferNavigation()) | 745 if (!delegate_->ShouldTransferNavigation()) |
735 return; | 746 return; |
736 | 747 |
737 GURL dest_url(url); | 748 GURL dest_url(url); |
738 Referrer referrer_to_use(referrer); | 749 Referrer referrer_to_use(referrer); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 } else { | 793 } else { |
783 // If there's no last committed entry, create an entry for about:blank | 794 // If there's no last committed entry, create an entry for about:blank |
784 // with a subframe entry for our destination. | 795 // with a subframe entry for our destination. |
785 // TODO(creis): Ensure this case can't exist in https://crbug.com/524208. | 796 // TODO(creis): Ensure this case can't exist in https://crbug.com/524208. |
786 entry = NavigationEntryImpl::FromNavigationEntry( | 797 entry = NavigationEntryImpl::FromNavigationEntry( |
787 controller_->CreateNavigationEntry( | 798 controller_->CreateNavigationEntry( |
788 GURL(url::kAboutBlankURL), referrer_to_use, page_transition, | 799 GURL(url::kAboutBlankURL), referrer_to_use, page_transition, |
789 is_renderer_initiated, std::string(), | 800 is_renderer_initiated, std::string(), |
790 controller_->GetBrowserContext())); | 801 controller_->GetBrowserContext())); |
791 } | 802 } |
792 // TODO(creis): Handle POST submissions. See https://crbug.com/582211 and | |
793 // https://crbug.com/101395. | |
794 entry->AddOrUpdateFrameEntry( | 803 entry->AddOrUpdateFrameEntry( |
795 node, -1, -1, nullptr, | 804 node, -1, -1, nullptr, |
796 static_cast<SiteInstanceImpl*>(source_site_instance), dest_url, | 805 static_cast<SiteInstanceImpl*>(source_site_instance), dest_url, |
797 referrer_to_use, PageState(), "GET", -1); | 806 referrer_to_use, PageState(), method, -1); |
798 } else { | 807 } else { |
799 // Main frame case. | 808 // Main frame case. |
800 entry = NavigationEntryImpl::FromNavigationEntry( | 809 entry = NavigationEntryImpl::FromNavigationEntry( |
801 controller_->CreateNavigationEntry( | 810 controller_->CreateNavigationEntry( |
802 dest_url, referrer_to_use, page_transition, is_renderer_initiated, | 811 dest_url, referrer_to_use, page_transition, is_renderer_initiated, |
803 std::string(), controller_->GetBrowserContext())); | 812 std::string(), controller_->GetBrowserContext())); |
804 entry->root_node()->frame_entry->set_source_site_instance( | 813 entry->root_node()->frame_entry->set_source_site_instance( |
805 static_cast<SiteInstanceImpl*>(source_site_instance)); | 814 static_cast<SiteInstanceImpl*>(source_site_instance)); |
806 } | 815 } |
807 | 816 |
808 entry->SetRedirectChain(redirect_chain); | 817 entry->SetRedirectChain(redirect_chain); |
809 // Don't allow an entry replacement if there is no entry to replace. | 818 // Don't allow an entry replacement if there is no entry to replace. |
810 // http://crbug.com/457149 | 819 // http://crbug.com/457149 |
811 if (should_replace_current_entry && controller_->GetEntryCount() > 0) | 820 if (should_replace_current_entry && controller_->GetEntryCount() > 0) |
812 entry->set_should_replace_entry(true); | 821 entry->set_should_replace_entry(true); |
813 if (controller_->GetLastCommittedEntry() && | 822 if (controller_->GetLastCommittedEntry() && |
814 controller_->GetLastCommittedEntry()->GetIsOverridingUserAgent()) { | 823 controller_->GetLastCommittedEntry()->GetIsOverridingUserAgent()) { |
815 entry->SetIsOverridingUserAgent(true); | 824 entry->SetIsOverridingUserAgent(true); |
816 } | 825 } |
817 entry->set_transferred_global_request_id(transferred_global_request_id); | 826 entry->set_transferred_global_request_id(transferred_global_request_id); |
818 // TODO(creis): Set user gesture and intent received timestamp on Android. | 827 // TODO(creis): Set user gesture and intent received timestamp on Android. |
819 | 828 |
820 // We may not have successfully added the FrameNavigationEntry to |entry| | 829 // We may not have successfully added the FrameNavigationEntry to |entry| |
821 // above (per https://crbug.com/608402), in which case we create it from | 830 // above (per https://crbug.com/608402), in which case we create it from |
822 // scratch. This works because we do not depend on |frame_entry| being inside | 831 // scratch. This works because we do not depend on |frame_entry| being inside |
823 // |entry| during NavigateToEntry. This will go away when we shortcut this | 832 // |entry| during NavigateToEntry. This will go away when we shortcut this |
824 // further in https://crbug.com/536906. | 833 // further in https://crbug.com/536906. |
825 scoped_refptr<FrameNavigationEntry> frame_entry(entry->GetFrameEntry(node)); | 834 scoped_refptr<FrameNavigationEntry> frame_entry(entry->GetFrameEntry(node)); |
826 if (!frame_entry) { | 835 if (!frame_entry) { |
827 // TODO(creis): Handle POST submissions here, as above. | |
828 frame_entry = new FrameNavigationEntry( | 836 frame_entry = new FrameNavigationEntry( |
829 node->unique_name(), -1, -1, nullptr, | 837 node->unique_name(), -1, -1, nullptr, |
830 static_cast<SiteInstanceImpl*>(source_site_instance), dest_url, | 838 static_cast<SiteInstanceImpl*>(source_site_instance), dest_url, |
831 referrer_to_use, "GET", -1); | 839 referrer_to_use, method, -1); |
832 } | 840 } |
833 NavigateToEntry(node, *frame_entry, *entry.get(), | 841 NavigateToEntry(node, *frame_entry, *entry.get(), |
834 NavigationController::NO_RELOAD, false, false); | 842 NavigationController::NO_RELOAD, false, false, post_body); |
835 } | 843 } |
836 | 844 |
837 // PlzNavigate | 845 // PlzNavigate |
838 void NavigatorImpl::OnBeforeUnloadACK(FrameTreeNode* frame_tree_node, | 846 void NavigatorImpl::OnBeforeUnloadACK(FrameTreeNode* frame_tree_node, |
839 bool proceed) { | 847 bool proceed) { |
840 CHECK(IsBrowserSideNavigationEnabled()); | 848 CHECK(IsBrowserSideNavigationEnabled()); |
841 DCHECK(frame_tree_node); | 849 DCHECK(frame_tree_node); |
842 | 850 |
843 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | 851 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
844 | 852 |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 if (pending_entry != controller_->GetVisibleEntry() || | 1173 if (pending_entry != controller_->GetVisibleEntry() || |
1166 !should_preserve_entry) { | 1174 !should_preserve_entry) { |
1167 controller_->DiscardPendingEntry(true); | 1175 controller_->DiscardPendingEntry(true); |
1168 | 1176 |
1169 // Also force the UI to refresh. | 1177 // Also force the UI to refresh. |
1170 controller_->delegate()->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL); | 1178 controller_->delegate()->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL); |
1171 } | 1179 } |
1172 } | 1180 } |
1173 | 1181 |
1174 } // namespace content | 1182 } // namespace content |
OLD | NEW |