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/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 return; | 145 return; |
146 } | 146 } |
147 | 147 |
148 // This ensures that notifications about the end of the previous | 148 // This ensures that notifications about the end of the previous |
149 // navigation are sent before notifications about the start of the | 149 // navigation are sent before notifications about the start of the |
150 // new navigation. | 150 // new navigation. |
151 render_frame_host->SetNavigationHandle(scoped_ptr<NavigationHandleImpl>()); | 151 render_frame_host->SetNavigationHandle(scoped_ptr<NavigationHandleImpl>()); |
152 } | 152 } |
153 | 153 |
154 render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create( | 154 render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create( |
155 validated_url, render_frame_host->frame_tree_node(), navigation_start)); | 155 validated_url, render_frame_host->frame_tree_node(), navigation_start, |
156 controller_->GetPendingEntry())); | |
156 } | 157 } |
157 | 158 |
158 void NavigatorImpl::DidFailProvisionalLoadWithError( | 159 void NavigatorImpl::DidFailProvisionalLoadWithError( |
159 RenderFrameHostImpl* render_frame_host, | 160 RenderFrameHostImpl* render_frame_host, |
160 const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) { | 161 const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) { |
161 VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec() | 162 VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec() |
162 << ", error_code: " << params.error_code | 163 << ", error_code: " << params.error_code |
163 << ", error_description: " << params.error_description | 164 << ", error_description: " << params.error_description |
164 << ", showing_repost_interstitial: " << | 165 << ", showing_repost_interstitial: " << |
165 params.showing_repost_interstitial | 166 params.showing_repost_interstitial |
(...skipping 26 matching lines...) Expand all Loading... | |
192 | 193 |
193 // We used to cancel the pending renderer here for cross-site downloads. | 194 // We used to cancel the pending renderer here for cross-site downloads. |
194 // However, it's not safe to do that because the download logic repeatedly | 195 // However, it's not safe to do that because the download logic repeatedly |
195 // looks for this WebContents based on a render ID. Instead, we just | 196 // looks for this WebContents based on a render ID. Instead, we just |
196 // leave the pending renderer around until the next navigation event | 197 // leave the pending renderer around until the next navigation event |
197 // (Navigate, DidNavigate, etc), which will clean it up properly. | 198 // (Navigate, DidNavigate, etc), which will clean it up properly. |
198 // | 199 // |
199 // TODO(creis): Find a way to cancel any pending RFH here. | 200 // TODO(creis): Find a way to cancel any pending RFH here. |
200 } | 201 } |
201 | 202 |
202 // We usually clear the pending entry when it fails, so that an arbitrary URL | 203 NavigationHandleImpl* handle = render_frame_host->navigation_handle(); |
Charlie Reis
2016/02/06 00:54:58
nit: Please put these declarations below the big c
Charlie Harrison
2016/02/08 15:06:42
Done.
| |
203 // isn't left visible above a committed page. This must be enforced when | 204 NavigationEntry* pending_entry = controller_->GetPendingEntry(); |
204 // the pending entry isn't visible (e.g., renderer-initiated navigations) to | 205 bool pending_matches_fail_msg = |
205 // prevent URL spoofs for in-page navigations that don't go through | 206 handle && pending_entry && |
206 // DidStartProvisionalLoadForFrame. | 207 handle->pending_nav_entry_id() == pending_entry->GetUniqueID(); |
207 // | 208 // Another complicated case here is the fact that racy conditions can cause a |
Charlie Reis
2016/02/06 00:54:58
nit: Drop "Another complicated case here is the fa
Charlie Harrison
2016/02/08 15:06:42
Done.
| |
208 // However, we do preserve the pending entry in some cases, such as on the | 209 // fail message to arrive after its corresponding pending entry has been |
209 // initial navigation of an unmodified blank tab. We also allow the delegate | 210 // replaced by another navigation. If |DiscardPendingEntry| is called in this |
210 // to say when it's safe to leave aborted URLs in the omnibox, to let the user | 211 // case, then the completely valid entry for the new navigation would be |
211 // edit the URL and try again. This may be useful in cases that the committed | 212 // discarded. See crbug.com/513742. To catch this case, the current pending |
212 // page cannot be attacker-controlled. In these cases, we still allow the | 213 // entry is compared against the current navigation handle's entry id, which |
213 // view to clear the pending entry and typed URL if the user requests | 214 // should correspond to the failed load. |
214 // (e.g., hitting Escape with focus in the address bar). | 215 if (pending_matches_fail_msg) { |
Charlie Reis
2016/02/06 00:54:58
Sanity check: I'm a bit nervous about unintentiona
| |
215 // | 216 // We usually clear the pending entry when it fails, so that an arbitrary |
216 // Note: don't touch the transient entry, since an interstitial may exist. | 217 // URL isn't left visible above a committed page. This must be enforced |
217 bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() || | 218 // when the pending entry isn't visible (e.g., renderer-initiated |
218 delegate_->ShouldPreserveAbortedURLs(); | 219 // navigations) to prevent URL spoofs for in-page navigations that don't go |
219 if (controller_->GetPendingEntry() != controller_->GetVisibleEntry() || | 220 // through DidStartProvisionalLoadForFrame. |
220 !should_preserve_entry) { | 221 // |
221 controller_->DiscardPendingEntry(true); | 222 // However, we do preserve the pending entry in some cases, such as on the |
223 // initial navigation of an unmodified blank tab. We also allow the | |
224 // delegate to say when it's safe to leave aborted URLs in the omnibox, to | |
225 // let the user edit the URL and try again. This may be useful in cases | |
226 // that the committed page cannot be attacker-controlled. In these cases, | |
227 // we still allow the view to clear the pending entry and typed URL if the | |
228 // user requests (e.g., hitting Escape with focus in the address bar). | |
229 // | |
230 // Note: don't touch the transient entry, since an interstitial may exist. | |
231 bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() || | |
232 delegate_->ShouldPreserveAbortedURLs(); | |
233 if (pending_entry != controller_->GetVisibleEntry() || | |
234 !should_preserve_entry) { | |
235 controller_->DiscardPendingEntry(true); | |
222 | 236 |
223 // Also force the UI to refresh. | 237 // Also force the UI to refresh. |
224 controller_->delegate()->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL); | 238 controller_->delegate()->NotifyNavigationStateChanged( |
239 INVALIDATE_TYPE_URL); | |
240 } | |
225 } | 241 } |
226 | 242 |
227 if (delegate_) | 243 if (delegate_) |
228 delegate_->DidFailProvisionalLoadWithError(render_frame_host, params); | 244 delegate_->DidFailProvisionalLoadWithError(render_frame_host, params); |
229 } | 245 } |
230 | 246 |
231 void NavigatorImpl::DidFailLoadWithError( | 247 void NavigatorImpl::DidFailLoadWithError( |
232 RenderFrameHostImpl* render_frame_host, | 248 RenderFrameHostImpl* render_frame_host, |
233 const GURL& url, | 249 const GURL& url, |
234 int error_code, | 250 int error_code, |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
766 } | 782 } |
767 | 783 |
768 // In all other cases the current navigation, if any, is canceled and a new | 784 // In all other cases the current navigation, if any, is canceled and a new |
769 // NavigationRequest is created for the node. | 785 // NavigationRequest is created for the node. |
770 frame_tree_node->CreatedNavigationRequest( | 786 frame_tree_node->CreatedNavigationRequest( |
771 NavigationRequest::CreateRendererInitiated( | 787 NavigationRequest::CreateRendererInitiated( |
772 frame_tree_node, common_params, begin_params, body, | 788 frame_tree_node, common_params, begin_params, body, |
773 controller_->GetLastCommittedEntryIndex(), | 789 controller_->GetLastCommittedEntryIndex(), |
774 controller_->GetEntryCount())); | 790 controller_->GetEntryCount())); |
775 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | 791 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
776 navigation_request->CreateNavigationHandle(); | |
777 | |
778 if (frame_tree_node->IsMainFrame()) { | 792 if (frame_tree_node->IsMainFrame()) { |
779 // Renderer-initiated main-frame navigations that need to swap processes | 793 // Renderer-initiated main-frame navigations that need to swap processes |
780 // will go to the browser via a OpenURL call, and then be handled by the | 794 // will go to the browser via a OpenURL call, and then be handled by the |
781 // same code path as browser-initiated navigations. For renderer-initiated | 795 // same code path as browser-initiated navigations. For renderer-initiated |
782 // main frame navigation that start via a BeginNavigation IPC, the | 796 // main frame navigation that start via a BeginNavigation IPC, the |
783 // RenderFrameHost will not be swapped. Therefore it is safe to call | 797 // RenderFrameHost will not be swapped. Therefore it is safe to call |
784 // DidStartMainFrameNavigation with the SiteInstance from the current | 798 // DidStartMainFrameNavigation with the SiteInstance from the current |
785 // RenderFrameHost. | 799 // RenderFrameHost. |
786 DidStartMainFrameNavigation( | 800 DidStartMainFrameNavigation( |
787 common_params.url, | 801 common_params.url, |
788 frame_tree_node->current_frame_host()->GetSiteInstance()); | 802 frame_tree_node->current_frame_host()->GetSiteInstance()); |
789 navigation_data_.reset(); | 803 navigation_data_.reset(); |
790 } | 804 } |
791 | 805 |
806 // The NavigationHandle must be created after the call to | |
807 // |DidStartMainFrameNavigation|, so it receives the most up to date pending | |
808 // entry from the NavigationController. | |
809 navigation_request->CreateNavigationHandle(controller_->GetPendingEntry()); | |
792 navigation_request->BeginNavigation(); | 810 navigation_request->BeginNavigation(); |
793 } | 811 } |
794 | 812 |
795 // PlzNavigate | 813 // PlzNavigate |
796 void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node, | 814 void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node, |
797 ResourceResponse* response, | 815 ResourceResponse* response, |
798 scoped_ptr<StreamHandle> body) { | 816 scoped_ptr<StreamHandle> body) { |
799 CHECK(IsBrowserSideNavigationEnabled()); | 817 CHECK(IsBrowserSideNavigationEnabled()); |
800 | 818 |
801 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | 819 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
934 bool should_dispatch_beforeunload = | 952 bool should_dispatch_beforeunload = |
935 frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(); | 953 frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(); |
936 FrameMsg_Navigate_Type::Value navigation_type = | 954 FrameMsg_Navigate_Type::Value navigation_type = |
937 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); | 955 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); |
938 frame_tree_node->CreatedNavigationRequest( | 956 frame_tree_node->CreatedNavigationRequest( |
939 NavigationRequest::CreateBrowserInitiated( | 957 NavigationRequest::CreateBrowserInitiated( |
940 frame_tree_node, dest_url, dest_referrer, frame_entry, entry, | 958 frame_tree_node, dest_url, dest_referrer, frame_entry, entry, |
941 navigation_type, is_same_document_history_load, navigation_start, | 959 navigation_type, is_same_document_history_load, navigation_start, |
942 controller_)); | 960 controller_)); |
943 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); | 961 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); |
944 navigation_request->CreateNavigationHandle(); | 962 navigation_request->CreateNavigationHandle(&entry); |
945 | 963 |
946 // Have the current renderer execute its beforeunload event if needed. If it | 964 // Have the current renderer execute its beforeunload event if needed. If it |
947 // is not needed (when beforeunload dispatch is not needed or this navigation | 965 // is not needed (when beforeunload dispatch is not needed or this navigation |
948 // is synchronous and same-site) then NavigationRequest::BeginNavigation | 966 // is synchronous and same-site) then NavigationRequest::BeginNavigation |
949 // should be directly called instead. | 967 // should be directly called instead. |
950 if (should_dispatch_beforeunload && | 968 if (should_dispatch_beforeunload && |
951 ShouldMakeNetworkRequestForURL( | 969 ShouldMakeNetworkRequestForURL( |
952 navigation_request->common_params().url)) { | 970 navigation_request->common_params().url)) { |
953 navigation_request->SetWaitingForRendererResponse(); | 971 navigation_request->SetWaitingForRendererResponse(); |
954 frame_tree_node->current_frame_host()->DispatchBeforeUnload(true); | 972 frame_tree_node->current_frame_host()->DispatchBeforeUnload(true); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1038 entry->set_should_replace_entry(pending_entry->should_replace_entry()); | 1056 entry->set_should_replace_entry(pending_entry->should_replace_entry()); |
1039 entry->SetRedirectChain(pending_entry->GetRedirectChain()); | 1057 entry->SetRedirectChain(pending_entry->GetRedirectChain()); |
1040 } | 1058 } |
1041 controller_->SetPendingEntry(std::move(entry)); | 1059 controller_->SetPendingEntry(std::move(entry)); |
1042 if (delegate_) | 1060 if (delegate_) |
1043 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); | 1061 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); |
1044 } | 1062 } |
1045 } | 1063 } |
1046 | 1064 |
1047 } // namespace content | 1065 } // namespace content |
OLD | NEW |