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

Unified Diff: content/browser/frame_host/navigator_impl.cc

Issue 1697563002: PlzNavigate: clear pending entry on aborted navigations (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/frame_host/navigator_impl.cc
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index baf2bcdb4c383096c4c14d1858a34ddb305befb7..5e33ea948ba39bddc3c137b822d662eb54cd7faf 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -204,44 +204,7 @@ void NavigatorImpl::DidFailProvisionalLoadWithError(
// TODO(creis): Find a way to cancel any pending RFH here.
}
- // Racy conditions can cause a fail message to arrive after its corresponding
- // pending entry has been replaced by another navigation. If
- // |DiscardPendingEntry| is called in this case, then the completely valid
- // entry for the new navigation would be discarded. See crbug.com/513742. To
- // catch this case, the current pending entry is compared against the current
- // navigation handle's entry id, which should correspond to the failed load.
- NavigationHandleImpl* handle = render_frame_host->navigation_handle();
- NavigationEntry* pending_entry = controller_->GetPendingEntry();
- bool pending_matches_fail_msg =
- handle && pending_entry &&
- handle->pending_nav_entry_id() == pending_entry->GetUniqueID();
- if (pending_matches_fail_msg) {
- // We usually clear the pending entry when it fails, so that an arbitrary
- // URL isn't left visible above a committed page. This must be enforced
- // when the pending entry isn't visible (e.g., renderer-initiated
- // navigations) to prevent URL spoofs for in-page navigations that don't go
- // through DidStartProvisionalLoadForFrame.
- //
- // However, we do preserve the pending entry in some cases, such as on the
- // initial navigation of an unmodified blank tab. We also allow the
- // delegate to say when it's safe to leave aborted URLs in the omnibox, to
- // let the user edit the URL and try again. This may be useful in cases
- // that the committed page cannot be attacker-controlled. In these cases,
- // we still allow the view to clear the pending entry and typed URL if the
- // user requests (e.g., hitting Escape with focus in the address bar).
- //
- // Note: don't touch the transient entry, since an interstitial may exist.
- bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() ||
- delegate_->ShouldPreserveAbortedURLs();
- if (pending_entry != controller_->GetVisibleEntry() ||
- !should_preserve_entry) {
- controller_->DiscardPendingEntry(true);
-
- // Also force the UI to refresh.
- controller_->delegate()->NotifyNavigationStateChanged(
- INVALIDATE_TYPE_URL);
- }
- }
+ DiscardPendingEntryOnFailureIfNeeded(render_frame_host->navigation_handle());
if (delegate_)
delegate_->DidFailProvisionalLoadWithError(render_frame_host, params);
@@ -917,6 +880,8 @@ void NavigatorImpl::FailedNavigation(FrameTreeNode* frame_tree_node,
NavigationRequest* navigation_request = frame_tree_node->navigation_request();
DCHECK(navigation_request);
+ DiscardPendingEntryOnFailureIfNeeded(navigation_request->navigation_handle());
+
// If the request was canceled by the user do not show an error page.
if (error_code == net::ERR_ABORTED) {
frame_tree_node->ResetNavigationRequest(false);
@@ -1121,4 +1086,45 @@ void NavigatorImpl::DidStartMainFrameNavigation(
}
}
+void NavigatorImpl::DiscardPendingEntryOnFailureIfNeeded(
+ NavigationHandleImpl* handle) {
+ // Racy conditions can cause a fail message to arrive after its corresponding
+ // pending entry has been replaced by another navigation. If
+ // |DiscardPendingEntry| is called in this case, then the completely valid
+ // entry for the new navigation would be discarded. See crbug.com/513742. To
+ // catch this case, the current pending entry is compared against the current
+ // navigation handle's entry id, which should correspond to the failed load.
+ NavigationEntry* pending_entry = controller_->GetPendingEntry();
+ bool pending_matches_fail_msg =
+ handle && pending_entry &&
+ handle->pending_nav_entry_id() == pending_entry->GetUniqueID();
+ if (!pending_matches_fail_msg)
+ return;
+
+ // We usually clear the pending entry when it fails, so that an arbitrary URL
+ // isn't left visible above a committed page. This must be enforced when the
+ // pending entry isn't visible (e.g., renderer-initiated navigations) to
+ // prevent URL spoofs for in-page navigations that don't go through
+ // DidStartProvisionalLoadForFrame.
+ //
+ // However, we do preserve the pending entry in some cases, such as on the
+ // initial navigation of an unmodified blank tab. We also allow the delegate
+ // to say when it's safe to leave aborted URLs in the omnibox, to let the
+ // user edit the URL and try again. This may be useful in cases that the
+ // committed page cannot be attacker-controlled. In these cases, we still
+ // allow the view to clear the pending entry and typed URL if the user
+ // requests (e.g., hitting Escape with focus in the address bar).
+ //
+ // Note: don't touch the transient entry, since an interstitial may exist.
+ bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() ||
+ delegate_->ShouldPreserveAbortedURLs();
+ if (pending_entry != controller_->GetVisibleEntry() ||
+ !should_preserve_entry) {
+ controller_->DiscardPendingEntry(true);
+
+ // Also force the UI to refresh.
+ controller_->delegate()->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
+ }
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698