summaryrefslogtreecommitdiffstats
path: root/chrome/browser/prerender
diff options
context:
space:
mode:
authorshishir@chromium.org <shishir@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-14 22:23:17 +0000
committershishir@chromium.org <shishir@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-14 22:23:17 +0000
commit4fa199b586950d93a0987f13c01b9d994263a636 (patch)
tree42781baa82fe560777ae8512db4f0d2e6d0627b7 /chrome/browser/prerender
parentd38cdb80943af572fdccac502fb6defec763a68d (diff)
downloadchromium_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')
-rw-r--r--chrome/browser/prerender/prerender_browsertest.cc96
-rw-r--r--chrome/browser/prerender/prerender_contents.cc1
-rw-r--r--chrome/browser/prerender/prerender_contents.h1
-rw-r--r--chrome/browser/prerender/prerender_final_status.h1
-rw-r--r--chrome/browser/prerender/prerender_manager.cc23
-rw-r--r--chrome/browser/prerender/prerender_manager.h8
-rw-r--r--chrome/browser/prerender/prerender_manager_unittest.cc2
-rw-r--r--chrome/browser/prerender/prerender_observer.cc15
-rw-r--r--chrome/browser/prerender/prerender_observer.h6
-rw-r--r--chrome/browser/prerender/prerender_render_view_host_observer.cc2
-rw-r--r--chrome/browser/prerender/prerender_render_view_host_observer.h1
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();