Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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. | 59 // Total number of tiles displayed. |
| 60 const char kNumTilesHistogramName[] = "NewTabPage.NumberOfTiles"; | 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 | 61 |
| 67 // Format for tile clicks histogram. | 62 // Format for tile clicks histograms. |
| 68 const char kOpenedItemHistogramFormat[] = "NewTabPage.MostVisited.%s"; | 63 const char kOpenedItemPositionHistogramFormat[] = "NewTabPage.MostVisited.%s"; |
| 69 // Format for tile impressions histogram. | 64 const char kOpenedItemTypeHistogramFormat[] = "NewTabPage.TileTypeClicked.%s"; |
| 70 const char kImpressionHistogramFormat[] = "NewTabPage.SuggestionsImpression.%s"; | 65 // Format for tile impressions histograms. |
| 66 const char kImpressionPositionHistogramFormat[] = | |
| 67 "NewTabPage.SuggestionsImpression.%s"; | |
| 68 const char kImpressionTypeHistogramFormat[] = "NewTabPage.TileType.%s"; | |
| 71 // Identifiers for the various tile sources. | 69 // Identifiers for the various tile sources. |
| 72 const char kHistogramClientName[] = "client"; | 70 const char kHistogramClientName[] = "client"; |
| 73 const char kHistogramServerName[] = "server"; | 71 const char kHistogramServerName[] = "server"; |
| 74 const char kHistogramServerFormat[] = "server%d"; | 72 const char kHistogramServerFormat[] = "server%d"; |
| 75 const char kHistogramPopularName[] = "popular"; | 73 const char kHistogramPopularName[] = "popular"; |
| 76 | 74 |
| 77 const char kPopularSitesFieldTrialName[] = "NTPPopularSites"; | 75 const char kPopularSitesFieldTrialName[] = "NTPPopularSites"; |
| 78 | 76 |
| 77 // The visual type of a most visited tile. | |
| 78 // | |
| 79 // These values must stay in sync with the MostVisitedTileType enum | |
| 80 // in histograms.xml. | |
| 81 // | |
| 82 // A Java counterpart will be generated for this enum. | |
| 83 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp | |
| 84 enum MostVisitedTileType { | |
| 85 // The icon or thumbnail hasn't loaded yet. | |
| 86 NONE, | |
| 87 // The item displays a site's actual favicon or touch icon. | |
| 88 ICON_REAL, | |
| 89 // The item displays a color derived from the site's favicon or touch icon. | |
| 90 ICON_COLOR, | |
| 91 // The item displays a default gray box in place of an icon. | |
| 92 ICON_DEFAULT, | |
| 93 // The item displays a locally-captured thumbnail of the site content. | |
| 94 THUMBNAIL_LOCAL, | |
| 95 // The item displays a server-provided thumbnail of the site content. | |
| 96 THUMBNAIL_SERVER, | |
| 97 // The item displays a default graphic in place of a thumbnail. | |
| 98 THUMBNAIL_DEFAULT, | |
| 99 NUM_TILE_TYPES, | |
| 100 }; | |
| 101 | |
| 79 scoped_ptr<SkBitmap> MaybeFetchLocalThumbnail( | 102 scoped_ptr<SkBitmap> MaybeFetchLocalThumbnail( |
| 80 const GURL& url, | 103 const GURL& url, |
| 81 const scoped_refptr<TopSites>& top_sites) { | 104 const scoped_refptr<TopSites>& top_sites) { |
| 82 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 105 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 83 scoped_refptr<base::RefCountedMemory> image; | 106 scoped_refptr<base::RefCountedMemory> image; |
| 84 scoped_ptr<SkBitmap> bitmap; | 107 scoped_ptr<SkBitmap> bitmap; |
| 85 if (top_sites && top_sites->GetPageThumbnail(url, false, &image)) | 108 if (top_sites && top_sites->GetPageThumbnail(url, false, &image)) |
| 86 bitmap.reset(gfx::JPEGCodec::Decode(image->front(), image->size())); | 109 bitmap.reset(gfx::JPEGCodec::Decode(image->front(), image->size())); |
| 87 return bitmap.Pass(); | 110 return bitmap.Pass(); |
| 88 } | 111 } |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 ? base::StringPrintf(kHistogramServerFormat, provider_index) | 222 ? base::StringPrintf(kHistogramServerFormat, provider_index) |
| 200 : kHistogramServerName; | 223 : kHistogramServerName; |
| 201 } | 224 } |
| 202 NOTREACHED(); | 225 NOTREACHED(); |
| 203 return std::string(); | 226 return std::string(); |
| 204 } | 227 } |
| 205 | 228 |
| 206 MostVisitedSites::MostVisitedSites(Profile* profile) | 229 MostVisitedSites::MostVisitedSites(Profile* profile) |
| 207 : profile_(profile), num_sites_(0), received_most_visited_sites_(false), | 230 : profile_(profile), num_sites_(0), received_most_visited_sites_(false), |
| 208 received_popular_sites_(false), recorded_uma_(false), | 231 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) { | 232 scoped_observer_(this), weak_ptr_factory_(this) { |
| 211 // Register the debugging page for the Suggestions Service and the thumbnails | 233 // Register the debugging page for the Suggestions Service and the thumbnails |
| 212 // debugging page. | 234 // debugging page. |
| 213 content::URLDataSource::Add(profile_, | 235 content::URLDataSource::Add(profile_, |
| 214 new suggestions::SuggestionsSource(profile_)); | 236 new suggestions::SuggestionsSource(profile_)); |
| 215 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); | 237 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); |
| 216 | 238 |
| 217 // Register this class as an observer to the sync service. It is important to | 239 // 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 | 240 // be notified of changes in the sync state such as initialization, sync |
| 219 // being enabled or disabled, etc. | 241 // being enabled or disabled, etc. |
| 220 ProfileSyncService* profile_sync_service = | 242 ProfileSyncService* profile_sync_service = |
| 221 ProfileSyncServiceFactory::GetForProfile(profile_); | 243 ProfileSyncServiceFactory::GetForProfile(profile_); |
| 222 if (profile_sync_service) | 244 if (profile_sync_service) |
| 223 profile_sync_service->AddObserver(this); | 245 profile_sync_service->AddObserver(this); |
| 224 } | 246 } |
| 225 | 247 |
| 226 MostVisitedSites::~MostVisitedSites() { | 248 MostVisitedSites::~MostVisitedSites() { |
| 227 ProfileSyncService* profile_sync_service = | 249 ProfileSyncService* profile_sync_service = |
| 228 ProfileSyncServiceFactory::GetForProfile(profile_); | 250 ProfileSyncServiceFactory::GetForProfile(profile_); |
| 229 if (profile_sync_service && profile_sync_service->HasObserver(this)) | 251 if (profile_sync_service && profile_sync_service->HasObserver(this)) |
| 230 profile_sync_service->RemoveObserver(this); | 252 profile_sync_service->RemoveObserver(this); |
| 231 } | 253 } |
| 232 | 254 |
| 233 void MostVisitedSites::Destroy(JNIEnv* env, jobject obj) { | 255 void MostVisitedSites::Destroy(JNIEnv* env, jobject obj) { |
| 234 delete this; | 256 delete this; |
| 235 } | 257 } |
| 236 | 258 |
| 237 void MostVisitedSites::OnLoadingComplete(JNIEnv* env, jobject obj) { | |
| 238 RecordThumbnailUMAMetrics(); | |
| 239 } | |
| 240 | |
| 241 void MostVisitedSites::SetMostVisitedURLsObserver(JNIEnv* env, | 259 void MostVisitedSites::SetMostVisitedURLsObserver(JNIEnv* env, |
| 242 jobject obj, | 260 jobject obj, |
| 243 jobject j_observer, | 261 jobject j_observer, |
| 244 jint num_sites) { | 262 jint num_sites) { |
| 245 observer_.Reset(env, j_observer); | 263 observer_.Reset(env, j_observer); |
| 246 num_sites_ = num_sites; | 264 num_sites_ = num_sites; |
| 247 | 265 |
| 248 if (ShouldShowPopularSites() && | 266 if (ShouldShowPopularSites() && |
| 249 NeedPopularSites(profile_->GetPrefs(), num_sites_)) { | 267 NeedPopularSites(profile_->GetPrefs(), num_sites_)) { |
| 250 popular_sites_.reset(new PopularSites( | 268 popular_sites_.reset(new PopularSites( |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 } | 354 } |
| 337 | 355 |
| 338 void MostVisitedSites::OnObtainedThumbnail( | 356 void MostVisitedSites::OnObtainedThumbnail( |
| 339 bool is_local_thumbnail, | 357 bool is_local_thumbnail, |
| 340 scoped_ptr<ScopedJavaGlobalRef<jobject>> j_callback, | 358 scoped_ptr<ScopedJavaGlobalRef<jobject>> j_callback, |
| 341 const GURL& url, | 359 const GURL& url, |
| 342 const SkBitmap* bitmap) { | 360 const SkBitmap* bitmap) { |
| 343 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 361 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 344 JNIEnv* env = AttachCurrentThread(); | 362 JNIEnv* env = AttachCurrentThread(); |
| 345 ScopedJavaLocalRef<jobject> j_bitmap; | 363 ScopedJavaLocalRef<jobject> j_bitmap; |
| 346 if (bitmap) { | 364 if (bitmap) |
| 347 j_bitmap = gfx::ConvertToJavaBitmap(bitmap); | 365 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( | 366 Java_ThumbnailCallback_onMostVisitedURLsThumbnailAvailable( |
| 357 env, j_callback->obj(), j_bitmap.obj()); | 367 env, j_callback->obj(), j_bitmap.obj(), is_local_thumbnail); |
| 358 } | 368 } |
| 359 | 369 |
| 360 void MostVisitedSites::BlacklistUrl(JNIEnv* env, | 370 void MostVisitedSites::BlacklistUrl(JNIEnv* env, |
| 361 jobject obj, | 371 jobject obj, |
| 362 jstring j_url) { | 372 jstring j_url) { |
| 363 GURL url(ConvertJavaStringToUTF8(env, j_url)); | 373 GURL url(ConvertJavaStringToUTF8(env, j_url)); |
| 364 | 374 |
| 365 // Always blacklist in the local TopSites. | 375 // Always blacklist in the local TopSites. |
| 366 scoped_refptr<TopSites> top_sites = TopSitesFactory::GetForProfile(profile_); | 376 scoped_refptr<TopSites> top_sites = TopSitesFactory::GetForProfile(profile_); |
| 367 if (top_sites) | 377 if (top_sites) |
| 368 top_sites->AddBlacklistedURL(url); | 378 top_sites->AddBlacklistedURL(url); |
| 369 | 379 |
| 370 // Only blacklist in the server-side suggestions service if it's active. | 380 // Only blacklist in the server-side suggestions service if it's active. |
| 371 if (mv_source_ == SUGGESTIONS_SERVICE) { | 381 if (mv_source_ == SUGGESTIONS_SERVICE) { |
| 372 SuggestionsService* suggestions_service = | 382 SuggestionsService* suggestions_service = |
| 373 SuggestionsServiceFactory::GetForProfile(profile_); | 383 SuggestionsServiceFactory::GetForProfile(profile_); |
| 374 DCHECK(suggestions_service); | 384 DCHECK(suggestions_service); |
| 375 suggestions_service->BlacklistURL( | 385 suggestions_service->BlacklistURL( |
| 376 url, base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, | 386 url, base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, |
| 377 weak_ptr_factory_.GetWeakPtr()), | 387 weak_ptr_factory_.GetWeakPtr()), |
| 378 base::Closure()); | 388 base::Closure()); |
| 379 } | 389 } |
| 380 } | 390 } |
| 381 | 391 |
| 392 void MostVisitedSites::RecordTileTypeMetrics(JNIEnv* env, | |
| 393 jobject obj, | |
| 394 jintArray jtile_types, | |
| 395 jboolean is_icon_mode) { | |
| 396 std::vector<int> tile_types; | |
| 397 base::android::JavaIntArrayToIntVector(env, jtile_types, &tile_types); | |
| 398 DCHECK_EQ(current_suggestions_.size(), tile_types.size()); | |
| 399 | |
| 400 int counts_per_type[NUM_TILE_TYPES] = {0}; | |
| 401 for (size_t i = 0; i < tile_types.size(); i++) { | |
| 402 int tile_type = tile_types[i]; | |
| 403 counts_per_type[tile_type]++; | |
| 404 std::string histogram = base::StringPrintf( | |
| 405 kImpressionTypeHistogramFormat, | |
| 406 current_suggestions_[i]->GetSourceHistogramName().c_str()); | |
| 407 LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES); | |
| 408 } | |
| 409 | |
| 410 if (is_icon_mode) { | |
| 411 UMA_HISTOGRAM_COUNTS_100("NewTabPage.IconsReal", | |
| 412 counts_per_type[ICON_REAL]); | |
| 413 UMA_HISTOGRAM_COUNTS_100("NewTabPage.IconsColor", | |
| 414 counts_per_type[ICON_COLOR]); | |
| 415 UMA_HISTOGRAM_COUNTS_100("NewTabPage.IconsGray", | |
| 416 counts_per_type[ICON_DEFAULT]); | |
| 417 } else { | |
| 418 UMA_HISTOGRAM_COUNTS_100("NewTabPage.NumberOfThumbnailTiles", | |
| 419 counts_per_type[THUMBNAIL_LOCAL]); | |
| 420 UMA_HISTOGRAM_COUNTS_100("NewTabPage.NumberOfExternalTiles", | |
| 421 counts_per_type[THUMBNAIL_SERVER]); | |
| 422 UMA_HISTOGRAM_COUNTS_100("NewTabPage.NumberOfGrayTiles", | |
| 423 counts_per_type[THUMBNAIL_DEFAULT]); | |
| 424 } | |
| 425 } | |
| 426 | |
| 382 void MostVisitedSites::RecordOpenedMostVisitedItem(JNIEnv* env, | 427 void MostVisitedSites::RecordOpenedMostVisitedItem(JNIEnv* env, |
| 383 jobject obj, | 428 jobject obj, |
| 384 jint index) { | 429 jint index, |
| 430 jint tile_type) { | |
| 385 DCHECK_GE(index, 0); | 431 DCHECK_GE(index, 0); |
| 386 DCHECK_LT(index, static_cast<int>(current_suggestions_.size())); | 432 DCHECK_LT(index, static_cast<int>(current_suggestions_.size())); |
| 387 std::string histogram = base::StringPrintf( | 433 std::string histogram = base::StringPrintf( |
| 388 kOpenedItemHistogramFormat, | 434 kOpenedItemPositionHistogramFormat, |
| 389 current_suggestions_[index]->GetSourceHistogramName().c_str()); | 435 current_suggestions_[index]->GetSourceHistogramName().c_str()); |
| 390 LogHistogramEvent(histogram, index, num_sites_); | 436 LogHistogramEvent(histogram, index, num_sites_); |
| 437 | |
| 438 histogram = base::StringPrintf( | |
| 439 kOpenedItemTypeHistogramFormat, | |
| 440 current_suggestions_[index]->GetSourceHistogramName().c_str()); | |
| 441 LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES); | |
| 391 } | 442 } |
| 392 | 443 |
| 393 void MostVisitedSites::OnStateChanged() { | 444 void MostVisitedSites::OnStateChanged() { |
| 394 // There have been changes to the sync state. This class cares about a few | 445 // 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 | 446 // (just initialized, enabled/disabled or history sync state changed). Re-run |
| 396 // the query code which will use the proper state. | 447 // the query code which will use the proper state. |
| 397 QueryMostVisitedURLs(); | 448 QueryMostVisitedURLs(); |
| 398 } | 449 } |
| 399 | 450 |
| 400 // static | 451 // static |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 703 favicon_urls.push_back(popular_site.favicon_url.spec()); | 754 favicon_urls.push_back(popular_site.favicon_url.spec()); |
| 704 } | 755 } |
| 705 JNIEnv* env = AttachCurrentThread(); | 756 JNIEnv* env = AttachCurrentThread(); |
| 706 Java_MostVisitedURLsObserver_onPopularURLsAvailable( | 757 Java_MostVisitedURLsObserver_onPopularURLsAvailable( |
| 707 env, observer_.obj(), ToJavaArrayOfStrings(env, urls).obj(), | 758 env, observer_.obj(), ToJavaArrayOfStrings(env, urls).obj(), |
| 708 ToJavaArrayOfStrings(env, favicon_urls).obj()); | 759 ToJavaArrayOfStrings(env, favicon_urls).obj()); |
| 709 | 760 |
| 710 QueryMostVisitedURLs(); | 761 QueryMostVisitedURLs(); |
| 711 } | 762 } |
| 712 | 763 |
| 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() { | 764 void MostVisitedSites::RecordImpressionUMAMetrics() { |
| 724 for (size_t i = 0; i < current_suggestions_.size(); i++) { | 765 for (size_t i = 0; i < current_suggestions_.size(); i++) { |
| 725 std::string histogram = base::StringPrintf( | 766 std::string histogram = base::StringPrintf( |
| 726 kImpressionHistogramFormat, | 767 kImpressionPositionHistogramFormat, |
| 727 current_suggestions_[i]->GetSourceHistogramName().c_str()); | 768 current_suggestions_[i]->GetSourceHistogramName().c_str()); |
| 728 LogHistogramEvent(histogram, static_cast<int>(i), num_sites_); | 769 LogHistogramEvent(histogram, static_cast<int>(i), num_sites_); |
| 729 } | 770 } |
| 730 } | 771 } |
| 731 | 772 |
| 732 void MostVisitedSites::TopSitesLoaded(history::TopSites* top_sites) { | 773 void MostVisitedSites::TopSitesLoaded(history::TopSites* top_sites) { |
| 733 } | 774 } |
| 734 | 775 |
| 735 void MostVisitedSites::TopSitesChanged(history::TopSites* top_sites, | 776 void MostVisitedSites::TopSitesChanged(history::TopSites* top_sites, |
| 736 ChangeReason change_reason) { | 777 ChangeReason change_reason) { |
| 737 if (mv_source_ == TOP_SITES) { | 778 if (mv_source_ == TOP_SITES) { |
| 738 // The displayed suggestions are invalidated. | 779 // The displayed suggestions are invalidated. |
| 739 QueryMostVisitedURLs(); | 780 InitiateTopSitesQuery(); |
|
newt (away)
2015/09/28 22:34:21
There's no need to requery the server suggestions
| |
| 740 } | 781 } |
| 741 } | 782 } |
| 742 | 783 |
| 743 static jlong Init(JNIEnv* env, | 784 static jlong Init(JNIEnv* env, |
| 744 const JavaParamRef<jobject>& obj, | 785 const JavaParamRef<jobject>& obj, |
| 745 const JavaParamRef<jobject>& jprofile) { | 786 const JavaParamRef<jobject>& jprofile) { |
| 746 MostVisitedSites* most_visited_sites = | 787 MostVisitedSites* most_visited_sites = |
| 747 new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile)); | 788 new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile)); |
| 748 return reinterpret_cast<intptr_t>(most_visited_sites); | 789 return reinterpret_cast<intptr_t>(most_visited_sites); |
| 749 } | 790 } |
| OLD | NEW |