Index: content/browser/web_contents/web_contents_impl_unittest.cc |
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc |
index 5e322ef3fe8fcad6d1c4bbe1a6d142d624119e6f..dfba4445ce83e7aaca117e2f6ce2bbef99f9b330 100644 |
--- a/content/browser/web_contents/web_contents_impl_unittest.cc |
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc |
@@ -2884,6 +2884,70 @@ TEST_F(WebContentsImplTest, StartStopEventsBalance) { |
EXPECT_FALSE(observer.is_loading()); |
} |
+// Ensure that WebContentsImpl does not stop loading too early when there still |
+// is a pending renderer. This can happen if a same-process non user-initiated |
+// navigation completes while there is an ongoing cross-process navigation. |
+// TODO(fdegans): Rewrite the test for PlzNavigate when DidStartLoading and |
+// DidStopLoading are properly called. |
+TEST_F(WebContentsImplTest, NoEarlyStop) { |
+ const GURL kUrl1("http://www.chromium.org"); |
+ const GURL kUrl2("http://www.google.com"); |
+ const GURL kUrl3("http://www.wikipedia.org"); |
+ |
+ contents()->NavigateAndCommit(kUrl1); |
+ |
+ TestRenderFrameHost* current_rfh = contents()->GetMainFrame(); |
+ |
+ // Start a browser-initiated cross-process navigation to |kUrl2|. There should |
+ // be a pending RenderFrameHost and the WebContents should be loading. |
+ controller().LoadURL( |
+ kUrl2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); |
+ EXPECT_TRUE(contents()->cross_navigation_pending()); |
+ TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame(); |
+ ASSERT_TRUE(pending_rfh); |
+ EXPECT_TRUE(contents()->IsLoading()); |
+ |
+ // The current RenderFrameHost starts a non user-initiated render-initiated |
+ // navigation and sends a DidStartLoading IPC. The WebContents should still be |
+ // loading. |
+ current_rfh->OnMessageReceived( |
+ FrameHostMsg_DidStartLoading(current_rfh->GetRoutingID(), false)); |
+ EXPECT_TRUE(contents()->IsLoading()); |
+ |
+ // Simulate the pending RenderFrameHost DidStartLoading. There should still be |
+ // a pending RenderFrameHost and the WebContents should still be loading. |
+ pending_rfh->PrepareForCommit(); |
+ pending_rfh->OnMessageReceived( |
+ FrameHostMsg_DidStartLoading(pending_rfh->GetRoutingID(), false)); |
+ EXPECT_EQ(contents()->GetPendingMainFrame(), pending_rfh); |
+ EXPECT_TRUE(contents()->IsLoading()); |
+ |
+ // Simulate the commit and DidStopLoading from the renderer-initiated |
+ // navigation in the current RenderFrameHost. There should still be a pending |
+ // RenderFrameHost and the WebContents should still be loading. |
+ current_rfh->SendNavigate(1, kUrl3); |
+ current_rfh->OnMessageReceived( |
+ FrameHostMsg_DidStopLoading(current_rfh->GetRoutingID())); |
+ EXPECT_EQ(contents()->GetPendingMainFrame(), pending_rfh); |
+ EXPECT_TRUE(contents()->IsLoading()); |
+ |
+ // Commit the navigation. The formerly pending RenderFrameHost should now be |
+ // the current RenderFrameHost and the WebContents should still be loading. |
+ contents()->TestDidNavigate(pending_rfh, 1, kUrl2, |
+ ui::PAGE_TRANSITION_TYPED); |
+ EXPECT_FALSE(contents()->GetPendingMainFrame()); |
+ TestRenderFrameHost* new_current_rfh = contents()->GetMainFrame(); |
+ EXPECT_EQ(new_current_rfh, pending_rfh); |
+ EXPECT_TRUE(contents()->IsLoading()); |
+ |
+ // Simulate the new current RenderFrameHost DidStopLoading. The WebContents |
+ // should now have stopped loading. |
+ new_current_rfh->OnMessageReceived( |
+ FrameHostMsg_DidStopLoading(new_current_rfh->GetRoutingID())); |
+ EXPECT_EQ(contents()->GetMainFrame(), new_current_rfh); |
+ EXPECT_FALSE(contents()->IsLoading()); |
+} |
+ |
TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) { |
// PlayerIDs are actually pointers cast to int64, so verify that both negative |
// and positive player ids don't blow up. |