Index: content/browser/frame_host/navigation_controller_impl.cc |
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc |
index 1e0e55b71fc212027d87e08368f5815c83eb9acf..c133a633181190a019af936a93be4a607c757ae6 100644 |
--- a/content/browser/frame_host/navigation_controller_impl.cc |
+++ b/content/browser/frame_host/navigation_controller_impl.cc |
@@ -162,6 +162,26 @@ bool ShouldTreatNavigationAsReload(const NavigationEntry* entry) { |
return false; |
} |
+// Returns true if the error code indicates an error condition that is not |
+// recoverable or navigation is blocked. In such cases, session history |
+// navigations to the same NavigationEntry should not attempt to load the |
+// original URL. |
+// TODO(nasko): Find a better way to distinguish blocked vs failed navigations, |
+// as this is a very hacky way of accomplishing this. For now, a handful of |
+// error codes are considered, which are more or less known to be cases of |
+// blocked navigations. |
+bool IsBlockedNavigation(net::Error error_code) { |
+ switch (error_code) { |
+ case net::ERR_BLOCKED_BY_CLIENT: |
+ case net::ERR_BLOCKED_BY_RESPONSE: |
+ case net::ERR_BLOCKED_BY_XSS_AUDITOR: |
+ case net::ERR_UNSAFE_REDIRECT: |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |
+ |
} // namespace |
// NavigationControllerImpl ---------------------------------------------------- |
@@ -933,6 +953,24 @@ bool NavigationControllerImpl::RendererDidNavigate( |
frame_entry->set_redirect_chain(params.redirects); |
} |
+ // When a navigation in the main frame is blocked, it will display an error |
+ // page. To avoid loading the blocked URL on back/forward navigations, |
+ // do not store it in the FrameNavigationEntry's URL or PageState. Instead, |
+ // make it visible to the user as the virtual URL. Store a safe URL |
+ // (about:blank) as the one to load if the entry is revisited. |
+ // TODO(nasko): Consider supporting similar behavior for subframe |
+ // navigations, including AUTO_SUBFRAME. |
+ if (!rfh->GetParent() && |
+ IsBlockedNavigation(navigation_handle->GetNetErrorCode())) { |
+ DCHECK(params.url_is_unreachable); |
+ active_entry->SetURL(GURL(url::kAboutBlankURL)); |
+ active_entry->SetVirtualURL(params.url); |
+ if (frame_entry) { |
+ frame_entry->SetPageState( |
+ PageState::CreateFromURL(active_entry->GetURL())); |
+ } |
+ } |
+ |
// Use histogram to track memory impact of redirect chain because it's now |
// not cleared for committed entries. |
size_t redirect_chain_size = 0; |