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 "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
10 #include "content/browser/frame_host/frame_tree.h" | 10 #include "content/browser/frame_host/frame_tree.h" |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 void NavigatorImpl::DidStartProvisionalLoad( | 118 void NavigatorImpl::DidStartProvisionalLoad( |
119 RenderFrameHostImpl* render_frame_host, | 119 RenderFrameHostImpl* render_frame_host, |
120 const GURL& url) { | 120 const GURL& url) { |
121 bool is_error_page = (url.spec() == kUnreachableWebDataURL); | 121 bool is_error_page = (url.spec() == kUnreachableWebDataURL); |
122 bool is_iframe_srcdoc = (url.spec() == kAboutSrcDocURL); | 122 bool is_iframe_srcdoc = (url.spec() == kAboutSrcDocURL); |
123 GURL validated_url(url); | 123 GURL validated_url(url); |
124 RenderProcessHost* render_process_host = render_frame_host->GetProcess(); | 124 RenderProcessHost* render_process_host = render_frame_host->GetProcess(); |
125 render_process_host->FilterURL(false, &validated_url); | 125 render_process_host->FilterURL(false, &validated_url); |
126 | 126 |
127 bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame(); | 127 bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame(); |
128 NavigationEntryImpl* pending_entry = controller_->GetPendingEntry(); | 128 if (is_main_frame && !is_error_page) |
129 if (is_main_frame) { | 129 DidStartMainFrameNavigation(validated_url, |
130 // If there is no browser-initiated pending entry for this navigation and it | 130 render_frame_host->GetSiteInstance()); |
131 // is not for the error URL, create a pending entry using the current | |
132 // SiteInstance, and ensure the address bar updates accordingly. We don't | |
133 // know the referrer or extra headers at this point, but the referrer will | |
134 // be set properly upon commit. | |
135 bool has_browser_initiated_pending_entry = pending_entry && | |
136 !pending_entry->is_renderer_initiated(); | |
137 if (!has_browser_initiated_pending_entry && !is_error_page) { | |
138 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( | |
139 controller_->CreateNavigationEntry(validated_url, | |
140 content::Referrer(), | |
141 ui::PAGE_TRANSITION_LINK, | |
142 true /* is_renderer_initiated */, | |
143 std::string(), | |
144 controller_->GetBrowserContext())); | |
145 entry->set_site_instance(render_frame_host->GetSiteInstance()); | |
146 // TODO(creis): If there's a pending entry already, find a safe way to | |
147 // update it instead of replacing it and copying over things like this. | |
148 if (pending_entry) { | |
149 entry->set_transferred_global_request_id( | |
150 pending_entry->transferred_global_request_id()); | |
151 entry->set_should_replace_entry(pending_entry->should_replace_entry()); | |
152 entry->SetRedirectChain(pending_entry->GetRedirectChain()); | |
153 } | |
154 controller_->SetPendingEntry(entry); | |
155 if (delegate_) | |
156 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); | |
157 } | |
158 } | |
159 | 131 |
160 if (delegate_) { | 132 if (delegate_) { |
161 // Notify the observer about the start of the provisional load. | 133 // Notify the observer about the start of the provisional load. |
162 delegate_->DidStartProvisionalLoad( | 134 delegate_->DidStartProvisionalLoad( |
163 render_frame_host, validated_url, is_error_page, is_iframe_srcdoc); | 135 render_frame_host, validated_url, is_error_page, is_iframe_srcdoc); |
164 } | 136 } |
165 } | 137 } |
166 | 138 |
167 | 139 |
168 void NavigatorImpl::DidFailProvisionalLoadWithError( | 140 void NavigatorImpl::DidFailProvisionalLoadWithError( |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 else | 605 else |
634 CancelNavigation(frame_tree_node); | 606 CancelNavigation(frame_tree_node); |
635 } | 607 } |
636 | 608 |
637 // PlzNavigate | 609 // PlzNavigate |
638 void NavigatorImpl::OnBeginNavigation( | 610 void NavigatorImpl::OnBeginNavigation( |
639 FrameTreeNode* frame_tree_node, | 611 FrameTreeNode* frame_tree_node, |
640 const CommonNavigationParams& common_params, | 612 const CommonNavigationParams& common_params, |
641 const BeginNavigationParams& begin_params, | 613 const BeginNavigationParams& begin_params, |
642 scoped_refptr<ResourceRequestBody> body) { | 614 scoped_refptr<ResourceRequestBody> body) { |
| 615 // TODO(clamy): the url sent by the renderer should be validated with |
| 616 // FilterURL. |
643 // This is a renderer-initiated navigation. | 617 // This is a renderer-initiated navigation. |
644 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | 618 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
645 switches::kEnableBrowserSideNavigation)); | 619 switches::kEnableBrowserSideNavigation)); |
646 DCHECK(frame_tree_node); | 620 DCHECK(frame_tree_node); |
647 | 621 |
648 NavigationRequest* ongoing_navigation_request = | 622 NavigationRequest* ongoing_navigation_request = |
649 frame_tree_node->navigation_request(); | 623 frame_tree_node->navigation_request(); |
650 | 624 |
651 // The renderer-initiated navigation request is ignored iff a) there is an | 625 // The renderer-initiated navigation request is ignored iff a) there is an |
652 // ongoing request b) which is browser or user-initiated and c) the renderer | 626 // ongoing request b) which is browser or user-initiated and c) the renderer |
653 // request is not user-initiated. | 627 // request is not user-initiated. |
654 if (ongoing_navigation_request && | 628 if (ongoing_navigation_request && |
655 (ongoing_navigation_request->browser_initiated() || | 629 (ongoing_navigation_request->browser_initiated() || |
656 ongoing_navigation_request->begin_params().has_user_gesture) && | 630 ongoing_navigation_request->begin_params().has_user_gesture) && |
657 !begin_params.has_user_gesture) { | 631 !begin_params.has_user_gesture) { |
658 return; | 632 return; |
659 } | 633 } |
660 | 634 |
661 // In all other cases the current navigation, if any, is canceled and a new | 635 // In all other cases the current navigation, if any, is canceled and a new |
662 // NavigationRequest is created for the node. | 636 // NavigationRequest is created for the node. |
663 scoped_ptr<NavigationRequest> navigation_request = | 637 scoped_ptr<NavigationRequest> navigation_request = |
664 NavigationRequest::CreateRendererInitiated( | 638 NavigationRequest::CreateRendererInitiated( |
665 frame_tree_node, common_params, begin_params, body, | 639 frame_tree_node, common_params, begin_params, body, |
666 controller_->GetLastCommittedEntryIndex(), | 640 controller_->GetLastCommittedEntryIndex(), |
667 controller_->GetEntryCount()); | 641 controller_->GetEntryCount()); |
668 frame_tree_node->SetNavigationRequest(navigation_request.Pass()); | 642 frame_tree_node->SetNavigationRequest(navigation_request.Pass()); |
669 | 643 |
670 if (frame_tree_node->IsMainFrame()) | 644 if (frame_tree_node->IsMainFrame()) { |
| 645 // Renderer-initiated main-frame navigations that need to swap processes |
| 646 // will go to the browser via a OpenURL call, and then be handled by the |
| 647 // same code path as browser-initiated navigations. For renderer-initiated |
| 648 // main frame navigation that start via a BeginNavigation IPC, the |
| 649 // RenderFrameHost will not be swapped. Therefore it is safe to call |
| 650 // DidStartMainFrameNavigation with the SiteInstance from the current |
| 651 // RenderFrameHost. |
| 652 DidStartMainFrameNavigation( |
| 653 common_params.url, |
| 654 frame_tree_node->current_frame_host()->GetSiteInstance()); |
671 navigation_data_.reset(); | 655 navigation_data_.reset(); |
| 656 } |
672 | 657 |
673 BeginNavigation(frame_tree_node); | 658 BeginNavigation(frame_tree_node); |
674 } | 659 } |
675 | 660 |
676 // PlzNavigate | 661 // PlzNavigate |
677 void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node, | 662 void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node, |
678 ResourceResponse* response, | 663 ResourceResponse* response, |
679 scoped_ptr<StreamHandle> body) { | 664 scoped_ptr<StreamHandle> body) { |
680 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | 665 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
681 switches::kEnableBrowserSideNavigation)); | 666 switches::kEnableBrowserSideNavigation)); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 UMA_HISTOGRAM_TIMES( | 889 UMA_HISTOGRAM_TIMES( |
905 "Navigation.TimeToCommit_ExistingRenderer_BeforeUnloadDiscounted", | 890 "Navigation.TimeToCommit_ExistingRenderer_BeforeUnloadDiscounted", |
906 time_to_commit); | 891 time_to_commit); |
907 UMA_HISTOGRAM_TIMES( | 892 UMA_HISTOGRAM_TIMES( |
908 "Navigation.TimeToURLJobStart_ExistingRenderer_BeforeUnloadDiscounted", | 893 "Navigation.TimeToURLJobStart_ExistingRenderer_BeforeUnloadDiscounted", |
909 time_to_network); | 894 time_to_network); |
910 } | 895 } |
911 navigation_data_.reset(); | 896 navigation_data_.reset(); |
912 } | 897 } |
913 | 898 |
| 899 void NavigatorImpl::DidStartMainFrameNavigation( |
| 900 const GURL& url, |
| 901 SiteInstanceImpl* site_instance) { |
| 902 // If there is no browser-initiated pending entry for this navigation and it |
| 903 // is not for the error URL, create a pending entry using the current |
| 904 // SiteInstance, and ensure the address bar updates accordingly. We don't |
| 905 // know the referrer or extra headers at this point, but the referrer will |
| 906 // be set properly upon commit. |
| 907 NavigationEntryImpl* pending_entry = controller_->GetPendingEntry(); |
| 908 bool has_browser_initiated_pending_entry = |
| 909 pending_entry && !pending_entry->is_renderer_initiated(); |
| 910 if (!has_browser_initiated_pending_entry) { |
| 911 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( |
| 912 controller_->CreateNavigationEntry( |
| 913 url, content::Referrer(), ui::PAGE_TRANSITION_LINK, |
| 914 true /* is_renderer_initiated */, std::string(), |
| 915 controller_->GetBrowserContext())); |
| 916 entry->set_site_instance(site_instance); |
| 917 // TODO(creis): If there's a pending entry already, find a safe way to |
| 918 // update it instead of replacing it and copying over things like this. |
| 919 if (pending_entry) { |
| 920 entry->set_transferred_global_request_id( |
| 921 pending_entry->transferred_global_request_id()); |
| 922 entry->set_should_replace_entry(pending_entry->should_replace_entry()); |
| 923 entry->SetRedirectChain(pending_entry->GetRedirectChain()); |
| 924 } |
| 925 controller_->SetPendingEntry(entry); |
| 926 if (delegate_) |
| 927 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); |
| 928 } |
| 929 } |
| 930 |
914 } // namespace content | 931 } // namespace content |
OLD | NEW |