diff options
author | tburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-18 23:46:38 +0000 |
---|---|---|
committer | tburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-18 23:46:38 +0000 |
commit | f39506a82dc772467faef96b9e9a4678733bc969 (patch) | |
tree | 670240fe497d5c0f6de68fd5a4ae12649676c58f /chrome/browser/prerender | |
parent | 7837be66093e1ad899de26542ed5cfc6a69a74e4 (diff) | |
download | chromium_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.cc | 48 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_contents.h | 25 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.cc | 14 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.h | 10 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager_unittest.cc | 59 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_resource_handler.cc | 23 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_resource_handler.h | 12 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_resource_handler_unittest.cc | 14 |
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())); } } - |