summaryrefslogtreecommitdiffstats
path: root/chrome/browser/prerender
diff options
context:
space:
mode:
authortburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-18 23:46:38 +0000
committertburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-18 23:46:38 +0000
commitf39506a82dc772467faef96b9e9a4678733bc969 (patch)
tree670240fe497d5c0f6de68fd5a4ae12649676c58f /chrome/browser/prerender
parent7837be66093e1ad899de26542ed5cfc6a69a74e4 (diff)
downloadchromium_src-f39506a82dc772467faef96b9e9a4678733bc969.zip
chromium_src-f39506a82dc772467faef96b9e9a4678733bc969.tar.gz
chromium_src-f39506a82dc772467faef96b9e9a4678733bc969.tar.bz2
For prerendering, keep track of all the intermediate redirects, and hook into
the provisional load messages to catch an earlier time to substitute in the prerendered page. BUG=none TEST=search for techcrunch and notice how the preloaded techcrunch.com is used despite the redirect Review URL: http://codereview.chromium.org/6171007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71721 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/prerender')
-rw-r--r--chrome/browser/prerender/prerender_contents.cc48
-rw-r--r--chrome/browser/prerender/prerender_contents.h25
-rw-r--r--chrome/browser/prerender/prerender_manager.cc14
-rw-r--r--chrome/browser/prerender/prerender_manager.h10
-rw-r--r--chrome/browser/prerender/prerender_manager_unittest.cc59
-rw-r--r--chrome/browser/prerender/prerender_resource_handler.cc23
-rw-r--r--chrome/browser/prerender/prerender_resource_handler.h12
-rw-r--r--chrome/browser/prerender/prerender_resource_handler_unittest.cc14
8 files changed, 172 insertions, 33 deletions
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index 4970739..c5002f7 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -16,18 +16,26 @@
#include "chrome/common/notification_service.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/view_types.h"
+#include "chrome/common/render_messages.h"
#include "chrome/common/render_messages_params.h"
#include "gfx/rect.h"
PrerenderContents::PrerenderContents(PrerenderManager* prerender_manager,
Profile* profile,
- const GURL& url)
+ const GURL& url,
+ const std::vector<GURL>& alias_urls)
: prerender_manager_(prerender_manager),
render_view_host_(NULL),
prerender_url_(url),
profile_(profile),
page_id_(0) {
DCHECK(prerender_manager != NULL);
+ AddAliasURL(prerender_url_);
+ for (std::vector<GURL>::const_iterator it = alias_urls.begin();
+ it != alias_urls.end();
+ ++it) {
+ AddAliasURL(*it);
+ }
}
void PrerenderContents::StartPrerendering() {
@@ -87,6 +95,8 @@ void PrerenderContents::DidNavigate(
navigate_params_.reset(p);
url_ = params.url;
+
+ AddAliasURL(url_);
}
void PrerenderContents::UpdateTitle(RenderViewHost* render_view_host,
@@ -215,3 +225,39 @@ void PrerenderContents::ShowCreatedWidget(int route_id,
void PrerenderContents::ShowCreatedFullscreenWidget(int route_id) {
NOTIMPLEMENTED();
}
+
+bool PrerenderContents::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ bool message_is_ok = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(PrerenderContents, message, message_is_ok)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartProvisionalLoadForFrame,
+ OnDidStartProvisionalLoadForFrame)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidRedirectProvisionalLoad,
+ OnDidRedirectProvisionalLoad)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+
+ return handled;
+}
+
+void PrerenderContents::OnDidStartProvisionalLoadForFrame(int64 frame_id,
+ bool is_main_frame,
+ const GURL& url) {
+ if (is_main_frame)
+ AddAliasURL(url);
+}
+
+void PrerenderContents::OnDidRedirectProvisionalLoad(int32 page_id,
+ const GURL& source_url,
+ const GURL& target_url) {
+ AddAliasURL(target_url);
+}
+
+void PrerenderContents::AddAliasURL(const GURL& url) {
+ alias_urls_.push_back(url);
+}
+
+bool PrerenderContents::MatchesURL(const GURL& url) const {
+ return std::find(alias_urls_.begin(), alias_urls_.end(), url)
+ != alias_urls_.end();
+}
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h
index bf2963f..f64697e 100644
--- a/chrome/browser/prerender/prerender_contents.h
+++ b/chrome/browser/prerender/prerender_contents.h
@@ -37,7 +37,7 @@ class PrerenderContents : public RenderViewHostDelegate,
public JavaScriptAppModalDialogDelegate {
public:
PrerenderContents(PrerenderManager* prerender_manager, Profile* profile,
- const GURL& url);
+ const GURL& url, const std::vector<GURL>& alias_urls);
virtual ~PrerenderContents();
virtual void StartPrerendering();
@@ -52,6 +52,10 @@ class PrerenderContents : public RenderViewHostDelegate,
string16 title() const { return title_; }
int32 page_id() const { return page_id_; }
+ // Indicates whether this prerendered page can be used for the provided
+ // URL, i.e. whether there is a match.
+ bool MatchesURL(const GURL& url) const;
+
// RenderViewHostDelegate implementation.
virtual RenderViewHostDelegate::View* GetViewDelegate();
virtual const GURL& GetURL() const;
@@ -133,7 +137,21 @@ class PrerenderContents : public RenderViewHostDelegate,
const std::string& value);
virtual void ClearInspectorSettings();
+ protected:
+ // from RenderViewHostDelegate.
+ virtual bool OnMessageReceived(const IPC::Message& message);
+
private:
+ // Message handlers.
+ void OnDidStartProvisionalLoadForFrame(int64 frame_id,
+ bool main_frame,
+ const GURL& url);
+ void OnDidRedirectProvisionalLoad(int32 page_id,
+ const GURL& source_url,
+ const GURL& target_url);
+
+ void AddAliasURL(const GURL& url);
+
// The prerender manager owning this object.
PrerenderManager* prerender_manager_;
@@ -162,6 +180,11 @@ class PrerenderContents : public RenderViewHostDelegate,
GURL url_;
NotificationRegistrar registrar_;
+ // A vector of URLs that this prerendered page matches against.
+ // This array can contain more than element as a result of redirects,
+ // such as HTTP redirects or javascript redirects.
+ std::vector<GURL> alias_urls_;
+
DISALLOW_COPY_AND_ASSIGN(PrerenderContents);
};
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 0135880..02a2ac5 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -39,7 +39,8 @@ PrerenderManager::~PrerenderManager() {
}
}
-void PrerenderManager::AddPreload(const GURL& url) {
+void PrerenderManager::AddPreload(const GURL& url,
+ const std::vector<GURL>& alias_urls) {
DCHECK(CalledOnValidThread());
DeleteOldEntries();
// If the URL already exists in the set of preloaded URLs, don't do anything.
@@ -49,7 +50,7 @@ void PrerenderManager::AddPreload(const GURL& url) {
if (it->url_ == url)
return;
}
- PrerenderContentsData data(CreatePrerenderContents(url),
+ PrerenderContentsData data(CreatePrerenderContents(url, alias_urls),
GetCurrentTime(), url);
prerender_list_.push_back(data);
data.contents_->StartPrerendering();
@@ -75,7 +76,8 @@ PrerenderContents* PrerenderManager::GetEntry(const GURL& url) {
for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
it != prerender_list_.end();
++it) {
- if (it->url_ == url) {
+ PrerenderContents* pc = it->contents_;
+ if (pc->MatchesURL(url)) {
PrerenderContents* pc = it->contents_;
prerender_list_.erase(it);
return pc;
@@ -129,6 +131,8 @@ bool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const {
return (now - start < max_prerender_age_);
}
-PrerenderContents* PrerenderManager::CreatePrerenderContents(const GURL& url) {
- return new PrerenderContents(this, profile_, url);
+PrerenderContents* PrerenderManager::CreatePrerenderContents(
+ const GURL& url,
+ const std::vector<GURL>& alias_urls) {
+ return new PrerenderContents(this, profile_, url, alias_urls);
}
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index 0eff09a..c4a6375 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -7,6 +7,7 @@
#pragma once
#include <list>
+#include <vector>
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
@@ -26,8 +27,9 @@ class PrerenderManager : public base::RefCounted<PrerenderManager>,
// Owned by a Profile object for the lifetime of the profile.
explicit PrerenderManager(Profile* profile);
- // Preloads the URL supplied.
- void AddPreload(const GURL& url);
+ // Preloads the URL supplied. alias_urls indicates URLs that redirect
+ // to the same URL to be preloaded.
+ void AddPreload(const GURL& url, const std::vector<GURL>& alias_urls);
// For a given TabContents that wants to navigate to the URL supplied,
// determines whether a preloaded version of the URL can be used,
@@ -60,7 +62,9 @@ class PrerenderManager : public base::RefCounted<PrerenderManager>,
bool IsPrerenderElementFresh(const base::Time start) const;
void DeleteOldEntries();
virtual base::Time GetCurrentTime() const;
- virtual PrerenderContents* CreatePrerenderContents(const GURL& url);
+ virtual PrerenderContents* CreatePrerenderContents(
+ const GURL& url,
+ const std::vector<GURL>& alias_urls);
Profile* profile_;
diff --git a/chrome/browser/prerender/prerender_manager_unittest.cc b/chrome/browser/prerender/prerender_manager_unittest.cc
index e5cb293..97a573d 100644
--- a/chrome/browser/prerender/prerender_manager_unittest.cc
+++ b/chrome/browser/prerender/prerender_manager_unittest.cc
@@ -13,7 +13,14 @@ namespace {
class DummyPrerenderContents : public PrerenderContents {
public:
DummyPrerenderContents(PrerenderManager* prerender_manager, const GURL& url)
- : PrerenderContents(prerender_manager, NULL, url),
+ : PrerenderContents(prerender_manager, NULL, url,
+ std::vector<GURL>()),
+ has_started_(false) {
+ }
+
+ DummyPrerenderContents(PrerenderManager* prerender_manager, const GURL& url,
+ const std::vector<GURL> alias_urls)
+ : PrerenderContents(prerender_manager, NULL, url, alias_urls),
has_started_(false) {
}
@@ -43,6 +50,11 @@ class TestPrerenderManager : public PrerenderManager {
next_pc_.reset(pc);
}
+ // Shorthand to add a simple preload with no aliases.
+ void AddSimplePreload(const GURL& url) {
+ AddPreload(url, std::vector<GURL>());
+ }
+
PrerenderContents* next_pc() { return next_pc_.get(); }
protected:
@@ -54,7 +66,9 @@ class TestPrerenderManager : public PrerenderManager {
return time_;
}
- virtual PrerenderContents* CreatePrerenderContents(const GURL& url) {
+ virtual PrerenderContents* CreatePrerenderContents(
+ const GURL& url,
+ const std::vector<GURL>& alias_urls) {
return next_pc_.release();
}
@@ -83,7 +97,7 @@ TEST_F(PrerenderManagerTest, FoundTest) {
DummyPrerenderContents* pc =
new DummyPrerenderContents(prerender_manager_.get(), url);
prerender_manager_->SetNextPrerenderContents(pc);
- prerender_manager_->AddPreload(url);
+ prerender_manager_->AddSimplePreload(url);
EXPECT_TRUE(pc->has_started());
EXPECT_EQ(pc, prerender_manager_->GetEntry(url));
delete pc;
@@ -97,13 +111,13 @@ TEST_F(PrerenderManagerTest, DropSecondRequestTest) {
new DummyPrerenderContents(prerender_manager_.get(), url);
DummyPrerenderContents* null = NULL;
prerender_manager_->SetNextPrerenderContents(pc);
- prerender_manager_->AddPreload(url);
+ prerender_manager_->AddSimplePreload(url);
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc->has_started());
DummyPrerenderContents* pc1 =
new DummyPrerenderContents(prerender_manager_.get(), url);
prerender_manager_->SetNextPrerenderContents(pc1);
- prerender_manager_->AddPreload(url);
+ prerender_manager_->AddSimplePreload(url);
EXPECT_EQ(pc1, prerender_manager_->next_pc());
EXPECT_FALSE(pc1->has_started());
EXPECT_EQ(pc, prerender_manager_->GetEntry(url));
@@ -117,7 +131,7 @@ TEST_F(PrerenderManagerTest, ExpireTest) {
new DummyPrerenderContents(prerender_manager_.get(), url);
DummyPrerenderContents* null = NULL;
prerender_manager_->SetNextPrerenderContents(pc);
- prerender_manager_->AddPreload(url);
+ prerender_manager_->AddSimplePreload(url);
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc->has_started());
prerender_manager_->AdvanceTime(prerender_manager_->max_prerender_age()
@@ -133,14 +147,14 @@ TEST_F(PrerenderManagerTest, DropOldestRequestTest) {
new DummyPrerenderContents(prerender_manager_.get(), url);
DummyPrerenderContents* null = NULL;
prerender_manager_->SetNextPrerenderContents(pc);
- prerender_manager_->AddPreload(url);
+ prerender_manager_->AddSimplePreload(url);
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc->has_started());
GURL url1("http://news.google.com/");
DummyPrerenderContents* pc1 =
new DummyPrerenderContents(prerender_manager_.get(), url1);
prerender_manager_->SetNextPrerenderContents(pc1);
- prerender_manager_->AddPreload(url1);
+ prerender_manager_->AddSimplePreload(url1);
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc1->has_started());
EXPECT_EQ(null, prerender_manager_->GetEntry(url));
@@ -157,21 +171,21 @@ TEST_F(PrerenderManagerTest, TwoElementPrerenderTest) {
new DummyPrerenderContents(prerender_manager_.get(), url);
DummyPrerenderContents* null = NULL;
prerender_manager_->SetNextPrerenderContents(pc);
- prerender_manager_->AddPreload(url);
+ prerender_manager_->AddSimplePreload(url);
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc->has_started());
GURL url1("http://news.google.com/");
DummyPrerenderContents* pc1 =
new DummyPrerenderContents(prerender_manager_.get(), url1);
prerender_manager_->SetNextPrerenderContents(pc1);
- prerender_manager_->AddPreload(url1);
+ prerender_manager_->AddSimplePreload(url1);
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc1->has_started());
GURL url2("http://images.google.com/");
DummyPrerenderContents* pc2 =
new DummyPrerenderContents(prerender_manager_.get(), url2);
prerender_manager_->SetNextPrerenderContents(pc2);
- prerender_manager_->AddPreload(url2);
+ prerender_manager_->AddSimplePreload(url2);
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc2->has_started());
EXPECT_EQ(null, prerender_manager_->GetEntry(url));
@@ -180,3 +194,26 @@ TEST_F(PrerenderManagerTest, TwoElementPrerenderTest) {
delete pc1;
delete pc2;
}
+
+TEST_F(PrerenderManagerTest, AliasURLTest) {
+ GURL url("http://www.google.com/");
+ GURL alias_url1("http://www.google.com/index.html");
+ GURL alias_url2("http://google.com/");
+ GURL not_an_alias_url("http://google.com/index.html");
+ std::vector<GURL> alias_urls;
+ alias_urls.push_back(alias_url1);
+ alias_urls.push_back(alias_url2);
+ DummyPrerenderContents* pc =
+ new DummyPrerenderContents(prerender_manager_.get(), url, alias_urls);
+ prerender_manager_->SetNextPrerenderContents(pc);
+ prerender_manager_->AddSimplePreload(url);
+ EXPECT_EQ(NULL, prerender_manager_->GetEntry(not_an_alias_url));
+ EXPECT_EQ(pc, prerender_manager_->GetEntry(alias_url1));
+ prerender_manager_->SetNextPrerenderContents(pc);
+ prerender_manager_->AddSimplePreload(url);
+ EXPECT_EQ(pc, prerender_manager_->GetEntry(alias_url2));
+ prerender_manager_->SetNextPrerenderContents(pc);
+ prerender_manager_->AddSimplePreload(url);
+ EXPECT_EQ(pc, prerender_manager_->GetEntry(url));
+ delete pc;
+}
diff --git a/chrome/browser/prerender/prerender_resource_handler.cc b/chrome/browser/prerender/prerender_resource_handler.cc
index 507782e..652e89b 100644
--- a/chrome/browser/prerender/prerender_resource_handler.cc
+++ b/chrome/browser/prerender/prerender_resource_handler.cc
@@ -100,8 +100,10 @@ bool PrerenderResourceHandler::OnRequestRedirected(int request_id,
bool* defer) {
bool will_redirect = next_handler_->OnRequestRedirected(
request_id, url, response, defer);
- if (will_redirect)
+ if (will_redirect) {
+ alias_urls_.push_back(url);
url_ = url;
+ }
return will_redirect;
}
@@ -117,7 +119,8 @@ bool PrerenderResourceHandler::OnResponseStarted(int request_id,
NewRunnableMethod(
this,
&PrerenderResourceHandler::RunCallbackFromUIThread,
- url_));
+ url_,
+ alias_urls_));
}
return next_handler_->OnResponseStarted(request_id, response);
}
@@ -126,8 +129,10 @@ bool PrerenderResourceHandler::OnWillStart(int request_id,
const GURL& url,
bool* defer) {
bool will_start = next_handler_->OnWillStart(request_id, url, defer);
- if (will_start)
+ if (will_start) {
+ alias_urls_.push_back(url);
url_ = url;
+ }
return will_start;
}
@@ -154,14 +159,18 @@ void PrerenderResourceHandler::OnRequestClosed() {
next_handler_->OnRequestClosed();
}
-void PrerenderResourceHandler::RunCallbackFromUIThread(const GURL& url) {
+void PrerenderResourceHandler::RunCallbackFromUIThread(const GURL& url,
+ const std::vector<GURL>&
+ alias_urls) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- prerender_callback_->Run(url);
+ prerender_callback_->Run(url, alias_urls);
}
-void PrerenderResourceHandler::StartPrerender(const GURL& url) {
+void PrerenderResourceHandler::StartPrerender(const GURL& url,
+ const std::vector<GURL>&
+ alias_urls) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- prerender_manager_->AddPreload(url);
+ prerender_manager_->AddPreload(url, alias_urls);
}
void PrerenderResourceHandler::set_prerender_duration(base::TimeDelta dt) {
diff --git a/chrome/browser/prerender/prerender_resource_handler.h b/chrome/browser/prerender/prerender_resource_handler.h
index db825e7..b7a36f6 100644
--- a/chrome/browser/prerender/prerender_resource_handler.h
+++ b/chrome/browser/prerender/prerender_resource_handler.h
@@ -71,7 +71,8 @@ class PrerenderResourceHandler : public ResourceHandler {
private:
friend class PrerenderResourceHandlerTest;
- typedef Callback1<const GURL&>::Type PrerenderCallback;
+ typedef Callback2<const GURL&, const std::vector<GURL>&>::Type
+ PrerenderCallback;
static const int kDefaultPrerenderDurationSeconds;
@@ -81,11 +82,16 @@ class PrerenderResourceHandler : public ResourceHandler {
PrerenderCallback* callback);
virtual ~PrerenderResourceHandler();
- void RunCallbackFromUIThread(const GURL& url);
- void StartPrerender(const GURL& url);
+ void RunCallbackFromUIThread(const GURL& url,
+ const std::vector<GURL>& alias_urls);
+ void StartPrerender(const GURL& url,
+ const std::vector<GURL>& alias_urls);
void set_prerender_duration(base::TimeDelta prerender_duration);
void set_get_current_time_function(GetCurrentTimeFunction get_current_time);
+ // The set of URLs that are aliases to the URL to be prerendered,
+ // as a result of redirects.
+ std::vector<GURL> alias_urls_;
GURL url_;
scoped_refptr<ResourceHandler> next_handler_;
scoped_refptr<PrerenderManager> prerender_manager_;
diff --git a/chrome/browser/prerender/prerender_resource_handler_unittest.cc b/chrome/browser/prerender/prerender_resource_handler_unittest.cc
index 92ae2e3..110c4cc 100644
--- a/chrome/browser/prerender/prerender_resource_handler_unittest.cc
+++ b/chrome/browser/prerender/prerender_resource_handler_unittest.cc
@@ -100,8 +100,9 @@ class PrerenderResourceHandlerTest : public testing::Test {
pre_handler_->set_get_current_time_function(&FixedGetCurrentTime);
}
- void SetLastHandledURL(const GURL& url) {
+ void SetLastHandledURL(const GURL& url, const std::vector<GURL>& alias_urls) {
last_handled_url_ = url;
+ alias_urls_ = alias_urls;
}
// Common logic shared by many of the tests
@@ -125,6 +126,12 @@ class PrerenderResourceHandlerTest : public testing::Test {
loop_.RunAllPending();
}
+ // Test whether a given URL is part of alias_urls_.
+ bool ContainsAliasURL(const GURL& url) {
+ return std::find(alias_urls_.begin(), alias_urls_.end(), url)
+ != alias_urls_.end();
+ }
+
base::TimeDelta prerender_duration_;
scoped_refptr<MockResourceHandler> mock_handler_;
scoped_refptr<PrerenderResourceHandler> pre_handler_;
@@ -132,6 +139,7 @@ class PrerenderResourceHandlerTest : public testing::Test {
BrowserThread ui_thread_;
GURL last_handled_url_;
GURL default_url_;
+ std::vector<GURL> alias_urls_;
};
namespace {
@@ -208,7 +216,9 @@ TEST_F(PrerenderResourceHandlerTest, PrerenderRedirect) {
EXPECT_TRUE(last_handled_url_.is_empty());
loop_.RunAllPending();
EXPECT_EQ(url_redirect, last_handled_url_);
+ EXPECT_EQ(true, ContainsAliasURL(url_redirect));
+ EXPECT_EQ(true, ContainsAliasURL(default_url_));
+ EXPECT_EQ(2, static_cast<int>(alias_urls_.size()));
}
}
-