Chromium Code Reviews| Index: chrome/browser/prerender/prerender_browsertest.cc |
| diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc |
| index 6cc1560451a935f9a8a37d857578f8482d0f8f8d..f57053e0131e62e82a267d3ded29dd9abf7923f8 100644 |
| --- a/chrome/browser/prerender/prerender_browsertest.cc |
| +++ b/chrome/browser/prerender/prerender_browsertest.cc |
| @@ -744,8 +744,10 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
| OpenDestURLWithJSImpl("WindowOpen()"); |
| } |
| - void RemoveLinkElementsAndNavigate() const { |
| - OpenDestURLWithJSImpl("RemoveLinkElementsAndNavigate()"); |
| + void RemoveLinkElements() const { |
| + chrome::GetActiveWebContents(current_browser())->GetRenderViewHost()-> |
| + ExecuteJavascriptInWebFrame(string16(), |
| + ASCIIToUTF16("RemoveLinkElements()")); |
| } |
| void ClickToNextPageAfterPrerender() { |
| @@ -850,12 +852,39 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
| return prerender_link_manager; |
| } |
| - // Asserting on this can result in flaky tests. PrerenderHandles are only |
| - // removed from the PrerenderLinkManager when the prerenders are cancelled |
| - // from the renderer process, or the channel for the renderer process is |
| - // closed on the IO thread. In the latter case, the code must be careful to |
| - // wait for the channel to close, as it is done asynchronously after swapping |
| - // out the old process. See ChannelDestructionWatcher. |
| + bool DidReceivePrerenderStartEventForLinkNumber(int index) const { |
| + bool received_prerender_started; |
| + std::wstring expression = base::StringPrintf( |
| + L"window.domAutomationController.send(Boolean(" |
| + L"receivedPrerenderStartEvents[%d]))", index); |
| + |
| + CHECK(content::ExecuteJavaScriptAndExtractBool( |
| + chrome::GetActiveWebContents(current_browser())->GetRenderViewHost(), |
| + L"", expression, |
| + &received_prerender_started)); |
| + return received_prerender_started; |
| + } |
| + |
| + bool DidReceivePrerenderStopEventForLinkNumber(int index) const { |
| + bool received_prerender_stopped; |
| + std::wstring expression = base::StringPrintf( |
| + L"window.domAutomationController.send(Boolean(" |
| + L"receivedPrerenderStopEvents[%d]))", index); |
| + |
| + CHECK(content::ExecuteJavaScriptAndExtractBool( |
| + chrome::GetActiveWebContents(current_browser())->GetRenderViewHost(), |
| + L"", expression, |
| + &received_prerender_stopped)); |
| + return received_prerender_stopped; |
| + } |
| + |
| + // Asserting on this can result in flaky tests. PrerenderHandles are |
| + // removed from the PrerenderLinkManager when the prerender is canceled from |
| + // the browser, when the prerenders are cancelled from the renderer process, |
| + // or the channel for the renderer process is closed on the IO thread. In the |
| + // last case, the code must be careful to wait for the channel to close, as it |
| + // is done asynchronously after swapping out the old process. See |
| + // ChannelDestructionWatcher. |
| bool IsEmptyPrerenderLinkManager() const { |
| return GetPrerenderLinkManager()->IsEmpty(); |
| } |
| @@ -879,14 +908,18 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
| } |
| #endif |
| - TestPrerenderContents* GetPrerenderContents() const { |
| + TestPrerenderContents* GetPrerenderContentsFor(const GURL& url) const { |
| PrerenderManager::PrerenderData* prerender_data = |
| GetPrerenderManager()->FindPrerenderData( |
| - dest_url_, GetSessionStorageNamespace()); |
| + url, GetSessionStorageNamespace()); |
| return static_cast<TestPrerenderContents*>( |
| prerender_data ? prerender_data->contents() : NULL); |
| } |
| + TestPrerenderContents* GetPrerenderContents() const { |
| + return GetPrerenderContentsFor(dest_url_); |
| + } |
| + |
| void set_loader_path(const std::string& path) { |
| loader_path_ = path; |
| } |
| @@ -994,7 +1027,7 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
| TestPrerenderContents* prerender_contents = GetPrerenderContents(); |
| if (ShouldRenderPrerenderedPageCorrectly(expected_final_status)) { |
| - ASSERT_TRUE(prerender_contents != NULL); |
| + ASSERT_NE(static_cast<PrerenderContents*>(NULL), prerender_contents); |
| EXPECT_EQ(FINAL_STATUS_MAX, prerender_contents->final_status()); |
| if (call_javascript_ && expected_number_of_loads > 0) { |
| @@ -1022,9 +1055,9 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
| void NavigateToURLImpl(const GURL& dest_url, |
| WindowOpenDisposition disposition) const { |
| - ASSERT_TRUE(GetPrerenderManager() != NULL); |
| + ASSERT_NE(static_cast<PrerenderManager*>(NULL), GetPrerenderManager()); |
| // Make sure in navigating we have a URL to use in the PrerenderManager. |
| - ASSERT_TRUE(GetPrerenderContents() != NULL); |
| + ASSERT_NE(static_cast<PrerenderContents*>(NULL), GetPrerenderContents()); |
| // If opening the page in a background tab, it won't be shown when swapped |
| // in. |
| @@ -1055,7 +1088,7 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
| ui_test_utils::BROWSER_TEST_NONE); |
| // Make sure the PrerenderContents found earlier was used or removed. |
| - EXPECT_TRUE(GetPrerenderContents() == NULL); |
| + EXPECT_EQ(static_cast<PrerenderContents*>(NULL), GetPrerenderContents()); |
| if (call_javascript_ && web_contents) { |
| if (page_load_observer.get()) |
| @@ -1076,7 +1109,7 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
| void OpenDestURLWithJSImpl(const std::string& javascript_function_name) |
| const { |
| TestPrerenderContents* prerender_contents = GetPrerenderContents(); |
| - ASSERT_TRUE(prerender_contents != NULL); |
| + ASSERT_NE(static_cast<PrerenderContents*>(NULL), prerender_contents); |
| RenderViewHost* render_view_host = |
| chrome::GetActiveWebContents(current_browser())->GetRenderViewHost(); |
| @@ -1085,8 +1118,8 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
| string16(), ASCIIToUTF16(javascript_function_name)); |
| if (prerender_contents->quit_message_loop_on_destruction()) { |
| - // Run message loop until the prerender contents is destroyed. |
| - content::RunMessageLoop(); |
| + // Run message loop until the prerender contents is destroyed. |
| + content::RunMessageLoop(); |
| } else { |
| // We don't expect to pick up a running prerender, so instead |
| // observe one navigation. |
| @@ -1127,16 +1160,78 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPage) { |
| ASSERT_TRUE(IsEmptyPrerenderLinkManager()); |
| } |
| +// Checks that pending prerenders launch and receive proper event treatment. |
| +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPagePending) { |
| + std::deque<FinalStatus> expected_final_status_queue; |
| + expected_final_status_queue.push_back(FINAL_STATUS_USED); |
| + expected_final_status_queue.push_back(FINAL_STATUS_USED); |
| + PrerenderTestURL("files/prerender/prerender_page_pending.html", |
| + expected_final_status_queue, 1); |
| + |
| + ChannelDestructionWatcher first_channel_close_watcher; |
| + |
| + first_channel_close_watcher.WatchChannel( |
| + chrome::GetActiveWebContents(browser())->GetRenderProcessHost()); |
| + NavigateToDestURL(); |
| + // NavigateToDestURL doesn't run a message loop. Normally that's fine, but in |
| + // this case, we need the pending prerenders to start. |
| + content::RunMessageLoop(); |
| + first_channel_close_watcher.WaitForChannelClose(); |
| + |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); |
| + |
| + const GURL prerender_page_url = |
| + test_server()->GetURL("files/prerender/prerender_page.html"); |
| + EXPECT_FALSE(IsEmptyPrerenderLinkManager()); |
| + EXPECT_NE(static_cast<TestPrerenderContents*>(NULL), |
| + GetPrerenderContentsFor(prerender_page_url)); |
| + |
| + // Now navigate to our target page. |
| + ChannelDestructionWatcher second_channel_close_watcher; |
| + second_channel_close_watcher.WatchChannel( |
| + chrome::GetActiveWebContents(browser())->GetRenderProcessHost()); |
| + ui_test_utils::NavigateToURLWithDisposition( |
| + current_browser(), prerender_page_url, CURRENT_TAB, |
| + ui_test_utils::BROWSER_TEST_NONE); |
| + second_channel_close_watcher.WaitForChannelClose(); |
| + |
| + EXPECT_TRUE(IsEmptyPrerenderLinkManager()); |
| +} |
| + |
| +// Checks that pending prerenders which are canceled before they are launched |
| +// never get started. |
| +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageRemovesPending) { |
| + PrerenderTestURL("files/prerender/prerender_page_removes_pending.html", |
| + FINAL_STATUS_USED, 1); |
| + |
| + ChannelDestructionWatcher channel_close_watcher; |
| + channel_close_watcher.WatchChannel( |
| + chrome::GetActiveWebContents(browser())->GetRenderProcessHost()); |
| + NavigateToDestURL(); |
| + channel_close_watcher.WaitForChannelClose(); |
| + |
| + EXPECT_FALSE(DidReceivePrerenderStartEventForLinkNumber(1)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); |
| + |
| + ASSERT_TRUE(IsEmptyPrerenderLinkManager()); |
| +} |
| + |
| IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageRemovingLink) { |
| set_loader_path("files/prerender/prerender_loader_removing_links.html"); |
| set_loader_query_and_fragment("?links_to_insert=1&links_to_remove=1"); |
| PrerenderTestURL("files/prerender/prerender_page.html", |
| FINAL_STATUS_CANCELLED, 1); |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); |
| + |
| // No ChannelDestructionWatcher is needed here, since prerenders in the |
| // PrerenderLinkManager should be deleted by removing the links, rather than |
| // shutting down the renderer process. |
| - RemoveLinkElementsAndNavigate(); |
| - ASSERT_TRUE(IsEmptyPrerenderLinkManager()); |
| + RemoveLinkElements(); |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); |
| + EXPECT_TRUE(IsEmptyPrerenderLinkManager()); |
|
mmenke
2012/12/17 17:08:18
Forgot how ugly this was. Think it's worth noting
gavinp
2012/12/17 20:34:02
Done.
|
| } |
| IN_PROC_BROWSER_TEST_F( |
| @@ -1145,8 +1240,18 @@ IN_PROC_BROWSER_TEST_F( |
| set_loader_query_and_fragment("?links_to_insert=2&links_to_remove=2"); |
| PrerenderTestURL("files/prerender/prerender_page.html", |
| FINAL_STATUS_CANCELLED, 1); |
| - RemoveLinkElementsAndNavigate(); |
| - ASSERT_TRUE(IsEmptyPrerenderLinkManager()); |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(2)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(2)); |
| + |
| + RemoveLinkElements(); |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(2)); |
| + |
|
mmenke
2012/12/17 17:08:18
nit: Weird space for space.
gavinp
2012/12/17 20:34:02
Done.
|
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(2)); |
| + EXPECT_TRUE(IsEmptyPrerenderLinkManager()); |
| } |
| #if defined(OS_WIN) |
| @@ -1164,16 +1269,26 @@ IN_PROC_BROWSER_TEST_F( |
| set_loader_query_and_fragment("?links_to_insert=2&links_to_remove=1"); |
| PrerenderTestURL("files/prerender/prerender_page.html", |
| FINAL_STATUS_USED, 1); |
| - RemoveLinkElementsAndNavigate(); |
| -} |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(2)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(2)); |
| -IN_PROC_BROWSER_TEST_F( |
| - PrerenderBrowserTest, PrerenderPageRemovingLinkWithOneLinkRemovingTwo) { |
| - set_loader_path("files/prerender/prerender_loader_removing_links.html"); |
| - set_loader_query_and_fragment("?links_to_insert=1&links_to_remove=2"); |
| - PrerenderTestURL("files/prerender/prerender_page.html", |
| - FINAL_STATUS_CANCELLED, 1); |
| - RemoveLinkElementsAndNavigate(); |
| + RemoveLinkElements(); |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(2)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(2)); |
| + |
| + EXPECT_FALSE(IsEmptyPrerenderLinkManager()); |
| + |
| + ChannelDestructionWatcher channel_close_watcher; |
| + channel_close_watcher.WatchChannel( |
| + chrome::GetActiveWebContents(browser())->GetRenderProcessHost()); |
| + NavigateToDestURL(); |
| + channel_close_watcher.WaitForChannelClose(); |
| + |
| + EXPECT_TRUE(IsEmptyPrerenderLinkManager()); |
| } |
| // Checks that prerendering works in incognito mode. |
| @@ -2272,12 +2387,25 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelAll) { |
| 1); |
| // Post a task to cancel all the prerenders. |
| MessageLoop::current()->PostTask( |
| - FROM_HERE, |
| - base::Bind(&CancelAllPrerenders, GetPrerenderManager())); |
| + FROM_HERE, base::Bind(&CancelAllPrerenders, GetPrerenderManager())); |
| content::RunMessageLoop(); |
| EXPECT_TRUE(GetPrerenderContents() == NULL); |
| } |
| +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderEvents) { |
| + PrerenderTestURL("files/prerender/prerender_page.html", |
| + FINAL_STATUS_CANCELLED, 1); |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); |
| + EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); |
| + |
| + MessageLoop::current()->PostTask( |
| + FROM_HERE, base::Bind(&CancelAllPrerenders, GetPrerenderManager())); |
| + content::RunMessageLoop(); |
| + |
| + EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); |
| + EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(1)); |
| +} |
| + |
| // Prerendering and history tests. |
| // The prerendered page is navigated to in several ways [navigate via |
| // omnibox, click on link, key-modified click to open in background tab, etc], |