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 362f64cb03683179b02b3f5736da25e606c63d21..7adfe79445ace2bafe3760864f94fc0b1443dd3f 100644 |
--- a/content/browser/frame_host/navigator_impl.cc |
+++ b/content/browser/frame_host/navigator_impl.cc |
@@ -5,6 +5,7 @@ |
#include "content/browser/frame_host/navigator_impl.h" |
#include "base/command_line.h" |
+#include "content/browser/frame_host/frame_tree.h" |
#include "content/browser/frame_host/frame_tree_node.h" |
#include "content/browser/frame_host/navigation_controller_impl.h" |
#include "content/browser/frame_host/navigation_entry_impl.h" |
@@ -12,6 +13,7 @@ |
#include "content/browser/frame_host/render_frame_host_impl.h" |
#include "content/browser/renderer_host/render_view_host_impl.h" |
#include "content/browser/site_instance_impl.h" |
+#include "content/common/frame_messages.h" |
#include "content/public/browser/browser_context.h" |
#include "content/public/browser/invalidate_type.h" |
#include "content/public/browser/navigation_controller.h" |
@@ -91,4 +93,65 @@ void NavigatorImpl::DidStartProvisionalLoad( |
} |
} |
+ |
+void NavigatorImpl::DidFailProvisionalLoadWithError( |
+ RenderFrameHostImpl* render_frame_host, |
+ const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) { |
+ VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec() |
+ << ", error_code: " << params.error_code |
+ << ", error_description: " << params.error_description |
+ << ", is_main_frame: " << params.is_main_frame |
+ << ", showing_repost_interstitial: " << |
+ params.showing_repost_interstitial |
+ << ", frame_id: " << params.frame_id; |
+ GURL validated_url(params.url); |
+ RenderProcessHost* render_process_host = render_frame_host->GetProcess(); |
+ render_process_host->FilterURL(false, &validated_url); |
+ |
+ if (net::ERR_ABORTED == params.error_code) { |
+ // EVIL HACK ALERT! Ignore failed loads when we're showing interstitials. |
+ // This means that the interstitial won't be torn down properly, which is |
+ // bad. But if we have an interstitial, go back to another tab type, and |
+ // then load the same interstitial again, we could end up getting the first |
+ // interstitial's "failed" message (as a result of the cancel) when we're on |
+ // the second one. We can't tell this apart, so we think we're tearing down |
+ // the current page which will cause a crash later on. |
+ // |
+ // http://code.google.com/p/chromium/issues/detail?id=2855 |
+ // Because this will not tear down the interstitial properly, if "back" is |
+ // back to another tab type, the interstitial will still be somewhat alive |
+ // in the previous tab type. If you navigate somewhere that activates the |
+ // tab with the interstitial again, you'll see a flash before the new load |
+ // commits of the interstitial page. |
+ FrameTreeNode* root = |
+ render_frame_host->frame_tree_node()->frame_tree()->root(); |
+ if (root->render_manager()->interstitial_page() != NULL) { |
+ LOG(WARNING) << "Discarding message during interstitial."; |
+ return; |
+ } |
+ |
+ // We used to cancel the pending renderer here for cross-site downloads. |
+ // However, it's not safe to do that because the download logic repeatedly |
+ // looks for this WebContents based on a render ID. Instead, we just |
+ // leave the pending renderer around until the next navigation event |
+ // (Navigate, DidNavigate, etc), which will clean it up properly. |
+ // |
+ // TODO(creis): Find a way to cancel any pending RFH here. |
+ } |
+ |
+ // Do not usually clear the pending entry if one exists, so that the user's |
+ // typed URL is not lost when a navigation fails or is aborted. However, in |
+ // cases that we don't show the pending entry (e.g., renderer-initiated |
+ // navigations in an existing tab), we don't keep it around. That prevents |
+ // spoofs on in-page navigations that don't go through |
+ // DidStartProvisionalLoadForFrame. |
+ // In general, we 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. |
+ if (controller_->GetPendingEntry() != controller_->GetVisibleEntry()) |
+ controller_->DiscardPendingEntry(); |
+ |
+ delegate_->DidFailProvisionalLoadWithError(render_frame_host, params); |
+} |
+ |
} // namespace content |