diff options
author | tburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-15 00:56:47 +0000 |
---|---|---|
committer | tburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-15 00:56:47 +0000 |
commit | 9831b611335c19ee12ccc0ae55a4d6c728f292e6 (patch) | |
tree | f075d7d406f26d19ca3403f7e0898f23aef92ba0 | |
parent | a1639c1e430ebbfb6b6da01a736bfae61352d6df (diff) | |
download | chromium_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.cc | 12 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_contents.cc | 4 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_histograms.cc | 12 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_histograms.h | 4 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.h | 2 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_tab_helper.cc | 126 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_tab_helper.h | 10 |
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. |