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

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: nav id hack for data navs with base url 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 render_frame_host->navigation_handle()->set_is_transferring(false); 144 render_frame_host->navigation_handle()->set_is_transferring(false);
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 NavigationEntry* pending_entry = controller_->GetPendingEntry();
154 render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create( 155 render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create(
155 validated_url, render_frame_host->frame_tree_node(), navigation_start)); 156 validated_url, render_frame_host->frame_tree_node(), navigation_start,
157 pending_entry ? pending_entry->GetUniqueID() : 0));
156 } 158 }
157 159
158 void NavigatorImpl::DidFailProvisionalLoadWithError( 160 void NavigatorImpl::DidFailProvisionalLoadWithError(
159 RenderFrameHostImpl* render_frame_host, 161 RenderFrameHostImpl* render_frame_host,
160 const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) { 162 const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
161 VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec() 163 VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec()
162 << ", error_code: " << params.error_code 164 << ", error_code: " << params.error_code
163 << ", error_description: " << params.error_description 165 << ", error_description: " << params.error_description
164 << ", showing_repost_interstitial: " << 166 << ", showing_repost_interstitial: " <<
165 params.showing_repost_interstitial 167 params.showing_repost_interstitial
(...skipping 19 matching lines...) Expand all
185 // commits of the interstitial page. 187 // commits of the interstitial page.
186 FrameTreeNode* root = 188 FrameTreeNode* root =
187 render_frame_host->frame_tree_node()->frame_tree()->root(); 189 render_frame_host->frame_tree_node()->frame_tree()->root();
188 if (root->render_manager()->interstitial_page() != NULL) { 190 if (root->render_manager()->interstitial_page() != NULL) {
189 LOG(WARNING) << "Discarding message during interstitial."; 191 LOG(WARNING) << "Discarding message during interstitial.";
190 return; 192 return;
191 } 193 }
192 194
193 // We used to cancel the pending renderer here for cross-site downloads. 195 // 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 196 // 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 197 // looks for this WebContents based on a render ID. Instead, we just
196 // leave the pending renderer around until the next navigation event 198 // leave the pending renderer around until the next navigation event
197 // (Navigate, DidNavigate, etc), which will clean it up properly. 199 // (Navigate, DidNavigate, etc), which will clean it up properly.
198 // 200 //
199 // TODO(creis): Find a way to cancel any pending RFH here. 201 // TODO(creis): Find a way to cancel any pending RFH here.
200 } 202 }
201 203
202 // We usually clear the pending entry when it fails, so that an arbitrary URL 204 // Racy conditions can cause a fail message to arrive after its corresponding
203 // isn't left visible above a committed page. This must be enforced when 205 // pending entry has been replaced by another navigation. If
204 // the pending entry isn't visible (e.g., renderer-initiated navigations) to 206 // |DiscardPendingEntry| is called in this case, then the completely valid
205 // prevent URL spoofs for in-page navigations that don't go through 207 // entry for the new navigation would be discarded. See crbug.com/513742. To
206 // DidStartProvisionalLoadForFrame. 208 // catch this case, the current pending entry is compared against the current
207 // 209 // navigation handle's entry id, which should correspond to the failed load.
208 // However, we do preserve the pending entry in some cases, such as on the 210 NavigationHandleImpl* handle = render_frame_host->navigation_handle();
209 // initial navigation of an unmodified blank tab. We also allow the delegate 211 NavigationEntry* pending_entry = controller_->GetPendingEntry();
210 // to say when it's safe to leave aborted URLs in the omnibox, to let the user 212 bool pending_matches_fail_msg =
211 // edit the URL and try again. This may be useful in cases that the committed 213 handle && pending_entry &&
212 // page cannot be attacker-controlled. In these cases, we still allow the 214 handle->pending_nav_entry_id() == pending_entry->GetUniqueID();
213 // view to clear the pending entry and typed URL if the user requests 215 if (pending_matches_fail_msg) {
214 // (e.g., hitting Escape with focus in the address bar). 216 // We usually clear the pending entry when it fails, so that an arbitrary
215 // 217 // URL isn't left visible above a committed page. This must be enforced
216 // Note: don't touch the transient entry, since an interstitial may exist. 218 // when the pending entry isn't visible (e.g., renderer-initiated
217 bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() || 219 // navigations) to prevent URL spoofs for in-page navigations that don't go
218 delegate_->ShouldPreserveAbortedURLs(); 220 // through DidStartProvisionalLoadForFrame.
219 if (controller_->GetPendingEntry() != controller_->GetVisibleEntry() || 221 //
220 !should_preserve_entry) { 222 // However, we do preserve the pending entry in some cases, such as on the
221 controller_->DiscardPendingEntry(true); 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. The pending entry is guaranteed to be
809 // non null at this point.
810 DCHECK(controller_->GetPendingEntry());
811 navigation_request->CreateNavigationHandle(
812 controller_->GetPendingEntry()->GetUniqueID());
792 navigation_request->BeginNavigation(); 813 navigation_request->BeginNavigation();
793 } 814 }
794 815
795 // PlzNavigate 816 // PlzNavigate
796 void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node, 817 void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node,
797 ResourceResponse* response, 818 ResourceResponse* response,
798 scoped_ptr<StreamHandle> body) { 819 scoped_ptr<StreamHandle> body) {
799 CHECK(IsBrowserSideNavigationEnabled()); 820 CHECK(IsBrowserSideNavigationEnabled());
800 821
801 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); 822 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 = 955 bool should_dispatch_beforeunload =
935 frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(); 956 frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload();
936 FrameMsg_Navigate_Type::Value navigation_type = 957 FrameMsg_Navigate_Type::Value navigation_type =
937 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type); 958 GetNavigationType(controller_->GetBrowserContext(), entry, reload_type);
938 frame_tree_node->CreatedNavigationRequest( 959 frame_tree_node->CreatedNavigationRequest(
939 NavigationRequest::CreateBrowserInitiated( 960 NavigationRequest::CreateBrowserInitiated(
940 frame_tree_node, dest_url, dest_referrer, frame_entry, entry, 961 frame_tree_node, dest_url, dest_referrer, frame_entry, entry,
941 navigation_type, is_same_document_history_load, navigation_start, 962 navigation_type, is_same_document_history_load, navigation_start,
942 controller_)); 963 controller_));
943 NavigationRequest* navigation_request = frame_tree_node->navigation_request(); 964 NavigationRequest* navigation_request = frame_tree_node->navigation_request();
944 navigation_request->CreateNavigationHandle(); 965 navigation_request->CreateNavigationHandle(entry.GetUniqueID());
945 966
946 // Have the current renderer execute its beforeunload event if needed. If it 967 // 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 968 // is not needed (when beforeunload dispatch is not needed or this navigation
948 // is synchronous and same-site) then NavigationRequest::BeginNavigation 969 // is synchronous and same-site) then NavigationRequest::BeginNavigation
949 // should be directly called instead. 970 // should be directly called instead.
950 if (should_dispatch_beforeunload && 971 if (should_dispatch_beforeunload &&
951 ShouldMakeNetworkRequestForURL( 972 ShouldMakeNetworkRequestForURL(
952 navigation_request->common_params().url)) { 973 navigation_request->common_params().url)) {
953 navigation_request->SetWaitingForRendererResponse(); 974 navigation_request->SetWaitingForRendererResponse();
954 frame_tree_node->current_frame_host()->DispatchBeforeUnload(true); 975 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()); 1059 entry->set_should_replace_entry(pending_entry->should_replace_entry());
1039 entry->SetRedirectChain(pending_entry->GetRedirectChain()); 1060 entry->SetRedirectChain(pending_entry->GetRedirectChain());
1040 } 1061 }
1041 controller_->SetPendingEntry(std::move(entry)); 1062 controller_->SetPendingEntry(std::move(entry));
1042 if (delegate_) 1063 if (delegate_)
1043 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); 1064 delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL);
1044 } 1065 }
1045 } 1066 }
1046 1067
1047 } // namespace content 1068 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698