summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-11 19:50:29 +0000
committermmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-11 19:50:29 +0000
commitf3c93ecc2083de148f8702ae9a5c0d9459711585 (patch)
treee199ac268e7d5d7eee958e284faa027b7050fe62
parent78de2e4874658de56d48d5a4fcb9f6d22f011d89 (diff)
downloadchromium_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.cc51
-rw-r--r--chrome/browser/prerender/prerender_contents.cc26
-rw-r--r--chrome/browser/prerender/prerender_contents.h8
-rw-r--r--chrome/browser/prerender/prerender_manager.cc3
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);