Index: content/browser/frame_host/navigation_controller_impl_browsertest.cc |
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc |
index 75b8e0912f53a6c5e14cc6c2b5eb865f4c7e22ed..d0c797accff73530650ccb7b55f8132b3edaa7e2 100644 |
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc |
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc |
@@ -1207,4 +1207,96 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
} |
} |
+namespace { |
+ |
+class FailureWatcher : public WebContentsObserver { |
+ public: |
+ // Observes failure for the specified |node|. |
+ explicit FailureWatcher(FrameTreeNode* node) |
+ : WebContentsObserver( |
+ node->current_frame_host()->delegate()->GetAsWebContents()), |
+ frame_tree_node_id_(node->frame_tree_node_id()), |
+ message_loop_runner_(new MessageLoopRunner) {} |
+ |
+ void Wait() { |
+ message_loop_runner_->Run(); |
+ } |
+ |
+ private: |
+ void DidFailLoad(RenderFrameHost* render_frame_host, |
+ const GURL& validated_url, |
+ int error_code, |
+ const base::string16& error_description) override { |
+ RenderFrameHostImpl* rfh = |
+ static_cast<RenderFrameHostImpl*>(render_frame_host); |
+ if (rfh->frame_tree_node()->frame_tree_node_id() != frame_tree_node_id_) |
+ return; |
+ |
+ message_loop_runner_->Quit(); |
+ } |
+ |
+ void DidFailProvisionalLoad( |
+ RenderFrameHost* render_frame_host, |
+ const GURL& validated_url, |
+ int error_code, |
+ const base::string16& error_description) override { |
+ RenderFrameHostImpl* rfh = |
+ static_cast<RenderFrameHostImpl*>(render_frame_host); |
+ if (rfh->frame_tree_node()->frame_tree_node_id() != frame_tree_node_id_) |
+ return; |
+ |
+ message_loop_runner_->Quit(); |
+ } |
+ |
+ // The id of the FrameTreeNode whose navigations to observe. |
+ int frame_tree_node_id_; |
+ |
+ // The MessageLoopRunner used to spin the message loop. |
+ scoped_refptr<MessageLoopRunner> message_loop_runner_; |
+}; |
+ |
+} // namespace |
+ |
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
+ StopCausesFailureDespiteJavaScriptURL) { |
+ NavigationControllerImpl& controller = |
+ static_cast<NavigationControllerImpl&>( |
+ shell()->web_contents()->GetController()); |
+ |
+ FrameTreeNode* root = |
+ static_cast<WebContentsImpl*>(shell()->web_contents())-> |
+ GetFrameTree()->root(); |
+ |
+ // Start with a normal page. |
+ GURL url1(embedded_test_server()->GetURL( |
+ "/navigation_controller/simple_page_1.html")); |
+ EXPECT_TRUE(NavigateToURL(shell(), url1)); |
+ |
+ // Have the user decide to go to a different page which is very slow. |
+ StallDelegate stall_delegate; |
+ ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate); |
+ GURL url2(embedded_test_server()->GetURL( |
+ "/navigation_controller/simple_page_2.html")); |
+ controller.LoadURL(url2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); |
+ |
+ // That should be the pending entry. |
+ NavigationEntryImpl* entry = controller.GetPendingEntry(); |
+ ASSERT_NE(nullptr, entry); |
+ EXPECT_EQ(url2, entry->GetURL()); |
+ |
+ // Loading a JavaScript URL shouldn't affect the ability to stop. |
+ { |
+ FailureWatcher watcher(root); |
+ GURL js("javascript:(function(){})()"); |
+ controller.LoadURL(js, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); |
+ // This LoadURL ends up purging the pending entry, which is why this is |
+ // tricky. |
+ EXPECT_EQ(nullptr, controller.GetPendingEntry()); |
+ shell()->web_contents()->Stop(); |
+ watcher.Wait(); |
+ } |
+ |
+ ResourceDispatcherHost::Get()->SetDelegate(nullptr); |
+} |
+ |
} // namespace content |