diff options
author | shishir@chromium.org <shishir@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-14 22:23:17 +0000 |
---|---|---|
committer | shishir@chromium.org <shishir@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-14 22:23:17 +0000 |
commit | 4fa199b586950d93a0987f13c01b9d994263a636 (patch) | |
tree | 42781baa82fe560777ae8512db4f0d2e6d0627b7 /chrome/browser/prerender | |
parent | d38cdb80943af572fdccac502fb6defec763a68d (diff) | |
download | chromium_src-4fa199b586950d93a0987f13c01b9d994263a636.zip chromium_src-4fa199b586950d93a0987f13c01b9d994263a636.tar.gz chromium_src-4fa199b586950d93a0987f13c01b9d994263a636.tar.bz2 |
Changes to not use the prerendered contents when window.opener needs to be set.
BUG=79922
TEST=browser_tests
Review URL: http://codereview.chromium.org/6915019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85394 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/prerender')
11 files changed, 122 insertions, 34 deletions
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index e51751b..a099b2c 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc @@ -53,6 +53,18 @@ std::string CreateServerRedirect(const std::string& dest_url) { return kServerRedirectBase + dest_url; } +// Returns true iff the final status is one in which the prerendered +// page should prerender correctly. The page still may not be used. +bool ShouldRenderPrerenderedPageCorrectly(FinalStatus status) { + switch (status) { + case FINAL_STATUS_USED: + case FINAL_STATUS_WINDOW_OPENER: + return true; + default: + return false; + } +} + // PrerenderContents that stops the UI message loop on DidStopLoading(). class TestPrerenderContents : public PrerenderContents { public: @@ -109,7 +121,7 @@ class TestPrerenderContents : public PrerenderContents { virtual void DidStopLoading() OVERRIDE { PrerenderContents::DidStopLoading(); ++number_of_loads_; - if (expected_final_status_ == FINAL_STATUS_USED && + if (ShouldRenderPrerenderedPageCorrectly(expected_final_status_) && number_of_loads_ >= expected_number_of_loads_) { MessageLoopForUI::current()->Quit(); } else if (expected_final_status_ == FINAL_STATUS_RENDERER_CRASHED) { @@ -286,6 +298,30 @@ class PrerenderBrowserTest : public InProcessBrowserTest { NavigateToURLImpl(dest_url_); } + void OpenDestUrlInNewWindowViaJs() const { + // Make sure in navigating we have a URL to use in the PrerenderManager. + EXPECT_TRUE(prerender_manager()->FindEntry(dest_url_) != NULL); + + bool open_window_result = false; + ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( + browser()->GetSelectedTabContents()->render_view_host(), L"", + L"window.domAutomationController.send(JsOpenLinkInNewWindow())", + &open_window_result)); + EXPECT_TRUE(open_window_result); + } + + void OpenDestUrlInNewWindowViaClick() const { + // Make sure in navigating we have a URL to use in the PrerenderManager. + EXPECT_TRUE(prerender_manager()->FindEntry(dest_url_) != NULL); + + bool click_prerendered_link_result = false; + ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( + browser()->GetSelectedTabContents()->render_view_host(), L"", + L"window.domAutomationController.send(ClickOpenLinkInNewWindow())", + &click_prerendered_link_result)); + EXPECT_TRUE(click_prerendered_link_result); + } + // 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); @@ -376,26 +412,23 @@ class PrerenderBrowserTest : public InProcessBrowserTest { static_cast<TestPrerenderContents*>( prerender_manager()->FindEntry(dest_url_)); - switch (expected_final_status) { - case FINAL_STATUS_USED: { - ASSERT_TRUE(prerender_contents != NULL); - - if (call_javascript_) { - // Check if page behaves as expected while in prerendered state. - bool prerender_test_result = false; - ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( - prerender_contents->render_view_host_mutable(), L"", - L"window.domAutomationController.send(DidPrerenderPass())", - &prerender_test_result)); - EXPECT_TRUE(prerender_test_result); - } - break; + if (ShouldRenderPrerenderedPageCorrectly(expected_final_status)) { + ASSERT_TRUE(prerender_contents != NULL); + EXPECT_EQ(FINAL_STATUS_MAX, prerender_contents->final_status()); + + if (call_javascript_) { + // Check if page behaves as expected while in prerendered state. + bool prerender_test_result = false; + ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( + prerender_contents->render_view_host_mutable(), L"", + L"window.domAutomationController.send(DidPrerenderPass())", + &prerender_test_result)); + EXPECT_TRUE(prerender_test_result); } - default: - // In the failure case, we should have removed dest_url_ from the - // prerender_manager. - EXPECT_TRUE(prerender_contents == NULL); - break; + } else { + // In the failure case, we should have removed dest_url_ from the + // prerender_manager. + EXPECT_TRUE(prerender_contents == NULL); } } @@ -1076,4 +1109,27 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorIframe) { NavigateToDestURL(); } +// Checks that if a page is opened in a new window by javascript the +// prerendered page is not used. +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, + PrerenderWindowOpenerJsOpenInNewPageTest) { + PrerenderTestURL("files/prerender/prerender_page.html", + FINAL_STATUS_WINDOW_OPENER, + 1); + OpenDestUrlInNewWindowViaJs(); +} + +// Checks that if a page is opened due to click on a href with target="_blank" +// the prerendered page is not used. +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, + PrerenderWindowOpenerClickOpenInNewPageTest) { + PrerenderTestURL("files/prerender/prerender_page.html", + FINAL_STATUS_WINDOW_OPENER, + 1); + OpenDestUrlInNewWindowViaClick(); +} + +// TODO(shishir): Add a test for the case when the page having the +// prerendering link already has an opener set. + } // namespace prerender diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc index bdbd6b9..495a8cc 100644 --- a/chrome/browser/prerender/prerender_contents.cc +++ b/chrome/browser/prerender/prerender_contents.cc @@ -605,6 +605,7 @@ void PrerenderContents::OnRenderViewHostCreated( void PrerenderContents::OnDidStartProvisionalLoadForFrame(int64 frame_id, bool is_main_frame, + bool has_opener_set, const GURL& url) { if (is_main_frame) { if (!AddAliasURL(url)) diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h index a77c8cf..d9b690d 100644 --- a/chrome/browser/prerender/prerender_contents.h +++ b/chrome/browser/prerender/prerender_contents.h @@ -273,6 +273,7 @@ class PrerenderContents : public RenderViewHostDelegate, // Message handlers. void OnDidStartProvisionalLoadForFrame(int64 frame_id, bool main_frame, + bool has_opener_set, const GURL& url); void OnUpdateFaviconURL(int32 page_id, const std::vector<FaviconURL>& urls); void OnMaybeCancelPrerenderForHTML5Media(); diff --git a/chrome/browser/prerender/prerender_final_status.h b/chrome/browser/prerender/prerender_final_status.h index 342dc1f..7344ce8 100644 --- a/chrome/browser/prerender/prerender_final_status.h +++ b/chrome/browser/prerender/prerender_final_status.h @@ -34,6 +34,7 @@ enum FinalStatus { FINAL_STATUS_RENDERER_CRASHED, FINAL_STATUS_UNSUPPORTED_SCHEME, FINAL_STATUS_INVALID_HTTP_METHOD, + FINAL_STATUS_WINDOW_OPENER, FINAL_STATUS_MAX, }; diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index 8c0d2d0..e9b7c4a 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc @@ -412,12 +412,20 @@ PrerenderContents* PrerenderManager::GetEntry(const GURL& url) { } bool PrerenderManager::MaybeUsePreloadedPageOld(TabContents* tab_contents, - const GURL& url) { + const GURL& url, + bool has_opener_set) { DCHECK(CalledOnValidThread()); scoped_ptr<PrerenderContents> prerender_contents(GetEntry(url)); if (prerender_contents.get() == NULL) return false; + // Do not use the prerendered version if the opener window.property was + // supposed to be set. + if (has_opener_set) { + prerender_contents.release()->Destroy(FINAL_STATUS_WINDOW_OPENER); + return false; + } + // If we are just in the control group (which can be detected by noticing // that prerendering hasn't even started yet), record that |tab_contents| now // would be showing a prerendered contents, but otherwise, don't do anything. @@ -498,10 +506,12 @@ bool PrerenderManager::MaybeUsePreloadedPageOld(TabContents* tab_contents, } bool PrerenderManager::MaybeUsePreloadedPage(TabContents* tab_contents, - const GURL& url) { + const GURL& url, + bool has_opener_set) { if (!PrerenderContents::UseTabContents()) { VLOG(1) << "Checking for prerender with LEGACY code"; - return PrerenderManager::MaybeUsePreloadedPageOld(tab_contents, url); + return PrerenderManager::MaybeUsePreloadedPageOld(tab_contents, url, + has_opener_set); } VLOG(1) << "Checking for prerender with NEW code"; DCHECK(CalledOnValidThread()); @@ -510,6 +520,13 @@ bool PrerenderManager::MaybeUsePreloadedPage(TabContents* tab_contents, if (prerender_contents.get() == NULL) return false; + // Do not use the prerendered version if the opener window.property was + // supposed to be set. + if (has_opener_set) { + prerender_contents.release()->Destroy(FINAL_STATUS_WINDOW_OPENER); + return false; + } + // If we are just in the control group (which can be detected by noticing // that prerendering hasn't even started yet), record that |tab_contents| now // would be showing a prerendered contents, but otherwise, don't do anything. diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h index dbad41a..3095670 100644 --- a/chrome/browser/prerender/prerender_manager.h +++ b/chrome/browser/prerender/prerender_manager.h @@ -100,8 +100,12 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, // determines whether a preloaded version of the URL can be used, // and substitutes the prerendered RVH into the TabContents. Returns // whether or not a prerendered RVH could be used or not. - bool MaybeUsePreloadedPage(TabContents* tab_contents, const GURL& url); - bool MaybeUsePreloadedPageOld(TabContents* tab_contents, const GURL& url); + bool MaybeUsePreloadedPage(TabContents* tab_contents, + const GURL& url, + bool has_opener_set); + bool MaybeUsePreloadedPageOld(TabContents* tab_contents, + const GURL& url, + bool has_opener_set); // Moves a PrerenderContents to the pending delete list from the list of // active prerenders when prerendering should be cancelled. diff --git a/chrome/browser/prerender/prerender_manager_unittest.cc b/chrome/browser/prerender/prerender_manager_unittest.cc index a671cfe..74f4a7a 100644 --- a/chrome/browser/prerender/prerender_manager_unittest.cc +++ b/chrome/browser/prerender/prerender_manager_unittest.cc @@ -189,7 +189,7 @@ class PrerenderManagerTest : public testing::Test { TEST_F(PrerenderManagerTest, EmptyTest) { GURL url("http://www.google.com/"); - EXPECT_FALSE(prerender_manager()->MaybeUsePreloadedPage(NULL, url)); + EXPECT_FALSE(prerender_manager()->MaybeUsePreloadedPage(NULL, url, false)); } TEST_F(PrerenderManagerTest, FoundTest) { diff --git a/chrome/browser/prerender/prerender_observer.cc b/chrome/browser/prerender/prerender_observer.cc index 30a1248..459ed3a 100644 --- a/chrome/browser/prerender/prerender_observer.cc +++ b/chrome/browser/prerender/prerender_observer.cc @@ -20,14 +20,15 @@ PrerenderObserver::PrerenderObserver(TabContents* tab_contents) PrerenderObserver::~PrerenderObserver() { } -void PrerenderObserver::ProvisionalChangeToMainFrameUrl(const GURL& url) { +void PrerenderObserver::ProvisionalChangeToMainFrameUrl(const GURL& url, + bool has_opener_set) { PrerenderManager* prerender_manager = MaybeGetPrerenderManager(); if (!prerender_manager) return; if (prerender_manager->IsTabContentsPrerendering(tab_contents())) return; prerender_manager->MarkTabContentsAsNotPrerendered(tab_contents()); - MaybeUsePreloadedPage(url); + MaybeUsePreloadedPage(url, has_opener_set); } bool PrerenderObserver::OnMessageReceived(const IPC::Message& message) { @@ -40,6 +41,7 @@ bool PrerenderObserver::OnMessageReceived(const IPC::Message& message) { void PrerenderObserver::OnDidStartProvisionalLoadForFrame(int64 frame_id, bool is_main_frame, + bool has_opener_set, const GURL& url) { // Don't include prerendered pages in the PPLT metric until after they are // swapped in. @@ -71,14 +73,15 @@ PrerenderManager* PrerenderObserver::MaybeGetPrerenderManager() { return tab_contents()->profile()->GetPrerenderManager(); } -bool PrerenderObserver::MaybeUsePreloadedPage(const GURL& url) { +bool PrerenderObserver::MaybeUsePreloadedPage(const GURL& url, + bool has_opener_set) { PrerenderManager* prerender_manager = MaybeGetPrerenderManager(); if (!prerender_manager) return false; DCHECK(!prerender_manager->IsTabContentsPrerendering(tab_contents())); - if (prerender_manager->MaybeUsePreloadedPage(tab_contents(), url)) - return true; - return false; + return prerender_manager->MaybeUsePreloadedPage(tab_contents(), + url, + has_opener_set); } bool PrerenderObserver::IsPrerendering() { diff --git a/chrome/browser/prerender/prerender_observer.h b/chrome/browser/prerender/prerender_observer.h index f2ec018..f8ab5f0 100644 --- a/chrome/browser/prerender/prerender_observer.h +++ b/chrome/browser/prerender/prerender_observer.h @@ -30,13 +30,15 @@ class PrerenderObserver : public TabContentsObserver { virtual ~PrerenderObserver(); // TabContentsObserver implementation. - virtual void ProvisionalChangeToMainFrameUrl(const GURL& url) OVERRIDE; + virtual void ProvisionalChangeToMainFrameUrl(const GURL& url, + bool has_opener_set) OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; virtual void DidStopLoading() OVERRIDE; // Message handler. void OnDidStartProvisionalLoadForFrame(int64 frame_id, bool main_frame, + bool has_opener_set, const GURL& url); private: @@ -46,7 +48,7 @@ class PrerenderObserver : public TabContentsObserver { // Checks with the PrerenderManager if the specified URL has been preloaded, // and if so, swap the RenderViewHost with the preload into this TabContents // object. - bool MaybeUsePreloadedPage(const GURL& url); + bool MaybeUsePreloadedPage(const GURL& url, bool has_opener_set); // Returns whether the TabContents being observed is currently prerendering. bool IsPrerendering(); diff --git a/chrome/browser/prerender/prerender_render_view_host_observer.cc b/chrome/browser/prerender/prerender_render_view_host_observer.cc index fe297a8..08e0a63 100644 --- a/chrome/browser/prerender/prerender_render_view_host_observer.cc +++ b/chrome/browser/prerender/prerender_render_view_host_observer.cc @@ -84,9 +84,11 @@ void PrerenderRenderViewHostObserver::OnRenderViewGone(int status, void PrerenderRenderViewHostObserver::OnDidStartProvisionalLoadForFrame( int64 frame_id, bool is_main_frame, + bool has_opener_set, const GURL& url) { prerender_contents_->OnDidStartProvisionalLoadForFrame(frame_id, is_main_frame, + has_opener_set, url); } diff --git a/chrome/browser/prerender/prerender_render_view_host_observer.h b/chrome/browser/prerender/prerender_render_view_host_observer.h index 6ca6179..13a25f8 100644 --- a/chrome/browser/prerender/prerender_render_view_host_observer.h +++ b/chrome/browser/prerender/prerender_render_view_host_observer.h @@ -49,6 +49,7 @@ class PrerenderRenderViewHostObserver : public RenderViewHostObserver { void OnRenderViewGone(int status, int exit_code); void OnDidStartProvisionalLoadForFrame(int64 frame_id, bool is_main_frame, + bool has_opener_set, const GURL& url); void OnUpdateFaviconURL(int32 page_id, const std::vector<FaviconURL>& urls); void OnMaybeCancelPrerenderForHTML5Media(); |