Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Side by Side Diff: content/browser/frame_host/navigator_impl.cc

Issue 1661423002: Solidify Entry discarding logic (NavigationHandle keeps its ID) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: creis review Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698