summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-21 15:45:35 +0000
committermmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-21 15:45:35 +0000
commitc4de5dfacd5f7fa135ee7069c9bfe7292c7d4c99 (patch)
treeb25c6f8642cca01fd9f5b16d699c34ecd78a4a0d
parent5458ef367834a5657cd36f5dac29c110329523d0 (diff)
downloadchromium_src-c4de5dfacd5f7fa135ee7069c9bfe7292c7d4c99.zip
chromium_src-c4de5dfacd5f7fa135ee7069c9bfe7292c7d4c99.tar.gz
chromium_src-c4de5dfacd5f7fa135ee7069c9bfe7292c7d4c99.tar.bz2
Adds a RenderWidgetHostView for prerendering RenderViewHosts.
This fixes prerendered RenderViews having 0 size until they're displayed. Also cancels prerendering if the source RenderViewHost is closed before prerendering starts. BUG=71221 TEST=PrerenderBrowserTest.PrerenderSize PrerenderManagerTest.SourceRenderViewClosed Review URL: http://codereview.chromium.org/6685012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82491 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/prerender/prerender_browsertest.cc12
-rw-r--r--chrome/browser/prerender/prerender_contents.cc15
-rw-r--r--chrome/browser/prerender/prerender_contents.h8
-rw-r--r--chrome/browser/prerender/prerender_final_status.h1
-rw-r--r--chrome/browser/prerender/prerender_manager.cc28
-rw-r--r--chrome/browser/prerender/prerender_manager.h15
-rw-r--r--chrome/browser/prerender/prerender_manager_unittest.cc223
-rw-r--r--chrome/browser/prerender/prerender_render_widget_host_view.cc306
-rw-r--r--chrome/browser/prerender/prerender_render_widget_host_view.h133
-rw-r--r--chrome/browser/prerender/prerender_resource_handler.cc7
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/test/data/prerender/prerender_size.html25
-rw-r--r--content/browser/tab_contents/render_view_host_manager.cc12
13 files changed, 670 insertions, 117 deletions
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 80450a5..a0e80d0 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <deque>
+
#include "base/command_line.h"
#include "base/path_service.h"
#include "base/string_util.h"
@@ -21,8 +23,6 @@
#include "net/url_request/url_request_context_getter.h"
#include "ui/base/l10n/l10n_util.h"
-#include <deque>
-
// Prerender tests work as follows:
//
// A page with a prefetch link to the test page is loaded. Once prerendered,
@@ -662,4 +662,12 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5VideoJs) {
1);
}
+// Checks that scripts can retrieve the correct window size while prerendering.
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderWindowSize) {
+ PrerenderTestURL("files/prerender/prerender_size.html",
+ FINAL_STATUS_USED,
+ 1);
+ NavigateToDestURL();
+}
+
} // namespace prerender
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index 0134e34..2d325955 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/prerender/prerender_final_status.h"
#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_render_widget_host_view.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_preferences_util.h"
#include "chrome/browser/ui/login/login_prompt.h"
@@ -87,9 +88,12 @@ PrerenderContents::Factory* PrerenderContents::CreateFactory() {
return new PrerenderContentsFactoryImpl();
}
-void PrerenderContents::StartPrerendering() {
+void PrerenderContents::StartPrerendering(
+ const RenderViewHost* source_render_view_host) {
DCHECK(profile_ != NULL);
DCHECK(!prerendering_has_started_);
+ DCHECK(source_render_view_host != NULL);
+ DCHECK(source_render_view_host->view() != NULL);
prerendering_has_started_ = true;
SiteInstance* site_instance = SiteInstance::CreateSiteInstance(profile_);
render_view_host_ = new RenderViewHost(site_instance, this, MSG_ROUTING_NONE,
@@ -106,9 +110,12 @@ void PrerenderContents::StartPrerendering() {
// Create the RenderView, so it can receive messages.
render_view_host_->CreateRenderView(string16());
- // Hide the RVH, so that we will run at a lower CPU priority.
- // Once the RVH is being swapped into a tab, we will Restore it again.
- render_view_host_->WasHidden();
+ // Give the RVH a PrerenderRenderWidgetHostView, both so its size can be set
+ // and so that the prerender can be cancelled under certain circumstances.
+ PrerenderRenderWidgetHostView* view =
+ new PrerenderRenderWidgetHostView(render_view_host_, this);
+ view->Init(source_render_view_host->view());
+
// Register this with the ResourceDispatcherHost as a prerender
// RenderViewHost. This must be done before the Navigate message to catch all
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h
index a2c919c..56ed08e 100644
--- a/chrome/browser/prerender/prerender_contents.h
+++ b/chrome/browser/prerender/prerender_contents.h
@@ -20,10 +20,11 @@
#include "content/common/window_container_type.h"
#include "webkit/glue/window_open_disposition.h"
+class RenderViewHost;
class TabContents;
struct FaviconURL;
-struct WebPreferences;
struct ViewHostMsg_FrameNavigate_Params;
+struct WebPreferences;
namespace base {
class ProcessMetrics;
@@ -66,7 +67,10 @@ class PrerenderContents : public RenderViewHostDelegate,
static Factory* CreateFactory();
- virtual void StartPrerendering();
+ // |source_render_view_host| is the RenderViewHost that initiated
+ // prerendering. It must be non-NULL and have its own view. It is used
+ // solely to determine the window bounds while prerendering.
+ virtual void StartPrerendering(const RenderViewHost* source_render_view_host);
// Verifies that the prerendering is not using too many resources, and kills
// it if not.
diff --git a/chrome/browser/prerender/prerender_final_status.h b/chrome/browser/prerender/prerender_final_status.h
index 19aa715..7a14986 100644
--- a/chrome/browser/prerender/prerender_final_status.h
+++ b/chrome/browser/prerender/prerender_final_status.h
@@ -30,6 +30,7 @@ enum FinalStatus {
FINAL_STATUS_PENDING_SKIPPED,
FINAL_STATUS_CONTROL_GROUP,
FINAL_STATUS_HTML5_MEDIA,
+ FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED,
FINAL_STATUS_MAX,
};
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 5bacafb..06507e0 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -134,9 +134,11 @@ void PrerenderManager::SetPrerenderContentsFactory(
prerender_contents_factory_.reset(prerender_contents_factory);
}
-bool PrerenderManager::AddPreload(const GURL& url,
- const std::vector<GURL>& alias_urls,
- const GURL& referrer) {
+bool PrerenderManager::AddPreload(
+ const std::pair<int, int>& child_route_id_pair,
+ const GURL& url,
+ const std::vector<GURL>& alias_urls,
+ const GURL& referrer) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DeleteOldEntries();
if (FindEntry(url))
@@ -177,6 +179,20 @@ bool PrerenderManager::AddPreload(const GURL& url,
return false;
}
+ RenderViewHost* source_render_view_host = NULL;
+ // This test should fail only during unit tests.
+ if (child_route_id_pair.first != -1) {
+ source_render_view_host =
+ RenderViewHost::FromID(child_route_id_pair.first,
+ child_route_id_pair.second);
+ // Don't prerender page if parent RenderViewHost no longer exists, or it has
+ // no view. The latter should only happen when the RenderView has closed.
+ if (!source_render_view_host || !source_render_view_host->view()) {
+ RecordFinalStatus(FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED);
+ return false;
+ }
+ }
+
// TODO(cbentzel): Move invalid checks here instead of PrerenderContents?
PrerenderContentsData data(CreatePrerenderContents(url, all_alias_urls,
referrer),
@@ -187,7 +203,7 @@ bool PrerenderManager::AddPreload(const GURL& url,
data.contents_->set_final_status(FINAL_STATUS_CONTROL_GROUP);
} else {
last_prerender_start_time_ = GetCurrentTimeTicks();
- data.contents_->StartPrerendering();
+ data.contents_->StartPrerendering(source_render_view_host);
}
while (prerender_list_.size() > max_elements_) {
data = prerender_list_.front();
@@ -200,7 +216,7 @@ bool PrerenderManager::AddPreload(const GURL& url,
}
void PrerenderManager::AddPendingPreload(
- const std::pair<int,int>& child_route_id_pair,
+ const std::pair<int, int>& child_route_id_pair,
const GURL& url,
const std::vector<GURL>& alias_urls,
const GURL& referrer) {
@@ -317,7 +333,7 @@ bool PrerenderManager::MaybeUsePreloadedPage(TabContents* tc, const GURL& url) {
for (std::vector<PendingContentsData>::iterator content_it =
pending_it->second.begin();
content_it != pending_it->second.end(); ++content_it) {
- AddPreload(content_it->url_, content_it->alias_urls_,
+ AddPreload(pending_it->first, content_it->url_, content_it->alias_urls_,
content_it->referrer_);
}
pending_prerender_list_.erase(pending_it);
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index 8b9dd00..51d31ac 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -53,11 +53,16 @@ class PrerenderManager : public base::RefCountedThreadSafe<PrerenderManager> {
// Owned by a Profile object for the lifetime of the profile.
explicit PrerenderManager(Profile* profile);
- // Preloads the URL supplied. alias_urls indicates URLs that redirect
- // to the same URL to be preloaded. Returns true if the URL was added,
- // false if it was not.
- bool AddPreload(const GURL& url, const std::vector<GURL>& alias_urls,
- const GURL& referrer);
+ // Preloads |url| if valid. |alias_urls| indicates URLs that redirect
+ // to the same URL to be preloaded. |child_route_id_pair| identifies the
+ // RenderViewHost that the prerender request came from and is used to
+ // set the initial window size of the RenderViewHost used for prerendering.
+ // Returns true if the URL was added, false if it was not.
+ bool AddPreload(
+ const std::pair<int, int>& child_route_id_pair,
+ const GURL& url,
+ const std::vector<GURL>& alias_urls,
+ const GURL& referrer);
void AddPendingPreload(const std::pair<int, int>& child_route_id_pair,
const GURL& url,
diff --git a/chrome/browser/prerender/prerender_manager_unittest.cc b/chrome/browser/prerender/prerender_manager_unittest.cc
index 49a4485..6ea9625 100644
--- a/chrome/browser/prerender/prerender_manager_unittest.cc
+++ b/chrome/browser/prerender/prerender_manager_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/memory/scoped_vector.h"
#include "base/time.h"
#include "chrome/browser/prerender/prerender_contents.h"
#include "chrome/browser/prerender/prerender_manager.h"
@@ -19,15 +20,6 @@ class DummyPrerenderContents : public PrerenderContents {
public:
DummyPrerenderContents(PrerenderManager* prerender_manager,
const GURL& url,
- FinalStatus expected_final_status)
- : PrerenderContents(prerender_manager, NULL, url,
- std::vector<GURL>(), GURL()),
- has_started_(false),
- expected_final_status_(expected_final_status) {
- }
-
- DummyPrerenderContents(PrerenderManager* prerender_manager,
- const GURL& url,
const std::vector<GURL> alias_urls,
FinalStatus expected_final_status)
: PrerenderContents(prerender_manager, NULL, url, alias_urls, GURL()),
@@ -39,7 +31,8 @@ class DummyPrerenderContents : public PrerenderContents {
EXPECT_EQ(expected_final_status_, final_status());
}
- virtual void StartPrerendering() OVERRIDE {
+ virtual void StartPrerendering(
+ const RenderViewHost* source_render_view_host) OVERRIDE {
has_started_ = true;
}
@@ -55,6 +48,8 @@ class DummyPrerenderContents : public PrerenderContents {
bool has_started() const { return has_started_; }
+ FinalStatus expected_final_status() const { return expected_final_status_; }
+
private:
bool has_started_;
FinalStatus expected_final_status_;
@@ -78,13 +73,31 @@ class TestPrerenderManager : public PrerenderManager {
time_ticks_ += delta;
}
- void SetNextPrerenderContents(PrerenderContents* pc) {
- next_pc_.reset(pc);
+ DummyPrerenderContents* CreateNextPrerenderContents(
+ const GURL& url,
+ FinalStatus expected_final_status) {
+ DummyPrerenderContents* pc =
+ new DummyPrerenderContents(this, url, std::vector<GURL>(),
+ expected_final_status);
+ SetNextPrerenderContents(pc);
+ return pc;
+ }
+
+ DummyPrerenderContents* CreateNextPrerenderContents(
+ const GURL& url,
+ const std::vector<GURL> alias_urls,
+ FinalStatus expected_final_status) {
+ DummyPrerenderContents* pc =
+ new DummyPrerenderContents(this, url, alias_urls,
+ expected_final_status);
+ SetNextPrerenderContents(pc);
+ return pc;
}
// Shorthand to add a simple preload with no aliases.
bool AddSimplePreload(const GURL& url) {
- return AddPreload(url, std::vector<GURL>(), GURL());
+ return AddPreload(std::pair<int, int>(-1, -1), url, std::vector<GURL>(),
+ GURL());
}
bool IsPendingEntry(const GURL& url) {
@@ -93,6 +106,12 @@ class TestPrerenderManager : public PrerenderManager {
void set_rate_limit_enabled(bool enabled) { rate_limit_enabled_ = true; }
+ // Shorthand to add a simple preload with aliases.
+ bool AddSimplePreloadWithAliases(const GURL& url,
+ const std::vector<GURL>& alias_urls) {
+ return AddPreload(std::pair<int, int>(-1, -1), url, alias_urls, GURL());
+ }
+
PrerenderContents* next_pc() { return next_pc_.get(); }
protected:
@@ -101,9 +120,24 @@ class TestPrerenderManager : public PrerenderManager {
next_pc()->set_final_status(
FINAL_STATUS_MANAGER_SHUTDOWN);
}
+ // Set the final status for all PrerenderContents with an expected final
+ // status of FINAL_STATUS_USED. These values are normally set when the
+ // prerendered RVH is swapped into a tab, which doesn't happen in these
+ // unit tests.
+ for (ScopedVector<PrerenderContents>::iterator it = used_pcs_.begin();
+ it != used_pcs_.end(); ++it) {
+ (*it)->set_final_status(FINAL_STATUS_USED);
+ }
}
private:
+ void SetNextPrerenderContents(DummyPrerenderContents* pc) {
+ DCHECK(!next_pc_.get());
+ next_pc_.reset(pc);
+ if (pc->expected_final_status() == FINAL_STATUS_USED)
+ used_pcs_.push_back(pc);
+ }
+
virtual base::Time GetCurrentTime() const OVERRIDE {
return time_;
}
@@ -123,6 +157,9 @@ class TestPrerenderManager : public PrerenderManager {
base::Time time_;
base::TimeTicks time_ticks_;
scoped_ptr<PrerenderContents> next_pc_;
+ // PrerenderContents with an |expected_final_status| of FINAL_STATUS_USED,
+ // tracked so they will be automatically deleted.
+ ScopedVector<PrerenderContents> used_pcs_;
};
class RestorePrerenderMode {
@@ -160,15 +197,12 @@ TEST_F(PrerenderManagerTest, EmptyTest) {
TEST_F(PrerenderManagerTest, FoundTest) {
GURL url("http://www.google.com/");
DummyPrerenderContents* pc =
- new DummyPrerenderContents(prerender_manager_.get(),
- url,
- FINAL_STATUS_USED);
- prerender_manager_->SetNextPrerenderContents(pc);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_USED);
EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
EXPECT_TRUE(pc->has_started());
ASSERT_EQ(pc, prerender_manager_->GetEntry(url));
- pc->set_final_status(FINAL_STATUS_USED);
- delete pc;
}
// Make sure that if queue a request, and a second prerender request for the
@@ -176,34 +210,33 @@ TEST_F(PrerenderManagerTest, FoundTest) {
TEST_F(PrerenderManagerTest, DropSecondRequestTest) {
GURL url("http://www.google.com/");
DummyPrerenderContents* pc =
- new DummyPrerenderContents(prerender_manager_.get(), url,
- FINAL_STATUS_USED);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_USED);
DummyPrerenderContents* null = NULL;
- prerender_manager_->SetNextPrerenderContents(pc);
EXPECT_TRUE(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_->CreateNextPrerenderContents(
+ url,
FINAL_STATUS_MANAGER_SHUTDOWN);
- prerender_manager_->SetNextPrerenderContents(pc1);
EXPECT_FALSE(prerender_manager_->AddSimplePreload(url));
EXPECT_EQ(pc1, prerender_manager_->next_pc());
EXPECT_FALSE(pc1->has_started());
+
ASSERT_EQ(pc, prerender_manager_->GetEntry(url));
- pc->set_final_status(FINAL_STATUS_USED);
- delete pc;
}
// Ensure that we expire a prerendered page after the max. permitted time.
TEST_F(PrerenderManagerTest, ExpireTest) {
GURL url("http://www.google.com/");
DummyPrerenderContents* pc =
- new DummyPrerenderContents(prerender_manager_.get(), url,
- FINAL_STATUS_TIMED_OUT);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_TIMED_OUT);
DummyPrerenderContents* null = NULL;
- prerender_manager_->SetNextPrerenderContents(pc);
EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc->has_started());
@@ -217,25 +250,25 @@ TEST_F(PrerenderManagerTest, ExpireTest) {
TEST_F(PrerenderManagerTest, DropOldestRequestTest) {
GURL url("http://www.google.com/");
DummyPrerenderContents* pc =
- new DummyPrerenderContents(prerender_manager_.get(), url,
- FINAL_STATUS_EVICTED);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_EVICTED);
DummyPrerenderContents* null = NULL;
- prerender_manager_->SetNextPrerenderContents(pc);
EXPECT_TRUE(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,
- FINAL_STATUS_USED);
- prerender_manager_->SetNextPrerenderContents(pc1);
+ prerender_manager_->CreateNextPrerenderContents(
+ url1,
+ FINAL_STATUS_USED);
EXPECT_TRUE(prerender_manager_->AddSimplePreload(url1));
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc1->has_started());
+
ASSERT_EQ(null, prerender_manager_->GetEntry(url));
ASSERT_EQ(pc1, prerender_manager_->GetEntry(url1));
- pc1->set_final_status(FINAL_STATUS_USED);
- delete pc1;
}
// Two element prerender test. Ensure that the LRU operates correctly if we
@@ -244,36 +277,35 @@ TEST_F(PrerenderManagerTest, TwoElementPrerenderTest) {
prerender_manager_->set_max_elements(2);
GURL url("http://www.google.com/");
DummyPrerenderContents* pc =
- new DummyPrerenderContents(prerender_manager_.get(), url,
- FINAL_STATUS_EVICTED);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_EVICTED);
DummyPrerenderContents* null = NULL;
- prerender_manager_->SetNextPrerenderContents(pc);
EXPECT_TRUE(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,
- FINAL_STATUS_USED);
- prerender_manager_->SetNextPrerenderContents(pc1);
+ prerender_manager_->CreateNextPrerenderContents(
+ url1,
+ FINAL_STATUS_USED);
EXPECT_TRUE(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,
- FINAL_STATUS_USED);
- prerender_manager_->SetNextPrerenderContents(pc2);
+ prerender_manager_->CreateNextPrerenderContents(
+ url2,
+ FINAL_STATUS_USED);
EXPECT_TRUE(prerender_manager_->AddSimplePreload(url2));
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc2->has_started());
+
ASSERT_EQ(null, prerender_manager_->GetEntry(url));
ASSERT_EQ(pc1, prerender_manager_->GetEntry(url1));
ASSERT_EQ(pc2, prerender_manager_->GetEntry(url2));
- pc1->set_final_status(FINAL_STATUS_USED);
- delete pc1;
- pc2->set_final_status(FINAL_STATUS_USED);
- delete pc2;
}
TEST_F(PrerenderManagerTest, AliasURLTest) {
@@ -284,41 +316,41 @@ TEST_F(PrerenderManagerTest, AliasURLTest) {
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,
- FINAL_STATUS_USED);
+
// Test that all of the aliases work, but nont_an_alias_url does not.
- prerender_manager_->SetNextPrerenderContents(pc);
- EXPECT_TRUE(prerender_manager_->AddPreload(url, alias_urls, GURL()));
+ DummyPrerenderContents* pc =
+ prerender_manager_->CreateNextPrerenderContents(
+ url, alias_urls, FINAL_STATUS_USED);
+ EXPECT_TRUE(prerender_manager_->AddSimplePreloadWithAliases(url, alias_urls));
ASSERT_EQ(NULL, prerender_manager_->GetEntry(not_an_alias_url));
ASSERT_EQ(pc, prerender_manager_->GetEntry(alias_url1));
- prerender_manager_->SetNextPrerenderContents(pc);
- EXPECT_TRUE(prerender_manager_->AddPreload(url, alias_urls, GURL()));
+ pc = prerender_manager_->CreateNextPrerenderContents(
+ url, alias_urls, FINAL_STATUS_USED);
+ EXPECT_TRUE(prerender_manager_->AddSimplePreloadWithAliases(url, alias_urls));
ASSERT_EQ(pc, prerender_manager_->GetEntry(alias_url2));
- prerender_manager_->SetNextPrerenderContents(pc);
- EXPECT_TRUE(prerender_manager_->AddPreload(url, alias_urls, GURL()));
+ pc = prerender_manager_->CreateNextPrerenderContents(
+ url, alias_urls, FINAL_STATUS_USED);
+ EXPECT_TRUE(prerender_manager_->AddSimplePreloadWithAliases(url, alias_urls));
ASSERT_EQ(pc, prerender_manager_->GetEntry(url));
// Test that alias URLs can not be added.
- prerender_manager_->SetNextPrerenderContents(pc);
- EXPECT_TRUE(prerender_manager_->AddPreload(url, alias_urls, GURL()));
+ pc = prerender_manager_->CreateNextPrerenderContents(
+ url, alias_urls, FINAL_STATUS_USED);
+ EXPECT_TRUE(prerender_manager_->AddSimplePreloadWithAliases(url, alias_urls));
EXPECT_FALSE(prerender_manager_->AddSimplePreload(url));
EXPECT_FALSE(prerender_manager_->AddSimplePreload(alias_url1));
EXPECT_FALSE(prerender_manager_->AddSimplePreload(alias_url2));
ASSERT_EQ(pc, prerender_manager_->GetEntry(url));
-
- pc->set_final_status(FINAL_STATUS_USED);
- delete pc;
}
// Ensure that we ignore prerender requests within the rate limit.
TEST_F(PrerenderManagerTest, RateLimitInWindowTest) {
GURL url("http://www.google.com/");
DummyPrerenderContents* pc =
- new DummyPrerenderContents(prerender_manager_.get(), url,
- FINAL_STATUS_MANAGER_SHUTDOWN);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_MANAGER_SHUTDOWN);
DummyPrerenderContents* null = NULL;
- prerender_manager_->SetNextPrerenderContents(pc);
EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc->has_started());
@@ -327,10 +359,9 @@ TEST_F(PrerenderManagerTest, RateLimitInWindowTest) {
prerender_manager_->AdvanceTimeTicks(base::TimeDelta::FromMilliseconds(1));
GURL url1("http://news.google.com/");
- DummyPrerenderContents* rate_limit_pc =
- new DummyPrerenderContents(prerender_manager_.get(), url1,
- FINAL_STATUS_MANAGER_SHUTDOWN);
- prerender_manager_->SetNextPrerenderContents(rate_limit_pc);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_MANAGER_SHUTDOWN);
EXPECT_FALSE(prerender_manager_->AddSimplePreload(url1));
prerender_manager_->set_rate_limit_enabled(false);
}
@@ -339,10 +370,10 @@ TEST_F(PrerenderManagerTest, RateLimitInWindowTest) {
TEST_F(PrerenderManagerTest, RateLimitOutsideWindowTest) {
GURL url("http://www.google.com/");
DummyPrerenderContents* pc =
- new DummyPrerenderContents(prerender_manager_.get(), url,
- FINAL_STATUS_EVICTED);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_EVICTED);
DummyPrerenderContents* null = NULL;
- prerender_manager_->SetNextPrerenderContents(pc);
EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(pc->has_started());
@@ -352,9 +383,9 @@ TEST_F(PrerenderManagerTest, RateLimitOutsideWindowTest) {
GURL url1("http://news.google.com/");
DummyPrerenderContents* rate_limit_pc =
- new DummyPrerenderContents(prerender_manager_.get(), url1,
- FINAL_STATUS_MANAGER_SHUTDOWN);
- prerender_manager_->SetNextPrerenderContents(rate_limit_pc);
+ prerender_manager_->CreateNextPrerenderContents(
+ url1,
+ FINAL_STATUS_MANAGER_SHUTDOWN);
EXPECT_TRUE(prerender_manager_->AddSimplePreload(url1));
EXPECT_EQ(null, prerender_manager_->next_pc());
EXPECT_TRUE(rate_limit_pc->has_started());
@@ -364,10 +395,9 @@ TEST_F(PrerenderManagerTest, RateLimitOutsideWindowTest) {
TEST_F(PrerenderManagerTest, PendingPreloadTest) {
GURL url("http://www.google.com/");
DummyPrerenderContents* pc =
- new DummyPrerenderContents(prerender_manager_.get(),
- url,
- FINAL_STATUS_USED);
- prerender_manager_->SetNextPrerenderContents(pc);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_USED);
EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
int child_id;
@@ -385,18 +415,14 @@ TEST_F(PrerenderManagerTest, PendingPreloadTest) {
EXPECT_TRUE(prerender_manager_->IsPendingEntry(pending_url));
EXPECT_TRUE(pc->has_started());
ASSERT_EQ(pc, prerender_manager_->GetEntry(url));
- pc->set_final_status(FINAL_STATUS_USED);
-
- delete pc;
}
TEST_F(PrerenderManagerTest, PendingPreloadSkippedTest) {
GURL url("http://www.google.com/");
DummyPrerenderContents* pc =
- new DummyPrerenderContents(prerender_manager_.get(),
- url,
- FINAL_STATUS_TIMED_OUT);
- prerender_manager_->SetNextPrerenderContents(pc);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_TIMED_OUT);
int child_id;
int route_id;
@@ -444,12 +470,23 @@ TEST_F(PrerenderManagerTest, ControlGroup) {
PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
GURL url("http://www.google.com/");
DummyPrerenderContents* pc =
- new DummyPrerenderContents(prerender_manager_.get(),
- url,
- FINAL_STATUS_CONTROL_GROUP);
- prerender_manager_->SetNextPrerenderContents(pc);
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_CONTROL_GROUP);
EXPECT_TRUE(prerender_manager_->AddSimplePreload(url));
EXPECT_FALSE(pc->has_started());
}
+// Tests that prerendering is cancelled when the source render view does not
+// exist. On failure, the DCHECK in CreatePrerenderContents() above should be
+// triggered.
+TEST_F(PrerenderManagerTest, SourceRenderViewClosed) {
+ GURL url("http://www.google.com/");
+ prerender_manager_->CreateNextPrerenderContents(
+ url,
+ FINAL_STATUS_MANAGER_SHUTDOWN);
+ EXPECT_FALSE(prerender_manager_->AddPreload(
+ std::pair<int, int>(100, 100), url, std::vector<GURL>(), GURL()));
+}
+
} // namespace prerender
diff --git a/chrome/browser/prerender/prerender_render_widget_host_view.cc b/chrome/browser/prerender/prerender_render_widget_host_view.cc
new file mode 100644
index 0000000..f5585de
--- /dev/null
+++ b/chrome/browser/prerender/prerender_render_widget_host_view.cc
@@ -0,0 +1,306 @@
+// Copyright (c) 2011 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/browser/prerender/prerender_render_widget_host_view.h"
+
+#include "base/logging.h"
+#include "chrome/browser/prerender/prerender_contents.h"
+#include "chrome/browser/prerender/prerender_final_status.h"
+#include "content/browser/renderer_host/render_widget_host.h"
+
+namespace prerender {
+
+PrerenderRenderWidgetHostView::PrerenderRenderWidgetHostView(
+ RenderWidgetHost* render_widget_host,
+ PrerenderContents* prerender_contents)
+ : render_widget_host_(render_widget_host),
+ prerender_contents_(prerender_contents) {
+ render_widget_host_->set_view(this);
+}
+
+PrerenderRenderWidgetHostView::~PrerenderRenderWidgetHostView() {
+}
+
+void PrerenderRenderWidgetHostView::Init(RenderWidgetHostView* view) {
+#if defined(OS_MACOSX)
+ cocoa_view_bounds_ = view->GetViewBounds();
+ root_window_rect_ = view->GetRootWindowRect();
+#endif // defined(OS_MACOSX)
+ SetBounds(view->GetViewBounds());
+
+ // PrerenderRenderWidgetHostViews are always hidden. This reduces the
+ // process priority of the render process while prerendering, and prevents it
+ // from painting anything until the page is actually displayed.
+ WasHidden();
+}
+
+void PrerenderRenderWidgetHostView::InitAsPopup(
+ RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::InitAsFullscreen() {
+ NOTREACHED();
+}
+
+RenderWidgetHost* PrerenderRenderWidgetHostView::GetRenderWidgetHost() const {
+ return render_widget_host_;
+}
+
+void PrerenderRenderWidgetHostView::DidBecomeSelected() {
+ // The View won't be shown during prerendering.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::WasHidden() {
+ render_widget_host_->WasHidden();
+}
+
+void PrerenderRenderWidgetHostView::SetSize(const gfx::Size& size) {
+ SetBounds(gfx::Rect(GetViewBounds().origin(), size));
+}
+
+void PrerenderRenderWidgetHostView::SetBounds(const gfx::Rect& rect) {
+ bounds_ = rect;
+ if (render_widget_host_)
+ render_widget_host_->WasResized();
+}
+
+gfx::NativeView PrerenderRenderWidgetHostView::GetNativeView() {
+ return NULL;
+}
+
+void PrerenderRenderWidgetHostView::MovePluginWindows(
+ const std::vector<webkit::npapi::WebPluginGeometry>& moves) {
+ // Since a PrerenderRenderWidgetHostView is always hidden and plugins are not
+ // loaded during prerendering, this will never be called.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::Focus() {
+ // A PrerenderRenderWidgetHostView can never be focused, as it's always
+ // hidden.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::Blur() {
+}
+
+bool PrerenderRenderWidgetHostView::HasFocus() {
+ return false;
+}
+
+void PrerenderRenderWidgetHostView::Show() {
+ // A PrerenderRenderWidgetHostView can never be shown, as it is not yet
+ // associated with a tab.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::Hide() {
+ WasHidden();
+}
+
+bool PrerenderRenderWidgetHostView::IsShowing() {
+ return false;
+}
+
+gfx::Rect PrerenderRenderWidgetHostView::GetViewBounds() const {
+ return bounds_;
+}
+
+void PrerenderRenderWidgetHostView::UpdateCursor(const WebCursor& cursor) {
+ // The cursor should only be updated in response to a mouse event, which
+ // hidden RenderViews don't have.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::SetIsLoading(bool is_loading) {
+ // Do nothing. PrerenderContents manages this flag.
+}
+
+void PrerenderRenderWidgetHostView::ImeUpdateTextInputState(
+ WebKit::WebTextInputType type,
+ const gfx::Rect& caret_rect) {
+ // Not called on hidden views.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::ImeCancelComposition() {
+ // Not called on hidden views.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::DidUpdateBackingStore(
+ const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
+ const std::vector<gfx::Rect>& copy_rects) {
+ // Since prerendering RenderViewsHosts are always hidden, this will not be
+ // be called.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::RenderViewGone(
+ base::TerminationStatus status, int error_code) {
+ // TODO(mmenke): This should result in the PrerenderContents cancelling the
+ // prerender itself.
+ Destroy();
+}
+
+void PrerenderRenderWidgetHostView::WillDestroyRenderWidget(
+ RenderWidgetHost* rwh) {
+ if (rwh == render_widget_host_)
+ render_widget_host_ = NULL;
+}
+
+void PrerenderRenderWidgetHostView::Destroy() {
+ delete this;
+}
+
+void PrerenderRenderWidgetHostView::SetTooltipText(
+ const std::wstring& tooltip_text) {
+ // Since this is only set on mouse move and the View can't be focused, this
+ // will never be called.
+ NOTREACHED();
+}
+
+BackingStore* PrerenderRenderWidgetHostView::AllocBackingStore(
+ const gfx::Size& size) {
+ // Since prerendering RenderViewsHosts are always hidden, this will not be
+ // be called.
+ NOTREACHED();
+ return NULL;
+}
+
+#if defined(OS_MACOSX)
+void PrerenderRenderWidgetHostView::SetTakesFocusOnlyOnMouseDown(bool flag) {
+ // This is only used by on RenderWidgetHosts currently in a TabContents.
+ NOTREACHED();
+}
+
+gfx::Rect PrerenderRenderWidgetHostView::GetViewCocoaBounds() const {
+ return cocoa_view_bounds_;
+}
+
+gfx::Rect PrerenderRenderWidgetHostView::GetRootWindowRect() {
+ return root_window_rect_;
+}
+
+void PrerenderRenderWidgetHostView::SetActive(bool active) {
+ // This view can never be made visible.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::SetWindowVisibility(bool visible) {
+ // This view can never be made visible.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::WindowFrameChanged() {
+ // Since there's no frame, and nothing to notify |this| of its change, this
+ // will never get called.
+ NOTREACHED();
+}
+
+// Since plugins are not loaded until the prerendered page is displayed, none of
+// the following functions will be called.
+void PrerenderRenderWidgetHostView::PluginFocusChanged(bool focused,
+ int plugin_id) {
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::StartPluginIme() {
+ NOTREACHED();
+}
+
+bool PrerenderRenderWidgetHostView::PostProcessEventForPluginIme(
+ const NativeWebKeyboardEvent& event) {
+ NOTREACHED();
+ return false;
+}
+
+gfx::PluginWindowHandle
+PrerenderRenderWidgetHostView::AllocateFakePluginWindowHandle(
+ bool opaque, bool root) {
+ NOTREACHED();
+ return gfx::kNullPluginWindow;
+}
+
+void PrerenderRenderWidgetHostView::DestroyFakePluginWindowHandle(
+ gfx::PluginWindowHandle window) {
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::AcceleratedSurfaceSetIOSurface(
+ gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier) {
+}
+
+void PrerenderRenderWidgetHostView::AcceleratedSurfaceSetTransportDIB(
+ gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ TransportDIB::Handle transport_dib) {
+}
+
+void PrerenderRenderWidgetHostView::AcceleratedSurfaceBuffersSwapped(
+ gfx::PluginWindowHandle window,
+ uint64 surface_id,
+ int renderer_id,
+ int32 route_id,
+ int gpu_host_id,
+ uint64 swap_buffers_count) {
+}
+
+void PrerenderRenderWidgetHostView::GpuRenderingStateDidChange() {
+}
+#endif // defined(OS_MACOSX)
+
+#if defined(TOOLKIT_USES_GTK)
+void PrerenderRenderWidgetHostView::CreatePluginContainer(
+ gfx::PluginWindowHandle id) {
+ // Since plugins are not loaded until the prerendered page is loaded, this
+ // should never be called.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::DestroyPluginContainer(
+ gfx::PluginWindowHandle id) {
+}
+
+void PrerenderRenderWidgetHostView::AcceleratedCompositingActivated(
+ bool activated) {
+}
+#endif // defined(TOOLKIT_USES_GTK)
+
+#if defined(OS_WIN)
+void PrerenderRenderWidgetHostView::WillWmDestroy() {
+}
+
+void PrerenderRenderWidgetHostView::ShowCompositorHostWindow(bool show) {
+}
+#endif // defined(OS_WIN)
+
+gfx::PluginWindowHandle
+PrerenderRenderWidgetHostView::GetCompositingSurface() {
+ return gfx::kNullPluginWindow;
+}
+
+void PrerenderRenderWidgetHostView::SetVisuallyDeemphasized(
+ const SkColor* color, bool animate) {
+ // This will not be called until the RVH is swapped into a tab.
+ NOTREACHED();
+}
+
+void PrerenderRenderWidgetHostView::SetBackground(const SkBitmap& background) {
+ // This will not be called for HTTP RenderViews.
+ NOTREACHED();
+}
+
+bool PrerenderRenderWidgetHostView::ContainsNativeView(
+ gfx::NativeView native_view) const {
+ return false;
+}
+
+} // namespace prerender
diff --git a/chrome/browser/prerender/prerender_render_widget_host_view.h b/chrome/browser/prerender/prerender_render_widget_host_view.h
new file mode 100644
index 0000000..81c278d
--- /dev/null
+++ b/chrome/browser/prerender/prerender_render_widget_host_view.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2011 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_BROWSER_PRERENDER_PRERENDER_RENDER_WIDGET_HOST_VIEW_H_
+#define CHROME_BROWSER_PRERENDER_PRERENDER_RENDER_WIDGET_HOST_VIEW_H_
+#pragma once
+
+#include <vector>
+
+#include "content/browser/renderer_host/render_widget_host_view.h"
+
+namespace prerender {
+
+class PrerenderContents;
+
+// A PrerenderRenderWidgetHostView acts as the "View" of prerendered web pages,
+// as they don't have an actual window (visible or hidden) until swapped into
+// a tab.
+class PrerenderRenderWidgetHostView : public RenderWidgetHostView {
+ public:
+ PrerenderRenderWidgetHostView(RenderWidgetHost* widget,
+ PrerenderContents* prerender_contents);
+ virtual ~PrerenderRenderWidgetHostView();
+
+ // Initializes |this| using the bounds from |view|, which must be non-NULL.
+ void Init(RenderWidgetHostView* view);
+
+ // Implementation of RenderWidgetHostView:
+ virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
+ const gfx::Rect& pos) OVERRIDE;
+ virtual void InitAsFullscreen() OVERRIDE;
+ virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE;
+ virtual void DidBecomeSelected() OVERRIDE;
+ virtual void WasHidden() OVERRIDE;
+ virtual void SetSize(const gfx::Size& size) OVERRIDE;
+ virtual void SetBounds(const gfx::Rect& rect) OVERRIDE;
+ virtual gfx::NativeView GetNativeView() OVERRIDE;
+ virtual void MovePluginWindows(
+ const std::vector<webkit::npapi::WebPluginGeometry>& moves) OVERRIDE;
+ virtual void Focus() OVERRIDE;
+ virtual void Blur() OVERRIDE;
+ virtual bool HasFocus() OVERRIDE;
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual bool IsShowing() OVERRIDE;
+ virtual gfx::Rect GetViewBounds() const OVERRIDE;
+ virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
+ virtual void SetIsLoading(bool is_loading) OVERRIDE;
+ virtual void ImeUpdateTextInputState(WebKit::WebTextInputType type,
+ const gfx::Rect& caret_rect) OVERRIDE;
+ virtual void ImeCancelComposition() OVERRIDE;
+ virtual void DidUpdateBackingStore(
+ const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
+ const std::vector<gfx::Rect>& copy_rects) OVERRIDE;
+ virtual void RenderViewGone(base::TerminationStatus status,
+ int error_code) OVERRIDE;
+ virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual void SetTooltipText(const std::wstring& tooltip_text) OVERRIDE;
+ virtual BackingStore* AllocBackingStore(const gfx::Size& size) OVERRIDE;
+
+#if defined(OS_MACOSX)
+ virtual void SetTakesFocusOnlyOnMouseDown(bool flag) OVERRIDE;
+ virtual gfx::Rect GetViewCocoaBounds() const OVERRIDE;
+ virtual gfx::Rect GetRootWindowRect() OVERRIDE;
+ virtual void SetActive(bool active) OVERRIDE;
+ virtual void SetWindowVisibility(bool visible) OVERRIDE;
+ virtual void WindowFrameChanged() OVERRIDE;
+ virtual void PluginFocusChanged(bool focused, int plugin_id) OVERRIDE;
+ virtual void StartPluginIme() OVERRIDE;
+ virtual bool PostProcessEventForPluginIme(
+ const NativeWebKeyboardEvent& event) OVERRIDE;
+
+ virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle(
+ bool opaque, bool root) OVERRIDE;
+ virtual void DestroyFakePluginWindowHandle(
+ gfx::PluginWindowHandle window) OVERRIDE;
+ virtual void AcceleratedSurfaceSetIOSurface(
+ gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 io_surface_identifier) OVERRIDE;
+ virtual void AcceleratedSurfaceSetTransportDIB(
+ gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ TransportDIB::Handle transport_dib) OVERRIDE;
+ virtual void AcceleratedSurfaceBuffersSwapped(
+ gfx::PluginWindowHandle window,
+ uint64 surface_id,
+ int renderer_id,
+ int32 route_id,
+ int gpu_host_id,
+ uint64 swap_buffers_count) OVERRIDE;
+ virtual void GpuRenderingStateDidChange() OVERRIDE;
+#endif
+
+#if defined(TOOLKIT_USES_GTK)
+ virtual void CreatePluginContainer(gfx::PluginWindowHandle id) OVERRIDE;
+ virtual void DestroyPluginContainer(gfx::PluginWindowHandle id) OVERRIDE;
+ virtual void AcceleratedCompositingActivated(bool activated) OVERRIDE;
+#endif
+
+#if defined(OS_WIN)
+ virtual void WillWmDestroy() OVERRIDE;
+ virtual void ShowCompositorHostWindow(bool show) OVERRIDE;
+#endif
+
+ virtual gfx::PluginWindowHandle GetCompositingSurface() OVERRIDE;
+ virtual void SetVisuallyDeemphasized(const SkColor* color,
+ bool animate) OVERRIDE;
+ virtual void SetBackground(const SkBitmap& background) OVERRIDE;
+
+ virtual bool ContainsNativeView(gfx::NativeView native_view) const OVERRIDE;
+
+ private:
+ RenderWidgetHost* render_widget_host_;
+ // Need this to cancel prerendering in some cases.
+ PrerenderContents* prerender_contents_;
+
+ gfx::Rect bounds_;
+#if defined(OS_MACOSX)
+ gfx::Rect cocoa_view_bounds_;
+ gfx::Rect root_window_rect_;
+#endif // defined(OS_MACOSX)
+
+ DISALLOW_COPY_AND_ASSIGN(PrerenderRenderWidgetHostView);
+};
+
+} // namespace prerender
+
+#endif // CHROME_BROWSER_PRERENDER_PRERENDER_RENDER_WIDGET_HOST_VIEW_H_
diff --git a/chrome/browser/prerender/prerender_resource_handler.cc b/chrome/browser/prerender/prerender_resource_handler.cc
index 0a7b507..dc96fd2 100644
--- a/chrome/browser/prerender/prerender_resource_handler.cc
+++ b/chrome/browser/prerender/prerender_resource_handler.cc
@@ -99,7 +99,9 @@ PrerenderResourceHandler::PrerenderResourceHandler(
PrerenderCallback* callback)
: next_handler_(next_handler),
prerender_callback_(callback),
- request_(request) {
+ request_(request),
+ child_id_(-1),
+ route_id_(-1) {
DCHECK(next_handler);
DCHECK(callback);
}
@@ -208,7 +210,8 @@ void PrerenderResourceHandler::StartPrerender(
prerender_manager_->AddPendingPreload(child_route_id_pair,
url, alias_urls, referrer);
} else {
- prerender_manager_->AddPreload(url, alias_urls, referrer);
+ prerender_manager_->AddPreload(child_route_id_pair, url, alias_urls,
+ referrer);
}
}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 49391cc..19a923d 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1639,6 +1639,8 @@
'browser/prerender/prerender_manager.h',
'browser/prerender/prerender_observer.cc',
'browser/prerender/prerender_observer.h',
+ 'browser/prerender/prerender_render_widget_host_view.cc',
+ 'browser/prerender/prerender_render_widget_host_view.h',
'browser/prerender/prerender_resource_handler.cc',
'browser/prerender/prerender_resource_handler.h',
'browser/printing/cloud_print/cloud_print_proxy_service.cc',
diff --git a/chrome/test/data/prerender/prerender_size.html b/chrome/test/data/prerender/prerender_size.html
new file mode 100644
index 0000000..025bb03
--- /dev/null
+++ b/chrome/test/data/prerender/prerender_size.html
@@ -0,0 +1,25 @@
+<html>
+<!--
+Checks that a prerendered page gets the correct window size.
+-->
+<head>
+<title>Prerender Window Size Test</title>
+
+<script>
+var width = window.innerWidth;
+var height = window.innerHeight;
+
+// Make sure width and height are positive.
+function DidPrerenderPass() {
+ return width > 0 && height > 0;
+}
+
+// Make sure width and height are the same as when prerendering.
+function DidDisplayPass() {
+ return width == window.innerWidth && height == window.innerHeight;
+}
+</script>
+
+</head>
+<body></body>
+</html>
diff --git a/content/browser/tab_contents/render_view_host_manager.cc b/content/browser/tab_contents/render_view_host_manager.cc
index 973a1d0..d08f6ab 100644
--- a/content/browser/tab_contents/render_view_host_manager.cc
+++ b/content/browser/tab_contents/render_view_host_manager.cc
@@ -691,15 +691,21 @@ void RenderViewHostManager::SwapInRenderViewHost(RenderViewHost* rvh) {
// Swap in the new view and make it active.
render_view_host_ = rvh;
render_view_host_->set_delegate(render_view_delegate_);
+ // Remove old RenderWidgetHostView with mocked out methods so it can be
+ // replaced with a new one that's a child of |delegate_|'s view.
+ scoped_ptr<RenderWidgetHostView> old_view(render_view_host_->view());
+ render_view_host_->set_view(NULL);
delegate_->CreateViewAndSetSizeForRVH(render_view_host_);
render_view_host_->ActivateDeferredPluginHandles();
// If the view is gone, then this RenderViewHost died while it was hidden.
// We ignored the RenderViewGone call at the time, so we should send it now
// to make sure the sad tab shows up, etc.
if (render_view_host_->view()) {
- // TODO(tburkard,cbentzel): Figure out why this hack is needed and/or
- // if it can be removed. On Windows, prerendering will not work without
- // doing a Hide before the Show.
+ // The Hide() is needed to sync the state of |render_view_host_|, which is
+ // hidden, with the newly created view, which does not know the
+ // RenderViewHost is hidden.
+ // TODO(tburkard,cbentzel): Figure out if this hack can be removed
+ // (http://crbug.com/79891).
render_view_host_->view()->Hide();
render_view_host_->view()->Show();
}