Index: content/browser/web_contents/web_contents_impl_browsertest.cc |
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc |
index e4a8ee7f367df23e2460315cfaa446defacb7f75..616ea79f836ca5240ab2720cd8821fbcecc01732 100644 |
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc |
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc |
@@ -484,6 +484,7 @@ struct LoadProgressDelegateAndObserver : public WebContentsDelegate, |
public WebContentsObserver { |
LoadProgressDelegateAndObserver(Shell* shell) |
: WebContentsObserver(shell->web_contents()), |
+ subframe_rfh(nullptr), |
did_start_loading(false), |
did_stop_loading(false) { |
web_contents()->SetDelegate(this); |
@@ -491,6 +492,7 @@ struct LoadProgressDelegateAndObserver : public WebContentsDelegate, |
// WebContentsDelegate: |
void LoadProgressChanged(WebContents* source, double progress) override { |
+ DLOG(INFO) << "LoadProgressChanged"; |
EXPECT_TRUE(did_start_loading); |
EXPECT_FALSE(did_stop_loading); |
progresses.push_back(progress); |
@@ -498,10 +500,31 @@ struct LoadProgressDelegateAndObserver : public WebContentsDelegate, |
// WebContentsObserver: |
void DidStartLoading(RenderViewHost* render_view_host) override { |
+ DLOG(INFO) << "DidStartLoading for " << render_view_host->GetSiteInstance()->GetSiteURL(); |
EXPECT_FALSE(did_start_loading); |
EXPECT_EQ(0U, progresses.size()); |
EXPECT_FALSE(did_stop_loading); |
did_start_loading = true; |
+ |
+ // TODO(creis): Replace with a callback with a setter function. |
+ if (subframe_rfh) { |
+ DLOG(INFO) << "Forcing a stale DidStartLoading for " << subframe_rfh->GetSiteInstance()->GetSiteURL(); |
+ // Before the new navigation has a chance to commit, simulate a |
+ // DidStartLoading IPC from the old subframe RFH. |
+ FrameHostMsg_DidStartLoading subframe_start_msg( |
+ subframe_rfh->GetRoutingID(), true); |
+ static_cast<WebContentsImpl*>(web_contents())->OnMessageReceived( |
+ subframe_rfh, subframe_start_msg); |
+ |
+ // Also simulate a DidChangeLoadProgress, but not a DidStopLoading. |
+ FrameHostMsg_DidChangeLoadProgress progress_msg( |
+ subframe_rfh->GetRoutingID(), 1.0); |
+ static_cast<WebContentsImpl*>(web_contents())->OnMessageReceived( |
+ subframe_rfh, progress_msg); |
+ |
+ // Only do this once. |
+ subframe_rfh = nullptr; |
+ } |
} |
void DidStopLoading(RenderViewHost* render_view_host) override { |
@@ -511,6 +534,8 @@ struct LoadProgressDelegateAndObserver : public WebContentsDelegate, |
did_stop_loading = true; |
} |
+ // TODO(creis): Replace with a Callback. |
+ RenderFrameHost* subframe_rfh; |
bool did_start_loading; |
std::vector<double> progresses; |
bool did_stop_loading; |
@@ -600,6 +625,47 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, |
EXPECT_TRUE(delegate->did_stop_loading); |
} |
+// Ensure that a new navigation that interrupts a pending one will still fire |
+// a DidStopLoading. See http://crbug.com/429399. |
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, |
+ LoadProgressAfterStaleDidStart) { |
+ host_resolver()->AddRule("*", "127.0.0.1"); |
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
+ |
+ // Start at a real page with a subframe. |
+ DLOG(INFO) << "First nav"; |
+ NavigateToURL(shell(), embedded_test_server()->GetURL( |
+ "/frame_tree/page_with_one_frame.html")); |
+ FrameTree* frame_tree = |
+ static_cast<WebContentsImpl*>(shell()->web_contents())->GetFrameTree(); |
+ ASSERT_EQ(1U, frame_tree->root()->child_count()); |
+ RenderFrameHost* subframe_rfh = |
+ frame_tree->root()->child_at(0)->current_frame_host(); |
+ |
+ scoped_ptr<LoadProgressDelegateAndObserver> delegate( |
+ new LoadProgressDelegateAndObserver(shell())); |
+ |
+ // Now start a new cross-process navigation. |
+ TestNavigationObserver tab_observer(shell()->web_contents(), 1); |
+ GURL url(embedded_test_server()->GetURL("foo.com", "/title2.html")); |
+ DLOG(INFO) << "Second nav to " << url; |
+ shell()->LoadURL(url); |
+ |
+ // Do this after the fake DidStartLoading in RFH::Navigate, so that it runs |
+ // when the real DidStartLoading arrives from the old renderer. |
+ delegate->subframe_rfh = subframe_rfh; |
+ |
+ // The fake subframe DidStartLoading should have incremented |
+ // loading_frames_in_progress_... |
+ |
+ // Now complete the new navigation. |
+ tab_observer.Wait(); |
+ EXPECT_EQ(url, shell()->web_contents()->GetLastCommittedURL()); |
+ |
+ // We should have gotten to DidStopLoading. |
+ EXPECT_TRUE(delegate->did_stop_loading); |
+} |
+ |
struct FirstVisuallyNonEmptyPaintObserver : public WebContentsObserver { |
FirstVisuallyNonEmptyPaintObserver(Shell* shell) |
: WebContentsObserver(shell->web_contents()), |