diff options
author | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-30 19:54:20 +0000 |
---|---|---|
committer | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-30 19:54:20 +0000 |
commit | 9a31e7f2ee3c632f829cd34490ba22995c401291 (patch) | |
tree | 90af46a27c32a71dd4e5358e42e2a15382f1b45b /chrome | |
parent | b48532fded2bbd1d9b1781c3ba6f645fc54a3070 (diff) | |
download | chromium_src-9a31e7f2ee3c632f829cd34490ba22995c401291.zip chromium_src-9a31e7f2ee3c632f829cd34490ba22995c401291.tar.gz chromium_src-9a31e7f2ee3c632f829cd34490ba22995c401291.tar.bz2 |
Fix visibility state of prerendered pages opened
in a new background tab not updating.
Also adds a couple tests for the visibility API.
BUG=87926
TEST=PrerenderBrowserTest.PrerenderVisibilityBackgroundTab, PrerenderBrowserTest.PrerenderVisibilityForegroundTab, PrerenderBrowserTest.PrerenderVisibility
Review URL: http://codereview.chromium.org/7282013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@91182 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/prerender/prerender_browsertest.cc | 86 | ||||
-rw-r--r-- | chrome/renderer/prerender/prerender_helper.cc | 11 | ||||
-rw-r--r-- | chrome/renderer/prerender/prerender_helper.h | 4 | ||||
-rw-r--r-- | chrome/test/data/prerender/prerender_visibility.html | 56 | ||||
-rw-r--r-- | chrome/test/data/prerender/prerender_visibility_hidden.html | 55 |
5 files changed, 201 insertions, 11 deletions
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 461af28..06350a3 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc @@ -105,6 +105,7 @@ class TestPrerenderContents : public PrerenderContents { new_render_view_host_(NULL), was_hidden_(false), was_shown_(false), + should_be_shown_(expected_final_status == FINAL_STATUS_USED), quit_message_loop_on_destruction_(true) { } @@ -124,12 +125,10 @@ class TestPrerenderContents : public PrerenderContents { // A used PrerenderContents will only be destroyed when we swap out // TabContents, at the end of a navigation caused by a call to // NavigateToURLImpl(). - if (final_status() == FINAL_STATUS_USED) { + if (final_status() == FINAL_STATUS_USED) EXPECT_TRUE(new_render_view_host_); - EXPECT_TRUE(was_shown_); - } else { - EXPECT_FALSE(was_shown_); - } + + EXPECT_EQ(should_be_shown_, was_shown_); // When the PrerenderContents is destroyed, quit the UI message loop. // This happens on navigation to used prerendered pages, and soon @@ -166,6 +165,11 @@ class TestPrerenderContents : public PrerenderContents { } } + // For tests that open the prerender in a new background tab, the RenderView + // will not have been made visible when the PrerenderContents is destroyed + // even though it is used. + void set_should_be_shown(bool value) { should_be_shown_ = value; } + // Some of the ui_test_utils calls that we use assume that no one will quit // the message loop that they run internally. So we dont quit the message // loop in the destructor so as not to interfere. @@ -220,6 +224,10 @@ class TestPrerenderContents : public PrerenderContents { // Set to true when the prerendering RenderWidget is shown, after having been // hidden. bool was_shown_; + // Expected final value of was_shown_. Defaults to true for + // FINAL_STATUS_USED, and false otherwise. + bool should_be_shown_; + bool quit_message_loop_on_destruction_; }; @@ -401,7 +409,13 @@ class PrerenderBrowserTest : public InProcessBrowserTest { } void NavigateToDestURL() const { - NavigateToURLImpl(dest_url_); + NavigateToDestURLWithDisposition(CURRENT_TAB); + } + + // Opens the url in a new tab, with no opener. + void NavigateToDestURLWithDisposition( + WindowOpenDisposition disposition) const { + NavigateToURLImpl(dest_url_, disposition); } void OpenDestUrlInNewWindowViaJs() const { @@ -447,7 +461,7 @@ class PrerenderBrowserTest : public InProcessBrowserTest { // Should be const but test_server()->GetURL(...) is not const. void NavigateToURL(const std::string& dest_html_file) { GURL dest_url = test_server()->GetURL(dest_html_file); - NavigateToURLImpl(dest_url); + NavigateToURLImpl(dest_url, CURRENT_TAB); } bool UrlIsInPrerenderManager(const std::string& html_file) { @@ -576,9 +590,15 @@ class PrerenderBrowserTest : public InProcessBrowserTest { } } - void NavigateToURLImpl(const GURL& dest_url) const { + void NavigateToURLImpl(const GURL& dest_url, + WindowOpenDisposition disposition) const { // Make sure in navigating we have a URL to use in the PrerenderManager. - EXPECT_TRUE(GetPrerenderContents() != NULL); + ASSERT_TRUE(GetPrerenderContents() != NULL); + + // If opening the page in a background tab, it won't be shown when swapped + // in. + if (disposition == NEW_BACKGROUND_TAB) + GetPrerenderContents()->set_should_be_shown(false); // ui_test_utils::NavigateToURL waits until DidStopLoading is called on // the current tab. As that tab is going to end up deleted, and may never @@ -588,7 +608,8 @@ class PrerenderBrowserTest : public InProcessBrowserTest { // As PrerenderTestURL waits until the prerendered page has completely // loaded, there is no race between loading |dest_url| and swapping the // prerendered TabContents into the tab. - browser()->OpenURL(dest_url, GURL(), CURRENT_TAB, PageTransition::TYPED); + ui_test_utils::NavigateToURLWithDisposition( + browser(), dest_url, disposition, ui_test_utils::BROWSER_TEST_NONE); ui_test_utils::RunMessageLoop(); // Make sure the PrerenderContents found earlier was used or removed. @@ -596,9 +617,26 @@ class PrerenderBrowserTest : public InProcessBrowserTest { if (call_javascript_) { // Check if page behaved as expected when actually displayed. + + // Locate the navigated TabContents. + TabContents* tab_contents = NULL; + switch (disposition) { + case CURRENT_TAB: + case NEW_FOREGROUND_TAB: + tab_contents = browser()->GetSelectedTabContents(); + break; + case NEW_BACKGROUND_TAB: + tab_contents = + browser()->GetTabContentsAt(browser()->active_index() + 1); + break; + default: + ASSERT_TRUE(false) << "Unsupported creation disposition"; + } + ASSERT_TRUE(tab_contents); + bool display_test_result = false; ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( - browser()->GetSelectedTabContents()->render_view_host(), L"", + tab_contents->render_view_host(), L"", L"window.domAutomationController.send(DidDisplayPass())", &display_test_result)); EXPECT_TRUE(display_test_result); @@ -621,6 +659,32 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPage) { NavigateToDestURL(); } +// Checks that the visibility API works. +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderVisibility) { + PrerenderTestURL("files/prerender/prerender_visibility.html", + FINAL_STATUS_USED, + 1); + NavigateToDestURL(); +} + +// Checks that the visibility API works when opening a page in a new hidden +// tab. +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderVisibilityBackgroundTab) { + PrerenderTestURL("files/prerender/prerender_visibility_hidden.html", + FINAL_STATUS_USED, + 1); + NavigateToDestURLWithDisposition(NEW_BACKGROUND_TAB); +} + +// Checks that the visibility API works when opening a page in a new foreground +// tab. +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderVisibilityForegroundTab) { + PrerenderTestURL("files/prerender/prerender_visibility.html", + FINAL_STATUS_USED, + 1); + NavigateToDestURLWithDisposition(NEW_FOREGROUND_TAB); +} + // Checks that the prerendering of a page is canceled correctly when a // Javascript alert is called. IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertBeforeOnload) { diff --git a/chrome/renderer/prerender/prerender_helper.cc b/chrome/renderer/prerender/prerender_helper.cc index 053f4ef..67092dc 100644 --- a/chrome/renderer/prerender/prerender_helper.cc +++ b/chrome/renderer/prerender/prerender_helper.cc @@ -10,6 +10,7 @@ #include "content/renderer/navigation_state.h" #include "content/renderer/render_view.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" // Helper macro for histograms. #define RECORD_PLT(tag, perceived_page_load_time) { \ @@ -29,6 +30,7 @@ PrerenderHelper::PrerenderHelper(RenderView* render_view) RenderViewObserverTracker<PrerenderHelper>(render_view), is_prerendering_(true), has_unrecorded_data_(false) { + UpdateVisibilityState(); } PrerenderHelper::~PrerenderHelper() { @@ -155,10 +157,19 @@ void PrerenderHelper::OnSetIsPrerendering(bool is_prerendering) { is_prerendering_ = false; prerender_display_time_ = base::Time::Now(); + UpdateVisibilityState(); } bool PrerenderHelper::HasUnrecordedData() const { return !prerender_display_time_.is_null(); } +void PrerenderHelper::UpdateVisibilityState() { + if (render_view()->webview()) { + render_view()->webview()->setVisibilityState( + render_view()->visibilityState(), + false); + } +} + } // namespace prerender diff --git a/chrome/renderer/prerender/prerender_helper.h b/chrome/renderer/prerender/prerender_helper.h index a2db36f..5c2c87c 100644 --- a/chrome/renderer/prerender/prerender_helper.h +++ b/chrome/renderer/prerender/prerender_helper.h @@ -49,6 +49,10 @@ class PrerenderHelper : public RenderViewObserver, // for the prerender have been recorded. bool HasUnrecordedData() const; + // Updates the visibility state of the RenderView. Must be called whenever + // prerendering starts or finishes. + void UpdateVisibilityState(); + // Tracks whether or not observed RenderView is currently prerendering. bool is_prerendering_; diff --git a/chrome/test/data/prerender/prerender_visibility.html b/chrome/test/data/prerender/prerender_visibility.html new file mode 100644 index 0000000..bb52498 --- /dev/null +++ b/chrome/test/data/prerender/prerender_visibility.html @@ -0,0 +1,56 @@ +<html> +<!-- +This test checks the visibility API when a prerendered page is displayed. +--> +<head> +<title>Prerender Visibility</title> + +<script> +// Checks visibility state while the page is still loading. +var loadingStatePassed = document.webkitHidden && + document.webkitVisibilityState == 'prerender'; + +// True if any visibility change event has occurred. +var visibilityChangeCalled = false; + +// True if the last visibility change event set the document's state to visible. +var visibilityChangePassed = false; + +// Checks that no visibility change events have occurred, current visibility +// state is "prerender", and visibility state while the page was loading was +// also "prerender". +function DidPrerenderPass() { + return !visibilityChangeCalled && + loadingStatePassed && + document.webkitHidden && + 'prerender' == document.webkitVisibilityState; +} + +function onVisibilityChange(event) { + // TODO(mmenke): Currently, we get 4 events when a page is shown - + // hidden -> visible -> hidden -> visible. + // Once that's fixed, add check to make sure we only have + // hidden -> visible, or just visible. + visibilityChangePassed = + !document.webkitHidden && + 'visible' == document.webkitVisibilityState; + visibilityChangeCalled = true; +} + +document.addEventListener("webkitvisibilitychange", + onVisibilityChange, + false); + +// Checks that the last visibility change resulted in a visible state, and that +// the current state is also visible. +function DidDisplayPass() { + return visibilityChangeCalled && + visibilityChangePassed && + !document.webkitHidden && + 'visible' == document.webkitVisibilityState; +} +</script> + +</head> +<body></body> +</html> diff --git a/chrome/test/data/prerender/prerender_visibility_hidden.html b/chrome/test/data/prerender/prerender_visibility_hidden.html new file mode 100644 index 0000000..090f998 --- /dev/null +++ b/chrome/test/data/prerender/prerender_visibility_hidden.html @@ -0,0 +1,55 @@ +<html> +<!-- +This test checks the visibility API when a prerendered page is visited without +being displayed. +--> +<head> +<title>Prerender Visibility Hidden</title> + +<script> +// Checks visibility state while the page is still loading. +var loadingStatePassed = document.webkitHidden && + document.webkitVisibilityState == 'prerender'; + +// True if any visibility change event has occurred. +var visibilityChangeCalled = false; + +// True if only one visibility change event has occurred, and that event was the +// transition to the 'hidden' state. +var visibilityChangePassed = false; + +// Checks that no visibility change events have occurred, current visibility +// state is "prerender", and visibility state while the page was loading was +// also "prerender". +function DidPrerenderPass() { + return !visibilityChangeCalled && + loadingStatePassed && + document.webkitHidden && + 'prerender' == document.webkitVisibilityState; +} + +function onVisibilityChange(event) { + visibilityChangePassed = + !visibilityChangeCalled && + document.webkitHidden && + 'hidden' == document.webkitVisibilityState; + visibilityChangeCalled = true; +} + +document.addEventListener("webkitvisibilitychange", + onVisibilityChange, + false); + +// Checks one and only one visibility change even occurred, and resulted in a +// hidden state, and that current state is also hidden. +function DidDisplayPass() { + return visibilityChangeCalled && + visibilityChangePassed && + document.webkitHidden && + 'hidden' == document.webkitVisibilityState; +} +</script> + +</head> +<body></body> +</html> |