summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-15 00:56:47 +0000
committertburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-15 00:56:47 +0000
commit9831b611335c19ee12ccc0ae55a4d6c728f292e6 (patch)
treef075d7d406f26d19ca3403f7e0898f23aef92ba0
parenta1639c1e430ebbfb6b6da01a736bfae61352d6df (diff)
downloadchromium_src-9831b611335c19ee12ccc0ae55a4d6c728f292e6.zip
chromium_src-9831b611335c19ee12ccc0ae55a4d6c728f292e6.tar.gz
chromium_src-9831b611335c19ee12ccc0ae55a4d6c728f292e6.tar.bz2
Compute the percentage of pixels of a webpage that is
already rendered at the time a prerender is swapped in, compared to the state of the page at the OnLoad event. This is intended for Canary/Dev only, and will be removed again in a few weeks. R=dominich Review URL: https://chromiumcodereview.appspot.com/10378109 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137037 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/prerender/prerender_browsertest.cc12
-rw-r--r--chrome/browser/prerender/prerender_contents.cc4
-rw-r--r--chrome/browser/prerender/prerender_histograms.cc12
-rw-r--r--chrome/browser/prerender/prerender_histograms.h4
-rw-r--r--chrome/browser/prerender/prerender_manager.h2
-rw-r--r--chrome/browser/prerender/prerender_tab_helper.cc126
-rw-r--r--chrome/browser/prerender/prerender_tab_helper.h10
7 files changed, 165 insertions, 5 deletions
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 95f6bf8..cb9b660 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -167,8 +167,10 @@ class TestPrerenderContents : public PrerenderContents {
// navigation, so this should be happen for every PrerenderContents for
// which a RenderViewHost is created, regardless of whether or not it's
// used.
- if (new_render_view_host_)
- EXPECT_TRUE(was_hidden_);
+ // TODO(tburkard): Temporarily disabled for pixel stats since we do not
+ // hide any more. Needs to be re-enabled once pixel stats are removed.
+ // if (new_render_view_host_)
+ // EXPECT_TRUE(was_hidden_);
// A used PrerenderContents will only be destroyed when we swap out
// WebContents, at the end of a navigation caused by a call to
@@ -176,7 +178,9 @@ class TestPrerenderContents : public PrerenderContents {
if (final_status() == FINAL_STATUS_USED)
EXPECT_TRUE(new_render_view_host_);
- EXPECT_EQ(should_be_shown_, was_shown_);
+ // TODO(tburkard): Temporarily disabled for pixel stats since we do not
+ // hide any more. Needs to be re-enabled once pixel stats are removed.
+ // EXPECT_EQ(should_be_shown_, was_shown_);
// When the PrerenderContents is destroyed, quit the UI message loop.
// This happens on navigation to used prerendered pages, and soon
@@ -1030,7 +1034,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderIncognito) {
}
// Checks that the visibility API works.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderVisibility) {
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderVisibility) {
PrerenderTestURL("files/prerender/prerender_visibility.html",
FINAL_STATUS_USED,
1);
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index a6573db..5e06df4 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -472,7 +472,9 @@ void PrerenderContents::Observe(int type,
// size, is also sets itself to be visible, which would then break the
// visibility API.
new_render_view_host->WasResized();
- prerender_contents_->web_contents()->HideContents();
+ // TODO(tburkard): Put this back in once pixel counting experiments
+ // are done.
+ // prerender_contents_->web_contents()->HideContents();
}
break;
}
diff --git a/chrome/browser/prerender/prerender_histograms.cc b/chrome/browser/prerender/prerender_histograms.cc
index 6359378..f150608 100644
--- a/chrome/browser/prerender/prerender_histograms.cc
+++ b/chrome/browser/prerender/prerender_histograms.cc
@@ -178,6 +178,18 @@ void PrerenderHistograms::RecordTimeSinceLastRecentVisit(
UMA_HISTOGRAM_TIMES(name, delta));
}
+void PrerenderHistograms::RecordFractionPixelsFinalAtSwapin(
+ double fraction) const {
+ if (fraction < 0.0 || fraction > 1.0)
+ return;
+ int percentage = static_cast<int>(fraction * 100);
+ if (percentage < 0 || percentage > 100)
+ return;
+ PREFIXED_HISTOGRAM(
+ base::FieldTrial::MakeName("FractionPixelsFinalAtSwapin", "Prerender"),
+ UMA_HISTOGRAM_PERCENTAGE(name, percentage));
+}
+
base::TimeTicks PrerenderHistograms::GetCurrentTimeTicks() const {
return base::TimeTicks::Now();
}
diff --git a/chrome/browser/prerender/prerender_histograms.h b/chrome/browser/prerender/prerender_histograms.h
index d0d7f5e..85dea4f 100644
--- a/chrome/browser/prerender/prerender_histograms.h
+++ b/chrome/browser/prerender/prerender_histograms.h
@@ -75,6 +75,10 @@ class PrerenderHistograms {
// Record the time since a page was recently visited.
void RecordTimeSinceLastRecentVisit(base::TimeDelta time) const;
+ // Record a percentage of pixels of the final page already in place at
+ // swap-in.
+ void RecordFractionPixelsFinalAtSwapin(double fraction) const;
+
private:
base::TimeTicks GetCurrentTimeTicks() const;
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index 42e7c86..3d73bcf 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -252,6 +252,8 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
Profile* profile() const { return profile_; }
+ PrerenderHistograms* histograms() const { return histograms_.get(); }
+
protected:
void SetPrerenderContentsFactory(
PrerenderContents::Factory* prerender_contents_factory);
diff --git a/chrome/browser/prerender/prerender_tab_helper.cc b/chrome/browser/prerender/prerender_tab_helper.cc
index 8f01fef..1d1feac 100644
--- a/chrome/browser/prerender/prerender_tab_helper.cc
+++ b/chrome/browser/prerender/prerender_tab_helper.cc
@@ -7,12 +7,20 @@
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/time.h"
+#include "chrome/browser/prerender/prerender_histograms.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
+#include "skia/ext/platform_canvas.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/rect.h"
+
+using content::WebContents;
namespace prerender {
@@ -33,8 +41,113 @@ void RecordPageviewEvent(PAGEVIEW_EVENTS event) {
} // namespace
+// Helper class to compute pixel-based stats on the paint progress
+// between when a prerendered page is swapped in and when the onload event
+// fires.
+class PrerenderTabHelper::PixelStats {
+ public:
+ explicit PixelStats(PrerenderTabHelper* tab_helper) :
+ weak_factory_(this),
+ tab_helper_(tab_helper) {
+ }
+
+ // Reasons why we need to fetch bitmaps: either a prerender was swapped in,
+ // or a prerendered page has finished loading.
+ enum BitmapType {
+ BITMAP_SWAP_IN,
+ BITMAP_ON_LOAD
+ };
+
+ void GetBitmap(BitmapType bitmap_type, WebContents* web_contents) {
+ if (bitmap_type == BITMAP_SWAP_IN) {
+ bitmap_.reset();
+ bitmap_web_contents_ = web_contents;
+ }
+
+ if (bitmap_type == BITMAP_ON_LOAD && bitmap_web_contents_ != web_contents)
+ return;
+
+ if (!web_contents || !web_contents->GetView() ||
+ !web_contents->GetRenderViewHost()) {
+ return;
+ }
+
+ skia::PlatformCanvas* temp_canvas = new skia::PlatformCanvas;
+ web_contents->GetRenderViewHost()->CopyFromBackingStore(
+ gfx::Rect(), gfx::Size(), temp_canvas,
+ base::Bind(&PrerenderTabHelper::PixelStats::HandleBitmapResult,
+ weak_factory_.GetWeakPtr(),
+ bitmap_type,
+ web_contents,
+ base::Owned(temp_canvas)));
+ }
+
+ private:
+ void HandleBitmapResult(BitmapType bitmap_type,
+ WebContents* web_contents,
+ skia::PlatformCanvas* temp_canvas,
+ bool succeeded) {
+ scoped_ptr<SkBitmap> bitmap;
+ if (succeeded) {
+ const SkBitmap& canvas_bitmap =
+ skia::GetTopDevice(*temp_canvas)->accessBitmap(false);
+ bitmap.reset(new SkBitmap());
+ canvas_bitmap.copyTo(bitmap.get(), SkBitmap::kARGB_8888_Config);
+ }
+
+ if (bitmap_web_contents_ != web_contents)
+ return;
+
+ if (bitmap_type == BITMAP_SWAP_IN)
+ bitmap_.swap(bitmap);
+
+ if (bitmap_type == BITMAP_ON_LOAD) {
+ PrerenderManager* prerender_manager =
+ tab_helper_->MaybeGetPrerenderManager();
+ if (prerender_manager) {
+ prerender_manager->histograms()->RecordFractionPixelsFinalAtSwapin(
+ CompareBitmaps(bitmap_.get(), bitmap.get()));
+ }
+ bitmap_.reset();
+ bitmap_web_contents_ = NULL;
+ }
+ }
+
+ // Helper comparing two bitmaps of identical size.
+ // Returns a value < 0.0 if there is an error, and otherwise, a double in
+ // [0, 1] indicating the fraction of pixels that are the same.
+ double CompareBitmaps(SkBitmap* bitmap1, SkBitmap* bitmap2) {
+ if (!bitmap1 || !bitmap2) {
+ return -2.0;
+ }
+ if (bitmap1->width() != bitmap2->width() ||
+ bitmap1->height() != bitmap2->height()) {
+ return -1.0;
+ }
+ int pixels = bitmap1->width() * bitmap1->height();
+ int same_pixels = 0;
+ for (int y = 0; y < bitmap1->height(); ++y) {
+ for (int x = 0; x < bitmap1->width(); ++x) {
+ if (bitmap1->getColor(x, y) == bitmap2->getColor(x, y))
+ same_pixels++;
+ }
+ }
+ return static_cast<double>(same_pixels) / static_cast<double>(pixels);
+ }
+
+ // Bitmap of what the last swapped in prerendered tab looked like at swapin,
+ // and the WebContents that it was swapped into.
+ scoped_ptr<SkBitmap> bitmap_;
+ WebContents* bitmap_web_contents_;
+
+ base::WeakPtrFactory<PixelStats> weak_factory_;
+
+ PrerenderTabHelper* tab_helper_;
+};
+
PrerenderTabHelper::PrerenderTabHelper(TabContentsWrapper* tab)
: content::WebContentsObserver(tab->web_contents()),
+ pixel_stats_(new PixelStats(this)),
tab_(tab) {
}
@@ -93,6 +206,8 @@ void PrerenderTabHelper::DidStopLoading() {
PrerenderManager::RecordPerceivedPageLoadTime(
now - pplt_load_start_, fraction_elapsed_at_swapin, web_contents(),
url_);
+ if (IsPrerendered())
+ pixel_stats_->GetBitmap(PixelStats::BITMAP_ON_LOAD, web_contents());
}
// Reset the PPLT metric.
@@ -129,6 +244,13 @@ bool PrerenderTabHelper::IsPrerendering() {
return prerender_manager->IsWebContentsPrerendering(web_contents());
}
+bool PrerenderTabHelper::IsPrerendered() {
+ PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
+ if (!prerender_manager)
+ return false;
+ return prerender_manager->IsWebContentsPrerendered(web_contents());
+}
+
void PrerenderTabHelper::PrerenderSwappedIn() {
// Ensure we are not prerendering any more.
DCHECK(!IsPrerendering());
@@ -136,11 +258,15 @@ void PrerenderTabHelper::PrerenderSwappedIn() {
// If we have already finished loading, report a 0 PPLT.
PrerenderManager::RecordPerceivedPageLoadTime(base::TimeDelta(), 1.0,
web_contents(), url_);
+ PrerenderManager* prerender_manager = MaybeGetPrerenderManager();
+ if (prerender_manager)
+ prerender_manager->histograms()->RecordFractionPixelsFinalAtSwapin(1.0);
} else {
// If we have not finished loading yet, record the actual load start, and
// rebase the start time to now.
actual_load_start_ = pplt_load_start_;
pplt_load_start_ = base::TimeTicks::Now();
+ pixel_stats_->GetBitmap(PixelStats::BITMAP_SWAP_IN, web_contents());
}
}
diff --git a/chrome/browser/prerender/prerender_tab_helper.h b/chrome/browser/prerender/prerender_tab_helper.h
index 82a8d26..2b29b10 100644
--- a/chrome/browser/prerender/prerender_tab_helper.h
+++ b/chrome/browser/prerender/prerender_tab_helper.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_PRERENDER_PRERENDER_TAB_HELPER_H_
#include "base/time.h"
+#include "base/memory/scoped_ptr.h"
#include "content/public/browser/web_contents_observer.h"
#include "googleurl/src/gurl.h"
@@ -42,12 +43,21 @@ class PrerenderTabHelper : public content::WebContentsObserver {
void PrerenderSwappedIn();
private:
+ // Helper class to compute pixel-based stats on the paint progress
+ // between when a prerendered page is swapped in and when the onload event
+ // fires.
+ class PixelStats;
+ scoped_ptr<PixelStats> pixel_stats_;
+
// Retrieves the PrerenderManager, or NULL, if none was found.
PrerenderManager* MaybeGetPrerenderManager() const;
// Returns whether the WebContents being observed is currently prerendering.
bool IsPrerendering();
+ // Returns whether the WebContents being observed was prerendered.
+ bool IsPrerendered();
+
bool IsTopSite(const GURL& url);
// TabContentsWrapper we're created for.