summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/prerender/prerender_browsertest.cc74
-rw-r--r--chrome/browser/prerender/prerender_contents.cc46
-rw-r--r--chrome/browser/prerender/prerender_contents.h3
-rw-r--r--chrome/browser/prerender/prerender_manager.cc17
-rw-r--r--chrome/browser/prerender/prerender_manager.h12
-rw-r--r--chrome/browser/prerender/prerender_manager_unittest.cc8
-rw-r--r--chrome/browser/prerender/prerender_tab_helper.cc16
-rw-r--r--chrome/browser/prerender/prerender_tab_helper.h8
-rw-r--r--chrome/browser/ui/browser_navigator.cc17
-rw-r--r--chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc2
-rw-r--r--chrome/chrome_renderer.gypi2
-rw-r--r--chrome/common/common_message_generator.h3
-rw-r--r--chrome/common/prerender_messages.h25
-rw-r--r--chrome/common/render_messages.h6
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc12
-rw-r--r--chrome/renderer/chrome_content_renderer_client.h5
-rw-r--r--chrome/renderer/chrome_render_view_observer.cc3
-rw-r--r--chrome/renderer/plugins/plugin_placeholder.cc3
-rw-r--r--chrome/renderer/prerender/prerender_dispatcher.cc60
-rw-r--r--chrome/renderer/prerender/prerender_dispatcher.h41
-rw-r--r--chrome/renderer/prerender/prerender_helper.cc6
-rw-r--r--chrome/renderer/prerender/prerender_webmediaplayer.cc4
-rw-r--r--chrome/test/data/prerender/prerender_loader.html6
-rw-r--r--chrome/test/data/prerender/prerender_loader_with_session_storage.html2
-rw-r--r--chrome/test/data/prerender/prerender_loader_with_unload.html2
-rw-r--r--content/browser/tab_contents/tab_contents.cc7
-rw-r--r--content/browser/tab_contents/tab_contents.h8
-rw-r--r--content/browser/tab_contents/tab_contents_view_helper.cc1
-rw-r--r--content/public/browser/web_contents.h3
-rw-r--r--ipc/ipc_message_utils.h1
30 files changed, 316 insertions, 87 deletions
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 8d624d7..81d63bd 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -172,8 +172,13 @@ class TestPrerenderContents : public PrerenderContents {
// When the PrerenderContents is destroyed, quit the UI message loop.
// This happens on navigation to used prerendered pages, and soon
// after cancellation of unused prerendered pages.
- if (quit_message_loop_on_destruction_)
- MessageLoopForUI::current()->Quit();
+ if (quit_message_loop_on_destruction_) {
+ // The message loop may not be running if this is swapped in
+ // synchronously on a Navigation.
+ MessageLoop* loop = MessageLoopForUI::current();
+ if (loop->is_running())
+ loop->Quit();
+ }
}
virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE {
@@ -488,7 +493,8 @@ class PrerenderBrowserTest : public InProcessBrowserTest {
const std::string& html_file,
const std::deque<FinalStatus>& expected_final_status_queue,
int expected_number_of_loads) {
- PrerenderTestURLImpl(test_server()->GetURL(html_file),
+ GURL url = test_server()->GetURL(html_file);
+ PrerenderTestURLImpl(url, url,
expected_final_status_queue,
expected_number_of_loads);
}
@@ -499,7 +505,19 @@ class PrerenderBrowserTest : public InProcessBrowserTest {
int expected_number_of_loads) {
std::deque<FinalStatus> expected_final_status_queue(1,
expected_final_status);
- PrerenderTestURLImpl(url,
+ PrerenderTestURLImpl(url, url,
+ expected_final_status_queue,
+ expected_number_of_loads);
+ }
+
+ void PrerenderTestURL(
+ const GURL& prerender_url,
+ const GURL& destination_url,
+ FinalStatus expected_final_status,
+ int expected_number_of_loads) {
+ std::deque<FinalStatus> expected_final_status_queue(1,
+ expected_final_status);
+ PrerenderTestURLImpl(prerender_url, destination_url,
expected_final_status_queue,
expected_number_of_loads);
}
@@ -691,14 +709,18 @@ class PrerenderBrowserTest : public InProcessBrowserTest {
private:
void PrerenderTestURLImpl(
- const GURL& url,
+ const GURL& prerender_url,
+ const GURL& destination_url,
const std::deque<FinalStatus>& expected_final_status_queue,
int expected_number_of_loads) {
- dest_url_ = url;
+ // TODO(cbentzel): Remove dest_url_?
+ dest_url_ = destination_url;
std::vector<net::TestServer::StringPair> replacement_text;
replacement_text.push_back(
- make_pair("REPLACE_WITH_PRERENDER_URL", dest_url_.spec()));
+ make_pair("REPLACE_WITH_PRERENDER_URL", prerender_url.spec()));
+ replacement_text.push_back(
+ make_pair("REPLACE_WITH_DESTINATION_URL", destination_url.spec()));
std::string replacement_path;
ASSERT_TRUE(net::TestServer::GetFilePathWithReplacements(
loader_path_,
@@ -789,17 +811,11 @@ class PrerenderBrowserTest : public InProcessBrowserTest {
}
}
- // 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
- // finish loading before that happens, exit the message loop on the deletion
- // of the used prerender contents instead.
- //
- // 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.
+ // Navigate to the prerendered URL, but don't run the message loop. Browser
+ // issued navigations to prerendered pages will synchronously swap in the
+ // prerendered page.
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.
EXPECT_TRUE(GetPrerenderContents() == NULL);
@@ -965,6 +981,19 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
NavigateToURL("files/prerender/prerender_page.html");
}
+// Checks that client-issued redirects work with prerendering.
+// This version navigates to the final destination page, rather than the
+// page which does the redirection via a mouse click.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
+ PrerenderClientRedirectNavigateToSecondViaClick) {
+ GURL prerender_url = test_server()->GetURL(
+ CreateClientRedirect("files/prerender/prerender_page.html"));
+ GURL destination_url = test_server()->GetURL(
+ "files/prerender/prerender_page.html");
+ PrerenderTestURL(prerender_url, destination_url, FINAL_STATUS_USED, 2);
+ OpenDestURLViaClick();
+}
+
// Checks that a prerender for an https will prevent a prerender from happening.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHttps) {
net::TestServer https_server(net::TestServer::TYPE_HTTPS,
@@ -1056,6 +1085,19 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
NavigateToURL("files/prerender/prerender_page.html");
}
+// Checks that server-issued redirects work with prerendering.
+// This version navigates to the final destination page, rather than the
+// page which does the redirection via a mouse click.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
+ PrerenderServerRedirectNavigateToSecondViaClick) {
+ GURL prerender_url = test_server()->GetURL(
+ CreateServerRedirect("files/prerender/prerender_page.html"));
+ GURL destination_url = test_server()->GetURL(
+ "files/prerender/prerender_page.html");
+ PrerenderTestURL(prerender_url, destination_url, FINAL_STATUS_USED, 1);
+ OpenDestURLViaClick();
+}
+
// Checks that server-issued redirects from an http to an https
// location will cancel prerendering.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index 92ba801..93d1029 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -21,7 +21,7 @@
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/icon_messages.h"
-#include "chrome/common/render_messages.h"
+#include "chrome/common/prerender_messages.h"
#include "chrome/common/url_constants.h"
#include "content/browser/renderer_host/resource_request_details.h"
#include "content/public/browser/browser_child_process_host.h"
@@ -59,6 +59,29 @@ struct PrerenderURLPredicate {
GURL url_;
};
+// Tells the render process at |child_id| whether |url| is a new prerendered
+// page, or whether |url| is being removed as a prerendered page. Currently
+// this will only inform the render process that created the prerendered page
+// with <link rel="prerender"> tags about it. This means that if the user
+// clicks on a link for a prerendered URL in a different page, the prerender
+// will not be swapped in.
+void InformRenderProcessAboutPrerender(const GURL& url,
+ bool is_add,
+ int child_id) {
+ if (child_id < 0)
+ return;
+ content::RenderProcessHost* render_process_host =
+ content::RenderProcessHost::FromID(child_id);
+ if (!render_process_host)
+ return;
+ IPC::Message* message = NULL;
+ if (is_add)
+ message = new PrerenderMsg_AddPrerenderURL(url);
+ else
+ message = new PrerenderMsg_RemovePrerenderURL(url);
+ render_process_host->Send(message);
+}
+
} // end namespace
class PrerenderContentsFactoryImpl : public PrerenderContents::Factory {
@@ -225,7 +248,8 @@ PrerenderContents::PrerenderContents(
child_id_(-1),
route_id_(-1),
origin_(origin),
- experiment_id_(experiment_id) {
+ experiment_id_(experiment_id),
+ creator_child_id_(-1) {
DCHECK(prerender_manager != NULL);
}
@@ -246,6 +270,13 @@ void PrerenderContents::StartPrerendering(
DCHECK(prerender_contents_.get() == NULL);
prerendering_has_started_ = true;
+ DCHECK(creator_child_id_ == -1);
+ DCHECK(alias_urls_.size() == 1);
+ if (source_render_view_host)
+ creator_child_id_ = source_render_view_host->GetProcess()->GetID();
+ InformRenderProcessAboutPrerender(prerender_url_, true,
+ creator_child_id_);
+
WebContents* new_contents = WebContents::Create(
profile_, NULL, MSG_ROUTING_NONE, NULL, session_storage_namespace);
prerender_contents_.reset(new TabContentsWrapper(new_contents));
@@ -361,8 +392,14 @@ PrerenderContents::~PrerenderContents() {
match_complete_status_,
final_status_);
- if (child_id_ != -1 && route_id_ != -1)
+ if (child_id_ != -1 && route_id_ != -1) {
prerender_tracker_->OnPrerenderingFinished(child_id_, route_id_);
+ for (std::vector<GURL>::const_iterator it = alias_urls_.begin();
+ it != alias_urls_.end();
+ ++it) {
+ InformRenderProcessAboutPrerender(*it, false, creator_child_id_);
+ }
+ }
// If we still have a TabContents, clean up anything we need to and then
// destroy it.
@@ -417,7 +454,7 @@ void PrerenderContents::Observe(int type,
// first navigation, so there's no need to send the message just after
// the TabContents is created.
new_render_view_host->Send(
- new ChromeViewMsg_SetIsPrerendering(
+ new PrerenderMsg_SetIsPrerendering(
new_render_view_host->GetRoutingID(),
true));
@@ -474,6 +511,7 @@ bool PrerenderContents::AddAliasURL(const GURL& url) {
}
alias_urls_.push_back(url);
+ InformRenderProcessAboutPrerender(url, true, creator_child_id_);
prerender_tracker_->AddPrerenderURLOnUIThread(url);
return true;
}
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h
index 139e4ff..85aa433 100644
--- a/chrome/browser/prerender/prerender_contents.h
+++ b/chrome/browser/prerender/prerender_contents.h
@@ -339,6 +339,9 @@ class PrerenderContents : public content::NotificationObserver,
// List of all pages the prerendered page has tried to prerender.
PendingPrerenderList pending_prerender_list_;
+ // The process that created the child id.
+ int creator_child_id_;
+
DISALLOW_COPY_AND_ASSIGN(PrerenderContents);
};
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 0b8589f..d10838c 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -35,7 +35,7 @@
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/render_messages.h"
+#include "chrome/common/prerender_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host_registry.h"
#include "content/public/browser/navigation_controller.h"
@@ -324,9 +324,9 @@ void PrerenderManager::CancelOmniboxPrerenders() {
}
bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents,
- const GURL& url,
- const GURL& opener_url) {
+ const GURL& url) {
DCHECK(CalledOnValidThread());
+ DCHECK(!IsWebContentsPrerendering(web_contents));
RecordNavigation(url);
scoped_ptr<PrerenderContents> prerender_contents(
@@ -334,11 +334,8 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents,
if (prerender_contents.get() == NULL)
return false;
- // Do not use the prerendered version if the opener url corresponding to the
- // window.opener property has the same origin as the url.
- // NOTE: This is broken in the cases where the document domain is modified
- // using the javascript property for "document.domain".
- if (opener_url.GetOrigin() == url.GetOrigin()) {
+ // Do not use the prerendered version if there is an opener object.
+ if (web_contents->HasOpener()) {
prerender_contents.release()->Destroy(FINAL_STATUS_WINDOW_OPENER);
return false;
}
@@ -424,8 +421,8 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents,
prerender_contents->set_final_status(FINAL_STATUS_USED);
new_render_view_host->Send(
- new ChromeViewMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(),
- false));
+ new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(),
+ false));
TabContentsWrapper* new_tab_contents =
prerender_contents->ReleasePrerenderContents();
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index 2d515b5..7a39614 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -125,15 +125,11 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
// Cancels all active prerenders with the ORIGIN_OMNIBOX origin.
void CancelOmniboxPrerenders();
- // For a given WebContents that wants to navigate to the URL supplied,
- // determines whether a prerendered version of the URL can be used,
- // and substitutes the prerendered RVH into the WebContents. |opener_url| is
- // set to the window.opener url that the WebContents should have set and
- // will be empty if there is no opener set. Returns whether or not a
- // prerendered RVH could be used or not.
+ // If |url| matches a valid prerendered page, try to swap it into
+ // |web_contents| and merge browsing histories. Returns |true| if a
+ // prerendered page is swapped in, |false| otherwise.
bool MaybeUsePrerenderedPage(content::WebContents* web_contents,
- const GURL& url,
- const GURL& opener_url);
+ const GURL& url);
// 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 8eb1aec..73c27e5 100644
--- a/chrome/browser/prerender/prerender_manager_unittest.cc
+++ b/chrome/browser/prerender/prerender_manager_unittest.cc
@@ -236,13 +236,7 @@ class PrerenderManagerTest : public testing::Test {
TEST_F(PrerenderManagerTest, EmptyTest) {
EXPECT_FALSE(prerender_manager()->MaybeUsePrerenderedPage(
NULL,
- GURL("http://www.google.com/"),
- GURL()));
-
- EXPECT_FALSE(prerender_manager()->MaybeUsePrerenderedPage(
- NULL,
- GURL("http://www.google.com/search"),
- GURL("http://www.google.com")));
+ GURL("http://www.google.com/")));
}
TEST_F(PrerenderManagerTest, FoundTest) {
diff --git a/chrome/browser/prerender/prerender_tab_helper.cc b/chrome/browser/prerender/prerender_tab_helper.cc
index badb85c..9c614ce 100644
--- a/chrome/browser/prerender/prerender_tab_helper.cc
+++ b/chrome/browser/prerender/prerender_tab_helper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -184,15 +184,12 @@ void PrerenderTabHelper::ProvisionalChangeToMainFrameUrl(
RecordPageviewEvent(PAGEVIEW_EVENT_NEW_URL);
if (IsTopSite(url))
RecordPageviewEvent(PAGEVIEW_EVENT_TOP_SITE_NEW_URL);
- if (!tab_->core_tab_helper()->delegate())
- return; // PrerenderManager needs a delegate to handle the swap.
PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
if (!prerender_manager)
return;
if (prerender_manager->IsWebContentsPrerendering(web_contents()))
return;
prerender_manager->MarkWebContentsAsNotPrerendered(web_contents());
- MaybeUsePrerenderedPage(url, opener_url);
}
void PrerenderTabHelper::UpdateTargetURL(int32 page_id, const GURL& url) {
@@ -247,17 +244,6 @@ PrerenderManager* PrerenderTabHelper::MaybeGetPrerenderManager() const {
Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
}
-bool PrerenderTabHelper::MaybeUsePrerenderedPage(const GURL& url,
- const GURL& opener_url) {
- PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
- if (!prerender_manager)
- return false;
- DCHECK(!prerender_manager->IsWebContentsPrerendering(web_contents()));
- return prerender_manager->MaybeUsePrerenderedPage(web_contents(),
- url,
- opener_url);
-}
-
bool PrerenderTabHelper::IsPrerendering() {
PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
if (!prerender_manager)
diff --git a/chrome/browser/prerender/prerender_tab_helper.h b/chrome/browser/prerender/prerender_tab_helper.h
index 156bcc5..1b3ebe2 100644
--- a/chrome/browser/prerender/prerender_tab_helper.h
+++ b/chrome/browser/prerender/prerender_tab_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -47,12 +47,6 @@ class PrerenderTabHelper : public content::WebContentsObserver {
// Retrieves the PrerenderManager, or NULL, if none was found.
PrerenderManager* MaybeGetPrerenderManager() const;
- // Checks with the PrerenderManager if the specified URL has been preloaded,
- // and if so, swap the RenderViewHost with the preload into this TabContents
- // object. |opener_url| denotes the window.opener url that is set for this
- // tab and is empty if there is no opener set.
- bool MaybeUsePrerenderedPage(const GURL& url, const GURL& opener_url);
-
// Returns whether the TabContents being observed is currently prerendering.
bool IsPrerendering();
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc
index 6dd05b2..80aa319 100644
--- a/chrome/browser/ui/browser_navigator.cc
+++ b/chrome/browser/ui/browser_navigator.cc
@@ -16,6 +16,8 @@
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/rlz/rlz.h"
#include "chrome/browser/tab_contents/tab_util.h"
@@ -361,6 +363,18 @@ void InitializeExtraHeaders(browser::NavigateParams* params,
#endif
}
+// If a prerendered page exists for |url|, replace the page at |target_contents|
+// with it.
+bool SwapInPrerender(TabContentsWrapper* target_contents, const GURL& url) {
+ prerender::PrerenderManager* prerender_manager =
+ prerender::PrerenderManagerFactory::GetForProfile(
+ target_contents->profile());
+ if (!prerender_manager)
+ return false;
+ return prerender_manager->MaybeUsePrerenderedPage(
+ target_contents->web_contents(), url);
+}
+
} // namespace
namespace browser {
@@ -535,6 +549,9 @@ void Navigate(NavigateParams* params) {
InitializeExtraHeaders(params, params->target_contents->profile(),
&extra_headers);
+ if (SwapInPrerender(params->target_contents, url))
+ return;
+
// Try to handle non-navigational URLs that popup dialogs and such, these
// should not actually navigate.
if (!HandleNonNavigationAboutURL(url)) {
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
index 79d7a88..03ebc0c 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
@@ -340,6 +340,8 @@ GURL NetInternalsTest::CreatePrerenderLoaderUrl(
std::vector<net::TestServer::StringPair> replacement_text;
replacement_text.push_back(
make_pair("REPLACE_WITH_PRERENDER_URL", prerender_url.spec()));
+ replacement_text.push_back(
+ make_pair("REPLACE_WITH_DESTINATION_URL", prerender_url.spec()));
std::string replacement_path;
EXPECT_TRUE(net::TestServer::GetFilePathWithReplacements(
"files/prerender/prerender_loader.html",
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 668d10b..15e708b3 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -181,6 +181,8 @@
'renderer/plugins/plugin_placeholder.h',
'renderer/plugins/plugin_uma.cc',
'renderer/plugins/plugin_uma.h',
+ 'renderer/prerender/prerender_dispatcher.cc',
+ 'renderer/prerender/prerender_dispatcher.h',
'renderer/prerender/prerender_helper.cc',
'renderer/prerender/prerender_helper.h',
'renderer/prerender/prerender_webmediaplayer.cc',
diff --git a/chrome/common/common_message_generator.h b/chrome/common/common_message_generator.h
index 4b231f2..fc818fb 100644
--- a/chrome/common/common_message_generator.h
+++ b/chrome/common/common_message_generator.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -10,6 +10,7 @@
#include "chrome/common/chrome_utility_messages.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/icon_messages.h"
+#include "chrome/common/prerender_messages.h"
#include "chrome/common/print_messages.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/safe_browsing/safebrowsing_messages.h"
diff --git a/chrome/common/prerender_messages.h b/chrome/common/prerender_messages.h
new file mode 100644
index 0000000..4c965a9
--- /dev/null
+++ b/chrome/common/prerender_messages.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Multiply-included message file, no traditional include guard.
+#include "googleurl/src/gurl.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_param_traits.h"
+
+#define IPC_MESSAGE_START PrerenderMsgStart
+
+// Tells a renderer if it's currently being prerendered. Must only be set
+// to true before any navigation occurs, and only set to false at most once
+// after that.
+IPC_MESSAGE_ROUTED1(PrerenderMsg_SetIsPrerendering,
+ bool /* whether the RenderView is prerendering */)
+
+// Specifies that a URL is currently being prerendered.
+IPC_MESSAGE_CONTROL1(PrerenderMsg_AddPrerenderURL,
+ GURL /* url */)
+
+// Specifies that a URL is no longer being prerendered.
+IPC_MESSAGE_CONTROL1(PrerenderMsg_RemovePrerenderURL,
+ GURL /* url */)
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 44933a6..a338c89 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -307,12 +307,6 @@ IPC_MESSAGE_ROUTED4(ChromeViewMsg_TranslatePage,
IPC_MESSAGE_ROUTED1(ChromeViewMsg_RevertTranslation,
int /* page id */)
-// Tells a renderer if it's currently being prerendered. Must only be set
-// to true before any navigation occurs, and only set to false at most once
-// after that.
-IPC_MESSAGE_ROUTED1(ChromeViewMsg_SetIsPrerendering,
- bool /* whether the RenderView is prerendering */)
-
// Sent on process startup to indicate whether this process is running in
// incognito mode.
IPC_MESSAGE_CONTROL1(ChromeViewMsg_SetIsIncognitoProcess,
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index badc417..6da46db 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -50,6 +50,7 @@
#include "chrome/renderer/page_load_histograms.h"
#include "chrome/renderer/plugins/plugin_placeholder.h"
#include "chrome/renderer/plugins/plugin_uma.h"
+#include "chrome/renderer/prerender/prerender_dispatcher.h"
#include "chrome/renderer/prerender/prerender_helper.h"
#include "chrome/renderer/prerender/prerender_webmediaplayer.h"
#include "chrome/renderer/print_web_view_helper.h"
@@ -157,6 +158,7 @@ void ChromeContentRendererClient::RenderThreadStarted() {
#if defined(ENABLE_SAFE_BROWSING)
phishing_classifier_.reset(safe_browsing::PhishingClassifierFilter::Create());
#endif
+ prerender_dispatcher_.reset(new prerender::PrerenderDispatcher());
RenderThread* thread = RenderThread::Get();
@@ -168,6 +170,7 @@ void ChromeContentRendererClient::RenderThreadStarted() {
#endif
thread->AddObserver(spellcheck_.get());
thread->AddObserver(visited_link_slave_.get());
+ thread->AddObserver(prerender_dispatcher_.get());
thread->RegisterExtension(extensions_v8::ExternalExtension::Get());
thread->RegisterExtension(extensions_v8::LoadTimesExtension::Get());
@@ -642,6 +645,15 @@ bool ChromeContentRendererClient::ShouldFork(WebFrame* frame,
const GURL& url,
bool is_initial_navigation,
bool* send_referrer) {
+ DCHECK(!frame->parent());
+
+ // If |url| matches one of the prerendered URLs, stop this navigation and try
+ // to swap in the prerendered page on the browser process. If the prerendered
+ // page no longer exists by the time the OpenURL IPC is handled, a normal
+ // navigation is attempted.
+ if (prerender_dispatcher_.get() && prerender_dispatcher_->IsPrerenderURL(url))
+ return true;
+
const ExtensionSet* extensions = extension_dispatcher_->extensions();
// Determine if the new URL is an extension (excluding bookmark apps).
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index 6cbf7d9..c18d866 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -26,6 +26,10 @@ class VisitedLinkSlave;
struct ChromeViewHostMsg_GetPluginInfo_Status;
+namespace prerender {
+class PrerenderDispatcher;
+}
+
namespace safe_browsing {
class PhishingClassifierFilter;
}
@@ -159,6 +163,7 @@ class ChromeContentRendererClient : public content::ContentRendererClient {
scoped_ptr<SpellCheck> spellcheck_;
scoped_ptr<VisitedLinkSlave> visited_link_slave_;
scoped_ptr<safe_browsing::PhishingClassifierFilter> phishing_classifier_;
+ scoped_ptr<prerender::PrerenderDispatcher> prerender_dispatcher_;
};
} // namespace chrome
diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc
index fffdbec..11f5994 100644
--- a/chrome/renderer/chrome_render_view_observer.cc
+++ b/chrome/renderer/chrome_render_view_observer.cc
@@ -14,6 +14,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/icon_messages.h"
+#include "chrome/common/prerender_messages.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/thumbnail_score.h"
#include "chrome/common/url_constants.h"
@@ -267,7 +268,7 @@ bool ChromeRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
// Filter only.
IPC_BEGIN_MESSAGE_MAP(ChromeRenderViewObserver, message)
- IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsPrerendering, OnSetIsPrerendering);
+ IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering);
IPC_END_MESSAGE_MAP()
return handled;
diff --git a/chrome/renderer/plugins/plugin_placeholder.cc b/chrome/renderer/plugins/plugin_placeholder.cc
index 5d2d269..0bd9c0c 100644
--- a/chrome/renderer/plugins/plugin_placeholder.cc
+++ b/chrome/renderer/plugins/plugin_placeholder.cc
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "chrome/common/jstemplate_builder.h"
#include "chrome/common/render_messages.h"
+#include "chrome/common/prerender_messages.h"
#include "chrome/renderer/chrome_content_renderer_client.h"
#include "chrome/renderer/custom_menu_commands.h"
#include "chrome/renderer/plugins/plugin_uma.h"
@@ -219,7 +220,7 @@ bool PluginPlaceholder::OnMessageReceived(const IPC::Message& message) {
// interest in them.
IPC_BEGIN_MESSAGE_MAP(PluginPlaceholder, message)
IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins)
- IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsPrerendering, OnSetIsPrerendering)
+ IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering)
IPC_END_MESSAGE_MAP()
return false;
diff --git a/chrome/renderer/prerender/prerender_dispatcher.cc b/chrome/renderer/prerender/prerender_dispatcher.cc
new file mode 100644
index 0000000..500d4be
--- /dev/null
+++ b/chrome/renderer/prerender/prerender_dispatcher.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/prerender/prerender_dispatcher.h"
+
+#include "base/logging.h"
+#include "chrome/common/prerender_messages.h"
+#include "googleurl/src/gurl.h"
+
+namespace prerender {
+
+PrerenderDispatcher::PrerenderDispatcher() {
+}
+
+PrerenderDispatcher::~PrerenderDispatcher() {
+}
+
+bool PrerenderDispatcher::IsPrerenderURL(const GURL& url) const {
+ return prerender_urls_.find(url) != prerender_urls_.end();
+}
+
+bool PrerenderDispatcher::OnControlMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PrerenderDispatcher, message)
+ IPC_MESSAGE_HANDLER(PrerenderMsg_AddPrerenderURL, OnAddPrerenderURL)
+ IPC_MESSAGE_HANDLER(PrerenderMsg_RemovePrerenderURL, OnRemovePrerenderURL)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void PrerenderDispatcher::OnAddPrerenderURL(const GURL& url) {
+ PrerenderMap::iterator it = prerender_urls_.find(url);
+ if (it != prerender_urls_.end()) {
+ DCHECK(it->second > 0);
+ it->second += 1;
+ } else {
+ prerender_urls_[url] = 1;
+ }
+}
+
+void PrerenderDispatcher::OnRemovePrerenderURL(const GURL& url) {
+ PrerenderMap::iterator it = prerender_urls_.find(url);
+ // This is possible with a spurious remove.
+ // TODO(cbentzel): We'd also want to send the map of active prerenders when
+ // creating a new render process, so the Add/Remove go relative to that.
+ // This may not be that big of a deal in practice, since the newly created tab
+ // is unlikely to go to the prerendered page.
+ if (it == prerender_urls_.end())
+ return;
+ DCHECK(it->second > 0);
+ it->second -= 1;
+ if (it->second == 0)
+ prerender_urls_.erase(it);
+}
+
+} // namespace prerender
diff --git a/chrome/renderer/prerender/prerender_dispatcher.h b/chrome/renderer/prerender/prerender_dispatcher.h
new file mode 100644
index 0000000..5537401
--- /dev/null
+++ b/chrome/renderer/prerender/prerender_dispatcher.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_PRERENDER_PRERENDER_DISPATCHER_H_
+#define CHROME_RENDERER_PRERENDER_PRERENDER_DISPATCHER_H_
+#pragma once
+
+#include <map>
+
+#include "base/compiler_specific.h"
+#include "content/public/renderer/render_process_observer.h"
+
+class GURL;
+
+namespace prerender {
+
+// PrerenderDispatcher keeps track of which URLs are being prerendered. There
+// is only one PrerenderDispatcher per render process, and it will only be
+// aware of prerenders that are triggered by this render process.
+class PrerenderDispatcher : public content::RenderProcessObserver {
+ public:
+ PrerenderDispatcher();
+ virtual ~PrerenderDispatcher();
+
+ bool IsPrerenderURL(const GURL & url) const;
+
+ private:
+ void OnAddPrerenderURL(const GURL& url);
+ void OnRemovePrerenderURL(const GURL& url);
+
+ // RenderProcessObserver:
+ virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ typedef std::map<GURL, int> PrerenderMap;
+ PrerenderMap prerender_urls_;
+};
+
+} // namespace prerender
+
+#endif // CHROME_RENDERER_PRERENDER_PRERENDER_DISPATCHER_H_
diff --git a/chrome/renderer/prerender/prerender_helper.cc b/chrome/renderer/prerender/prerender_helper.cc
index 84dc1d7..853a2f7 100644
--- a/chrome/renderer/prerender/prerender_helper.cc
+++ b/chrome/renderer/prerender/prerender_helper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6,7 +6,7 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
-#include "chrome/common/render_messages.h"
+#include "chrome/common/prerender_messages.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/render_view.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
@@ -131,7 +131,7 @@ void PrerenderHelper::DidStartProvisionalLoad(WebKit::WebFrame* frame) {
bool PrerenderHelper::OnMessageReceived(
const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(PrerenderHelper, message)
- IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsPrerendering, OnSetIsPrerendering)
+ IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering)
IPC_END_MESSAGE_MAP()
// Return false on ViewMsg_SetIsPrerendering so other observers can see the
// message.
diff --git a/chrome/renderer/prerender/prerender_webmediaplayer.cc b/chrome/renderer/prerender/prerender_webmediaplayer.cc
index 8189b4f..8fcc299 100644
--- a/chrome/renderer/prerender/prerender_webmediaplayer.cc
+++ b/chrome/renderer/prerender/prerender_webmediaplayer.cc
@@ -4,7 +4,7 @@
#include "chrome/renderer/prerender/prerender_webmediaplayer.h"
-#include "chrome/common/render_messages.h"
+#include "chrome/common/prerender_messages.h"
#include "content/public/renderer/render_view.h"
#include "media/base/filter_collection.h"
#include "media/base/media_log.h"
@@ -59,7 +59,7 @@ void PrerenderWebMediaPlayer::cancelLoad() {
bool PrerenderWebMediaPlayer::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(PrerenderWebMediaPlayer, message)
- IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsPrerendering, OnSetIsPrerendering)
+ IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering)
IPC_END_MESSAGE_MAP()
return false;
diff --git a/chrome/test/data/prerender/prerender_loader.html b/chrome/test/data/prerender/prerender_loader.html
index 66d4afe..9fed87a 100644
--- a/chrome/test/data/prerender/prerender_loader.html
+++ b/chrome/test/data/prerender/prerender_loader.html
@@ -56,7 +56,7 @@
}
function WindowOpen() {
- window.open('REPLACE_WITH_PRERENDER_URL');
+ window.open('REPLACE_WITH_DESTINATION_URL');
}
</script>
@@ -66,7 +66,7 @@
document.write('<link rel="prerender" href="REPLACE_WITH_PRERENDER_URL"/>');
</script>
<a target="_blank" id="toClickTarget"
- href="REPLACE_WITH_PRERENDER_URL">Link To click in new window</a>
-<a id="toClick" href="REPLACE_WITH_PRERENDER_URL">Link to click</a>
+ href="REPLACE_WITH_DESTINATION_URL">Link To click in new window</a>
+<a id="toClick" href="REPLACE_WITH_DESTINATION_URL">Link to click</a>
</body>
</html>
diff --git a/chrome/test/data/prerender/prerender_loader_with_session_storage.html b/chrome/test/data/prerender/prerender_loader_with_session_storage.html
index 9b8e282..5221086 100644
--- a/chrome/test/data/prerender/prerender_loader_with_session_storage.html
+++ b/chrome/test/data/prerender/prerender_loader_with_session_storage.html
@@ -32,6 +32,6 @@
window.onload = loader;
</script>
-<a id="toClick" href="REPLACE_WITH_PRERENDER_URL">Link to click</a>
+<a id="toClick" href="REPLACE_WITH_DESTINATION_URL">Link to click</a>
</body>
</html>
diff --git a/chrome/test/data/prerender/prerender_loader_with_unload.html b/chrome/test/data/prerender/prerender_loader_with_unload.html
index 4819015..50336fa 100644
--- a/chrome/test/data/prerender/prerender_loader_with_unload.html
+++ b/chrome/test/data/prerender/prerender_loader_with_unload.html
@@ -15,6 +15,6 @@
<script>
document.write('<link rel="prerender" href="REPLACE_WITH_PRERENDER_URL"/>');
</script>
-<a href="REPLACE_WITH_PRERENDER_URL">Link To Click</a>
+<a href="REPLACE_WITH_DESTINATION_URL">Link To Click</a>
</body>
</html>
diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc
index 239ec8e..84d54de 100644
--- a/content/browser/tab_contents/tab_contents.cc
+++ b/content/browser/tab_contents/tab_contents.cc
@@ -265,7 +265,8 @@ TabContents::TabContents(content::BrowserContext* browser_context,
static_cast<int>(content::kMaximumZoomFactor * 100)),
temporary_zoom_settings_(false),
content_restrictions_(0),
- view_type_(content::VIEW_TYPE_TAB_CONTENTS) {
+ view_type_(content::VIEW_TYPE_TAB_CONTENTS),
+ has_opener_(false) {
render_manager_.Init(browser_context, site_instance, routing_id);
// We have the initial size of the view be based on the size of the passed in
@@ -1351,6 +1352,10 @@ bool TabContents::GotResponseToLockMouseRequest(bool allowed) {
GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false;
}
+bool TabContents::HasOpener() const {
+ return has_opener_;
+}
+
bool TabContents::FocusLocationBarByDefault() {
content::WebUI* web_ui = GetWebUIForCurrentState();
if (web_ui)
diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h
index b2bca01..74dab24 100644
--- a/content/browser/tab_contents/tab_contents.h
+++ b/content/browser/tab_contents/tab_contents.h
@@ -115,6 +115,10 @@ class CONTENT_EXPORT TabContents
opener_web_ui_type_ = opener_web_ui_type;
}
+ void set_has_opener(bool has_opener) {
+ has_opener_ = has_opener;
+ }
+
JavaBridgeDispatcherHostManager* java_bridge_dispatcher_host_manager() const {
return java_bridge_dispatcher_host_manager_.get();
}
@@ -218,6 +222,7 @@ class CONTENT_EXPORT TabContents
virtual content::WebUI::TypeID GetWebUITypeForCurrentState() OVERRIDE;
virtual content::WebUI* GetWebUIForCurrentState() OVERRIDE;
virtual bool GotResponseToLockMouseRequest(bool allowed) OVERRIDE;
+ virtual bool HasOpener() const OVERRIDE;
// Implementation of PageNavigator.
virtual content::WebContents* OpenURL(
@@ -662,6 +667,9 @@ class CONTENT_EXPORT TabContents
// Our view type. Default is VIEW_TYPE_TAB_CONTENTS.
content::ViewType view_type_;
+ // Is there an opener associated with this?
+ bool has_opener_;
+
DISALLOW_COPY_AND_ASSIGN(TabContents);
};
diff --git a/content/browser/tab_contents/tab_contents_view_helper.cc b/content/browser/tab_contents/tab_contents_view_helper.cc
index 2edfab2..3992daa 100644
--- a/content/browser/tab_contents/tab_contents_view_helper.cc
+++ b/content/browser/tab_contents/tab_contents_view_helper.cc
@@ -81,6 +81,7 @@ TabContents* TabContentsViewHelper::CreateNewWindow(
NULL);
new_contents->set_opener_web_ui_type(
web_contents->GetWebUITypeForCurrentState());
+ new_contents->set_has_opener(!params.opener_url.is_empty());
if (params.opener_suppressed) {
// When the opener is suppressed, the original renderer cannot access the
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index f73813b..abd656a 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -363,6 +363,9 @@ class WebContents : public PageNavigator {
// Focuses the location bar.
virtual void SetFocusToLocationBar(bool select_all) = 0;
+
+ // Does this have an opener associated with it?
+ virtual bool HasOpener() const = 0;
};
} // namespace content
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index 3908b12..912bc04 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -100,6 +100,7 @@ enum IPCMessageStart {
GamepadMsgStart,
ShellMsgStart,
AccessibilityMsgStart,
+ PrerenderMsgStart,
LastIPCMsgStart // Must come last.
};