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], |