diff options
author | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-11 19:50:29 +0000 |
---|---|---|
committer | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-11 19:50:29 +0000 |
commit | f3c93ecc2083de148f8702ae9a5c0d9459711585 (patch) | |
tree | e199ac268e7d5d7eee958e284faa027b7050fe62 | |
parent | 78de2e4874658de56d48d5a4fcb9f6d22f011d89 (diff) | |
download | chromium_src-f3c93ecc2083de148f8702ae9a5c0d9459711585.zip chromium_src-f3c93ecc2083de148f8702ae9a5c0d9459711585.tar.gz chromium_src-f3c93ecc2083de148f8702ae9a5c0d9459711585.tar.bz2 |
Hide a TabContents's RenderViewHost while prerendering.
Should prevent offscreen drawing before display, except
in cases of WebGL, Canvas2D, and the like.
BUG=none
Test=PrerenderBrowserTest.*
Review URL: http://codereview.chromium.org/6975004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85021 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/prerender/prerender_browsertest.cc | 51 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_contents.cc | 26 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_contents.h | 8 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.cc | 3 |
4 files changed, 80 insertions, 8 deletions
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index a8b274f..2a11291 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc @@ -20,6 +20,7 @@ #include "chrome/test/ui_test_utils.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/tab_contents/tab_contents.h" +#include "content/common/notification_service.h" #include "grit/generated_resources.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" @@ -62,17 +63,28 @@ class TestPrerenderContents : public PrerenderContents { : PrerenderContents(prerender_manager, profile, url, referrer), number_of_loads_(0), expected_number_of_loads_(number_of_loads), - expected_final_status_(expected_final_status) { + expected_final_status_(expected_final_status), + was_hidden_(false), + was_shown_(false) { } virtual ~TestPrerenderContents() { EXPECT_EQ(expected_final_status_, final_status()) << " when testing URL " << prerender_url().path(); + // Prerendering RenderViewHosts should be hidden before the first + // navigation, so this should be happen for every PrerenderContents that's + // created, regardless of whether or not it's used. + EXPECT_TRUE(was_hidden_); + // A used PrerenderContents will only be destroyed when we swap out // TabContents, at the end of a navigation caused by a call to // NavigateToURLImpl(). - if (final_status() == FINAL_STATUS_USED) + if (final_status() == FINAL_STATUS_USED) { + EXPECT_TRUE(was_shown_); MessageLoopForUI::current()->Quit(); + } else { + EXPECT_FALSE(was_shown_); + } } virtual void OnRenderViewGone(int status, int exit_code) OVERRIDE { @@ -108,9 +120,44 @@ class TestPrerenderContents : public PrerenderContents { } private: + virtual void OnRenderViewHostCreated( + RenderViewHost* new_render_view_host) OVERRIDE { + // Used to make sure the RenderViewHost is hidden and, if used, + // subsequently shown. + notification_registrar().Add( + this, + NotificationType::RENDER_WIDGET_VISIBILITY_CHANGED, + Source<RenderWidgetHost>(new_render_view_host)); + PrerenderContents::OnRenderViewHostCreated(new_render_view_host); + } + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) OVERRIDE { + if (type.value == + NotificationType::RENDER_WIDGET_VISIBILITY_CHANGED) { + bool is_visible = *Details<bool>(details).ptr(); + if (!is_visible) { + was_hidden_ = true; + } else if (is_visible && was_hidden_) { + // Once hidden, a prerendered RenderViewHost should only be shown after + // being removed from the PrerenderContents for display. + EXPECT_FALSE(render_view_host()); + was_shown_ = true; + } + return; + } + PrerenderContents::Observe(type, source, details); + } + int number_of_loads_; int expected_number_of_loads_; FinalStatus expected_final_status_; + // Set to true when the prerendering RenderWidget is hidden. + bool was_hidden_; + // Set to true when the prerendering RenderWidget is shown, after having been + // hidden. + bool was_shown_; }; // PrerenderManager that uses TestPrerenderContents. diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc index 4a989bc..2f2ebd0 100644 --- a/chrome/browser/prerender/prerender_contents.cc +++ b/chrome/browser/prerender/prerender_contents.cc @@ -129,6 +129,8 @@ void PrerenderContents::StartPrerenderingOld( // Create the RenderView, so it can receive messages. render_view_host_->CreateRenderView(string16()); + OnRenderViewHostCreated(render_view_host_); + // 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 = @@ -473,19 +475,29 @@ void PrerenderContents::Observe(NotificationType type, } case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: { - // When a new RenderView is created for a prerendering TabContents, - // tell the new RenderView it's being used for prerendering before any - // navigations occur. Note that this is always triggered before the - // first navigation, so there's no need to send the message just after the - // TabContents is created. if (prerender_contents_.get()) { DCHECK_EQ(Source<TabContents>(source).ptr(), prerender_contents_->tab_contents()); Details<RenderViewHost> new_render_view_host(details); + OnRenderViewHostCreated(new_render_view_host.ptr()); + + // When a new RenderView is created for a prerendering TabContents, + // tell the new RenderView it's being used for prerendering before any + // navigations occur. Note that this is always triggered before the + // first navigation, so there's no need to send the message just after + // the TabContents is created. new_render_view_host->Send( new ViewMsg_SetIsPrerendering(new_render_view_host->routing_id(), true)); + + // Set the new TabContents and its RenderViewHost as hidden, to reduce + // resource usage. This can only be done after the first call to + // LoadURL, so there's an actual RenderViewHost with a + // RenderWidgetHostView to hide. + // + // Done here to prevent a race with loading the page. + prerender_contents_->tab_contents()->HideContents(); } break; } @@ -586,6 +598,10 @@ void PrerenderContents::ShowCreatedFullscreenWidget(int route_id) { NOTIMPLEMENTED(); } +void PrerenderContents::OnRenderViewHostCreated( + RenderViewHost* new_render_view_host) { +} + void PrerenderContents::OnDidStartProvisionalLoadForFrame(int64 frame_id, bool is_main_frame, const GURL& url) { diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h index a525756..2be7286 100644 --- a/chrome/browser/prerender/prerender_contents.h +++ b/chrome/browser/prerender/prerender_contents.h @@ -252,6 +252,14 @@ class PrerenderContents : public RenderViewHostDelegate, const GURL& prerender_url() const { return prerender_url_; } + NotificationRegistrar& notification_registrar() { + return notification_registrar_; + } + + // Called whenever a RenderViewHost is created for prerendering. Only called + // once the RenderViewHost has a RenderView and RenderWidgetHostView. + virtual void OnRenderViewHostCreated(RenderViewHost* new_render_view_host); + private: // Needs to be able to call the constructor. friend class PrerenderContentsFactoryImpl; diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index 9aa02fd..c249477 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc @@ -445,10 +445,11 @@ bool PrerenderManager::MaybeUsePreloadedPageOld(TabContents* tab_contents, RenderViewHost* render_view_host = prerender_contents->render_view_host_mutable(); + prerender_contents->set_render_view_host(NULL); + // RenderViewHosts in PrerenderContents start out hidden. // Since we are actually using it now, restore it. render_view_host->WasRestored(); - prerender_contents->set_render_view_host(NULL); render_view_host->Send( new ViewMsg_SetIsPrerendering(render_view_host->routing_id(), false)); tab_contents->SwapInRenderViewHost(render_view_host); |