diff options
author | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-21 15:45:35 +0000 |
---|---|---|
committer | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-21 15:45:35 +0000 |
commit | c4de5dfacd5f7fa135ee7069c9bfe7292c7d4c99 (patch) | |
tree | b25c6f8642cca01fd9f5b16d699c34ecd78a4a0d | |
parent | 5458ef367834a5657cd36f5dac29c110329523d0 (diff) | |
download | chromium_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.cc | 12 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_contents.cc | 15 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_contents.h | 8 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_final_status.h | 1 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.cc | 28 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.h | 15 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager_unittest.cc | 223 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_render_widget_host_view.cc | 306 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_render_widget_host_view.h | 133 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_resource_handler.cc | 7 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/test/data/prerender/prerender_size.html | 25 | ||||
-rw-r--r-- | content/browser/tab_contents/render_view_host_manager.cc | 12 |
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(); } |