Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: chrome/browser/android/most_visited_sites.cc

Issue 1373983003: Add UMA stats for which icon types are shown and clicked on the NTP. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: asvitkine's comments Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/android/most_visited_sites.h" 5 #include "chrome/browser/android/most_visited_sites.h"
6 6
7 #include "base/android/jni_android.h" 7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h" 8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h" 9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h" 10 #include "base/android/scoped_java_ref.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 using content::BrowserThread; 49 using content::BrowserThread;
50 using history::TopSites; 50 using history::TopSites;
51 using suggestions::ChromeSuggestion; 51 using suggestions::ChromeSuggestion;
52 using suggestions::SuggestionsProfile; 52 using suggestions::SuggestionsProfile;
53 using suggestions::SuggestionsService; 53 using suggestions::SuggestionsService;
54 using suggestions::SuggestionsServiceFactory; 54 using suggestions::SuggestionsServiceFactory;
55 using suggestions::SyncState; 55 using suggestions::SyncState;
56 56
57 namespace { 57 namespace {
58 58
59 // Total number of tiles displayed.
60 const char kNumTilesHistogramName[] = "NewTabPage.NumberOfTiles";
61 // Tracking thumbnails.
62 const char kNumLocalThumbnailTilesHistogramName[] =
63 "NewTabPage.NumberOfThumbnailTiles";
64 const char kNumEmptyTilesHistogramName[] = "NewTabPage.NumberOfGrayTiles";
65 const char kNumServerTilesHistogramName[] = "NewTabPage.NumberOfExternalTiles";
66
67 // Format for tile clicks histogram.
68 const char kOpenedItemHistogramFormat[] = "NewTabPage.MostVisited.%s";
69 // Format for tile impressions histogram.
70 const char kImpressionHistogramFormat[] = "NewTabPage.SuggestionsImpression.%s";
71 // Identifiers for the various tile sources. 59 // Identifiers for the various tile sources.
72 const char kHistogramClientName[] = "client"; 60 const char kHistogramClientName[] = "client";
73 const char kHistogramServerName[] = "server"; 61 const char kHistogramServerName[] = "server";
74 const char kHistogramServerFormat[] = "server%d"; 62 const char kHistogramServerFormat[] = "server%d";
75 const char kHistogramPopularName[] = "popular"; 63 const char kHistogramPopularName[] = "popular";
76 64
77 const char kPopularSitesFieldTrialName[] = "NTPPopularSites"; 65 const char kPopularSitesFieldTrialName[] = "NTPPopularSites";
78 66
67 // The visual type of a most visited tile.
68 //
69 // These values must stay in sync with the MostVisitedTileType enum
70 // in histograms.xml.
71 //
72 // A Java counterpart will be generated for this enum.
73 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp
74 enum MostVisitedTileType {
75 // The icon or thumbnail hasn't loaded yet.
76 NONE,
77 // The item displays a site's actual favicon or touch icon.
78 ICON_REAL,
79 // The item displays a color derived from the site's favicon or touch icon.
80 ICON_COLOR,
81 // The item displays a default gray box in place of an icon.
82 ICON_DEFAULT,
83 // The item displays a locally-captured thumbnail of the site content.
84 THUMBNAIL_LOCAL,
85 // The item displays a server-provided thumbnail of the site content.
86 THUMBNAIL_SERVER,
87 // The item displays a default graphic in place of a thumbnail.
88 THUMBNAIL_DEFAULT,
89 NUM_TILE_TYPES,
90 };
91
79 scoped_ptr<SkBitmap> MaybeFetchLocalThumbnail( 92 scoped_ptr<SkBitmap> MaybeFetchLocalThumbnail(
80 const GURL& url, 93 const GURL& url,
81 const scoped_refptr<TopSites>& top_sites) { 94 const scoped_refptr<TopSites>& top_sites) {
82 DCHECK_CURRENTLY_ON(BrowserThread::DB); 95 DCHECK_CURRENTLY_ON(BrowserThread::DB);
83 scoped_refptr<base::RefCountedMemory> image; 96 scoped_refptr<base::RefCountedMemory> image;
84 scoped_ptr<SkBitmap> bitmap; 97 scoped_ptr<SkBitmap> bitmap;
85 if (top_sites && top_sites->GetPageThumbnail(url, false, &image)) 98 if (top_sites && top_sites->GetPageThumbnail(url, false, &image))
86 bitmap.reset(gfx::JPEGCodec::Decode(image->front(), image->size())); 99 bitmap.reset(gfx::JPEGCodec::Decode(image->front(), image->size()));
87 return bitmap.Pass(); 100 return bitmap.Pass();
88 } 101 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 ? base::StringPrintf(kHistogramServerFormat, provider_index) 212 ? base::StringPrintf(kHistogramServerFormat, provider_index)
200 : kHistogramServerName; 213 : kHistogramServerName;
201 } 214 }
202 NOTREACHED(); 215 NOTREACHED();
203 return std::string(); 216 return std::string();
204 } 217 }
205 218
206 MostVisitedSites::MostVisitedSites(Profile* profile) 219 MostVisitedSites::MostVisitedSites(Profile* profile)
207 : profile_(profile), num_sites_(0), received_most_visited_sites_(false), 220 : profile_(profile), num_sites_(0), received_most_visited_sites_(false),
208 received_popular_sites_(false), recorded_uma_(false), 221 received_popular_sites_(false), recorded_uma_(false),
209 num_local_thumbs_(0), num_server_thumbs_(0), num_empty_thumbs_(0),
210 scoped_observer_(this), weak_ptr_factory_(this) { 222 scoped_observer_(this), weak_ptr_factory_(this) {
211 // Register the debugging page for the Suggestions Service and the thumbnails 223 // Register the debugging page for the Suggestions Service and the thumbnails
212 // debugging page. 224 // debugging page.
213 content::URLDataSource::Add(profile_, 225 content::URLDataSource::Add(profile_,
214 new suggestions::SuggestionsSource(profile_)); 226 new suggestions::SuggestionsSource(profile_));
215 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); 227 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_));
216 228
217 // Register this class as an observer to the sync service. It is important to 229 // Register this class as an observer to the sync service. It is important to
218 // be notified of changes in the sync state such as initialization, sync 230 // be notified of changes in the sync state such as initialization, sync
219 // being enabled or disabled, etc. 231 // being enabled or disabled, etc.
220 ProfileSyncService* profile_sync_service = 232 ProfileSyncService* profile_sync_service =
221 ProfileSyncServiceFactory::GetForProfile(profile_); 233 ProfileSyncServiceFactory::GetForProfile(profile_);
222 if (profile_sync_service) 234 if (profile_sync_service)
223 profile_sync_service->AddObserver(this); 235 profile_sync_service->AddObserver(this);
224 } 236 }
225 237
226 MostVisitedSites::~MostVisitedSites() { 238 MostVisitedSites::~MostVisitedSites() {
227 ProfileSyncService* profile_sync_service = 239 ProfileSyncService* profile_sync_service =
228 ProfileSyncServiceFactory::GetForProfile(profile_); 240 ProfileSyncServiceFactory::GetForProfile(profile_);
229 if (profile_sync_service && profile_sync_service->HasObserver(this)) 241 if (profile_sync_service && profile_sync_service->HasObserver(this))
230 profile_sync_service->RemoveObserver(this); 242 profile_sync_service->RemoveObserver(this);
231 } 243 }
232 244
233 void MostVisitedSites::Destroy(JNIEnv* env, jobject obj) { 245 void MostVisitedSites::Destroy(JNIEnv* env, jobject obj) {
234 delete this; 246 delete this;
235 } 247 }
236 248
237 void MostVisitedSites::OnLoadingComplete(JNIEnv* env, jobject obj) {
238 RecordThumbnailUMAMetrics();
239 }
240
241 void MostVisitedSites::SetMostVisitedURLsObserver(JNIEnv* env, 249 void MostVisitedSites::SetMostVisitedURLsObserver(JNIEnv* env,
242 jobject obj, 250 jobject obj,
243 jobject j_observer, 251 jobject j_observer,
244 jint num_sites) { 252 jint num_sites) {
245 observer_.Reset(env, j_observer); 253 observer_.Reset(env, j_observer);
246 num_sites_ = num_sites; 254 num_sites_ = num_sites;
247 255
248 if (ShouldShowPopularSites() && 256 if (ShouldShowPopularSites() &&
249 NeedPopularSites(profile_->GetPrefs(), num_sites_)) { 257 NeedPopularSites(profile_->GetPrefs(), num_sites_)) {
250 popular_sites_.reset(new PopularSites( 258 popular_sites_.reset(new PopularSites(
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 } 344 }
337 345
338 void MostVisitedSites::OnObtainedThumbnail( 346 void MostVisitedSites::OnObtainedThumbnail(
339 bool is_local_thumbnail, 347 bool is_local_thumbnail,
340 scoped_ptr<ScopedJavaGlobalRef<jobject>> j_callback, 348 scoped_ptr<ScopedJavaGlobalRef<jobject>> j_callback,
341 const GURL& url, 349 const GURL& url,
342 const SkBitmap* bitmap) { 350 const SkBitmap* bitmap) {
343 DCHECK_CURRENTLY_ON(BrowserThread::UI); 351 DCHECK_CURRENTLY_ON(BrowserThread::UI);
344 JNIEnv* env = AttachCurrentThread(); 352 JNIEnv* env = AttachCurrentThread();
345 ScopedJavaLocalRef<jobject> j_bitmap; 353 ScopedJavaLocalRef<jobject> j_bitmap;
346 if (bitmap) { 354 if (bitmap)
347 j_bitmap = gfx::ConvertToJavaBitmap(bitmap); 355 j_bitmap = gfx::ConvertToJavaBitmap(bitmap);
348 if (is_local_thumbnail) {
349 ++num_local_thumbs_;
350 } else {
351 ++num_server_thumbs_;
352 }
353 } else {
354 ++num_empty_thumbs_;
355 }
356 Java_ThumbnailCallback_onMostVisitedURLsThumbnailAvailable( 356 Java_ThumbnailCallback_onMostVisitedURLsThumbnailAvailable(
357 env, j_callback->obj(), j_bitmap.obj()); 357 env, j_callback->obj(), j_bitmap.obj(), is_local_thumbnail);
358 } 358 }
359 359
360 void MostVisitedSites::BlacklistUrl(JNIEnv* env, 360 void MostVisitedSites::BlacklistUrl(JNIEnv* env,
361 jobject obj, 361 jobject obj,
362 jstring j_url) { 362 jstring j_url) {
363 GURL url(ConvertJavaStringToUTF8(env, j_url)); 363 GURL url(ConvertJavaStringToUTF8(env, j_url));
364 364
365 // Always blacklist in the local TopSites. 365 // Always blacklist in the local TopSites.
366 scoped_refptr<TopSites> top_sites = TopSitesFactory::GetForProfile(profile_); 366 scoped_refptr<TopSites> top_sites = TopSitesFactory::GetForProfile(profile_);
367 if (top_sites) 367 if (top_sites)
368 top_sites->AddBlacklistedURL(url); 368 top_sites->AddBlacklistedURL(url);
369 369
370 // Only blacklist in the server-side suggestions service if it's active. 370 // Only blacklist in the server-side suggestions service if it's active.
371 if (mv_source_ == SUGGESTIONS_SERVICE) { 371 if (mv_source_ == SUGGESTIONS_SERVICE) {
372 SuggestionsService* suggestions_service = 372 SuggestionsService* suggestions_service =
373 SuggestionsServiceFactory::GetForProfile(profile_); 373 SuggestionsServiceFactory::GetForProfile(profile_);
374 DCHECK(suggestions_service); 374 DCHECK(suggestions_service);
375 suggestions_service->BlacklistURL( 375 suggestions_service->BlacklistURL(
376 url, base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, 376 url, base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable,
377 weak_ptr_factory_.GetWeakPtr()), 377 weak_ptr_factory_.GetWeakPtr()),
378 base::Closure()); 378 base::Closure());
379 } 379 }
380 } 380 }
381 381
382 void MostVisitedSites::RecordTileTypeMetrics(JNIEnv* env,
383 jobject obj,
384 jintArray jtile_types,
385 jboolean is_icon_mode) {
386 std::vector<int> tile_types;
387 base::android::JavaIntArrayToIntVector(env, jtile_types, &tile_types);
388 DCHECK_EQ(current_suggestions_.size(), tile_types.size());
389
390 int counts_per_type[NUM_TILE_TYPES] = {0};
391 for (size_t i = 0; i < tile_types.size(); ++i) {
392 int tile_type = tile_types[i];
393 ++counts_per_type[tile_type];
394 std::string histogram = base::StringPrintf(
395 "NewTabPage.TileType.%s",
396 current_suggestions_[i]->GetSourceHistogramName().c_str());
397 LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES);
398 }
399
400 if (is_icon_mode) {
401 UMA_HISTOGRAM_COUNTS_100("NewTabPage.IconsReal",
402 counts_per_type[ICON_REAL]);
Alexei Svitkine (slow) 2015/09/30 19:52:05 UMA_HISTOGRAM_COUNTS_100 allocates 50 buckets. I t
newt (away) 2015/09/30 20:40:54 Done. I had assumed that UMA_HISTOGRAM_COUNTS_100
Alexei Svitkine (slow) 2015/09/30 20:59:52 It is slower because it grabs a lock on that histo
403 UMA_HISTOGRAM_COUNTS_100("NewTabPage.IconsColor",
404 counts_per_type[ICON_COLOR]);
405 UMA_HISTOGRAM_COUNTS_100("NewTabPage.IconsGray",
406 counts_per_type[ICON_DEFAULT]);
407 } else {
408 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfThumbnailTiles",
409 counts_per_type[THUMBNAIL_LOCAL]);
410 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfExternalTiles",
411 counts_per_type[THUMBNAIL_SERVER]);
412 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfGrayTiles",
413 counts_per_type[THUMBNAIL_DEFAULT]);
414 }
415 }
416
382 void MostVisitedSites::RecordOpenedMostVisitedItem(JNIEnv* env, 417 void MostVisitedSites::RecordOpenedMostVisitedItem(JNIEnv* env,
383 jobject obj, 418 jobject obj,
384 jint index) { 419 jint index,
420 jint tile_type) {
385 DCHECK_GE(index, 0); 421 DCHECK_GE(index, 0);
386 DCHECK_LT(index, static_cast<int>(current_suggestions_.size())); 422 DCHECK_LT(index, static_cast<int>(current_suggestions_.size()));
387 std::string histogram = base::StringPrintf( 423 std::string histogram = base::StringPrintf(
388 kOpenedItemHistogramFormat, 424 "NewTabPage.MostVisited.%s",
389 current_suggestions_[index]->GetSourceHistogramName().c_str()); 425 current_suggestions_[index]->GetSourceHistogramName().c_str());
390 LogHistogramEvent(histogram, index, num_sites_); 426 LogHistogramEvent(histogram, index, num_sites_);
427
428 histogram = base::StringPrintf(
429 "NewTabPage.TileTypeClicked.%s",
430 current_suggestions_[index]->GetSourceHistogramName().c_str());
431 LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES);
391 } 432 }
392 433
393 void MostVisitedSites::OnStateChanged() { 434 void MostVisitedSites::OnStateChanged() {
394 // There have been changes to the sync state. This class cares about a few 435 // There have been changes to the sync state. This class cares about a few
395 // (just initialized, enabled/disabled or history sync state changed). Re-run 436 // (just initialized, enabled/disabled or history sync state changed). Re-run
396 // the query code which will use the proper state. 437 // the query code which will use the proper state.
397 QueryMostVisitedURLs(); 438 QueryMostVisitedURLs();
398 } 439 }
399 440
400 // static 441 // static
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 // Return destination postions filled so far which becomes the start_position 701 // Return destination postions filled so far which becomes the start_position
661 // for future runs. 702 // for future runs.
662 return i; 703 return i;
663 } 704 }
664 705
665 void MostVisitedSites::NotifyMostVisitedURLsObserver() { 706 void MostVisitedSites::NotifyMostVisitedURLsObserver() {
666 size_t num_suggestions = current_suggestions_.size(); 707 size_t num_suggestions = current_suggestions_.size();
667 if (received_most_visited_sites_ && received_popular_sites_ && 708 if (received_most_visited_sites_ && received_popular_sites_ &&
668 !recorded_uma_) { 709 !recorded_uma_) {
669 RecordImpressionUMAMetrics(); 710 RecordImpressionUMAMetrics();
670 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumTilesHistogramName, num_suggestions); 711 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfTiles", num_suggestions);
671 recorded_uma_ = true; 712 recorded_uma_ = true;
672 } 713 }
673 std::vector<base::string16> titles; 714 std::vector<base::string16> titles;
674 std::vector<std::string> urls; 715 std::vector<std::string> urls;
675 titles.reserve(num_suggestions); 716 titles.reserve(num_suggestions);
676 urls.reserve(num_suggestions); 717 urls.reserve(num_suggestions);
677 for (const Suggestion* suggestion : current_suggestions_) { 718 for (const Suggestion* suggestion : current_suggestions_) {
678 titles.push_back(suggestion->title); 719 titles.push_back(suggestion->title);
679 urls.push_back(suggestion->url.spec()); 720 urls.push_back(suggestion->url.spec());
680 } 721 }
(...skipping 22 matching lines...) Expand all
703 favicon_urls.push_back(popular_site.favicon_url.spec()); 744 favicon_urls.push_back(popular_site.favicon_url.spec());
704 } 745 }
705 JNIEnv* env = AttachCurrentThread(); 746 JNIEnv* env = AttachCurrentThread();
706 Java_MostVisitedURLsObserver_onPopularURLsAvailable( 747 Java_MostVisitedURLsObserver_onPopularURLsAvailable(
707 env, observer_.obj(), ToJavaArrayOfStrings(env, urls).obj(), 748 env, observer_.obj(), ToJavaArrayOfStrings(env, urls).obj(),
708 ToJavaArrayOfStrings(env, favicon_urls).obj()); 749 ToJavaArrayOfStrings(env, favicon_urls).obj());
709 750
710 QueryMostVisitedURLs(); 751 QueryMostVisitedURLs();
711 } 752 }
712 753
713 void MostVisitedSites::RecordThumbnailUMAMetrics() {
714 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumLocalThumbnailTilesHistogramName,
715 num_local_thumbs_);
716 num_local_thumbs_ = 0;
717 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumEmptyTilesHistogramName, num_empty_thumbs_);
718 num_empty_thumbs_ = 0;
719 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumServerTilesHistogramName, num_server_thumbs_);
720 num_server_thumbs_ = 0;
721 }
722
723 void MostVisitedSites::RecordImpressionUMAMetrics() { 754 void MostVisitedSites::RecordImpressionUMAMetrics() {
724 for (size_t i = 0; i < current_suggestions_.size(); i++) { 755 for (size_t i = 0; i < current_suggestions_.size(); i++) {
725 std::string histogram = base::StringPrintf( 756 std::string histogram = base::StringPrintf(
726 kImpressionHistogramFormat, 757 "NewTabPage.SuggestionsImpression.%s",
727 current_suggestions_[i]->GetSourceHistogramName().c_str()); 758 current_suggestions_[i]->GetSourceHistogramName().c_str());
728 LogHistogramEvent(histogram, static_cast<int>(i), num_sites_); 759 LogHistogramEvent(histogram, static_cast<int>(i), num_sites_);
729 } 760 }
730 } 761 }
731 762
732 void MostVisitedSites::TopSitesLoaded(history::TopSites* top_sites) { 763 void MostVisitedSites::TopSitesLoaded(history::TopSites* top_sites) {
733 } 764 }
734 765
735 void MostVisitedSites::TopSitesChanged(history::TopSites* top_sites, 766 void MostVisitedSites::TopSitesChanged(history::TopSites* top_sites,
736 ChangeReason change_reason) { 767 ChangeReason change_reason) {
737 if (mv_source_ == TOP_SITES) { 768 if (mv_source_ == TOP_SITES) {
738 // The displayed suggestions are invalidated. 769 // The displayed suggestions are invalidated.
739 QueryMostVisitedURLs(); 770 InitiateTopSitesQuery();
740 } 771 }
741 } 772 }
742 773
743 static jlong Init(JNIEnv* env, 774 static jlong Init(JNIEnv* env,
744 const JavaParamRef<jobject>& obj, 775 const JavaParamRef<jobject>& obj,
745 const JavaParamRef<jobject>& jprofile) { 776 const JavaParamRef<jobject>& jprofile) {
746 MostVisitedSites* most_visited_sites = 777 MostVisitedSites* most_visited_sites =
747 new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile)); 778 new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile));
748 return reinterpret_cast<intptr_t>(most_visited_sites); 779 return reinterpret_cast<intptr_t>(most_visited_sites);
749 } 780 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698