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 <string> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/android/jni_android.h" | 7 #include "base/android/jni_android.h" |
| 11 #include "base/android/jni_array.h" | 8 #include "base/android/jni_array.h" |
| 12 #include "base/android/jni_string.h" | 9 #include "base/android/jni_string.h" |
| 13 #include "base/android/scoped_java_ref.h" | 10 #include "base/android/scoped_java_ref.h" |
| 14 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/command_line.h" | |
| 15 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 16 #include "base/metrics/sparse_histogram.h" | 14 #include "base/metrics/sparse_histogram.h" |
| 17 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 19 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
| 20 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 19 #include "chrome/browser/android/popular_sites.h" | |
| 21 #include "chrome/browser/history/top_sites_factory.h" | 20 #include "chrome/browser/history/top_sites_factory.h" |
| 22 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
| 23 #include "chrome/browser/profiles/profile_android.h" | 22 #include "chrome/browser/profiles/profile_android.h" |
| 24 #include "chrome/browser/search/suggestions/suggestions_service_factory.h" | 23 #include "chrome/browser/search/suggestions/suggestions_service_factory.h" |
| 25 #include "chrome/browser/search/suggestions/suggestions_source.h" | 24 #include "chrome/browser/search/suggestions/suggestions_source.h" |
| 26 #include "chrome/browser/sync/profile_sync_service.h" | 25 #include "chrome/browser/sync/profile_sync_service.h" |
| 27 #include "chrome/browser/sync/profile_sync_service_factory.h" | 26 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 28 #include "chrome/browser/thumbnails/thumbnail_list_source.h" | 27 #include "chrome/browser/thumbnails/thumbnail_list_source.h" |
| 28 #include "chrome/common/chrome_switches.h" | |
| 29 #include "components/history/core/browser/top_sites.h" | 29 #include "components/history/core/browser/top_sites.h" |
| 30 #include "components/suggestions/suggestions_service.h" | 30 #include "components/suggestions/suggestions_service.h" |
| 31 #include "components/suggestions/suggestions_utils.h" | 31 #include "components/suggestions/suggestions_utils.h" |
| 32 #include "content/public/browser/browser_thread.h" | 32 #include "content/public/browser/browser_thread.h" |
| 33 #include "content/public/browser/url_data_source.h" | 33 #include "content/public/browser/url_data_source.h" |
| 34 #include "jni/MostVisitedSites_jni.h" | 34 #include "jni/MostVisitedSites_jni.h" |
| 35 #include "third_party/skia/include/core/SkBitmap.h" | 35 #include "third_party/skia/include/core/SkBitmap.h" |
| 36 #include "ui/gfx/android/java_bitmap.h" | 36 #include "ui/gfx/android/java_bitmap.h" |
| 37 #include "ui/gfx/codec/jpeg_codec.h" | 37 #include "ui/gfx/codec/jpeg_codec.h" |
| 38 #include "url/gurl.h" | |
| 38 | 39 |
| 39 using base::android::AttachCurrentThread; | 40 using base::android::AttachCurrentThread; |
| 40 using base::android::ConvertUTF8ToJavaString; | |
| 41 using base::android::ConvertJavaStringToUTF8; | 41 using base::android::ConvertJavaStringToUTF8; |
| 42 using base::android::ScopedJavaGlobalRef; | 42 using base::android::ScopedJavaGlobalRef; |
| 43 using base::android::ScopedJavaLocalRef; | 43 using base::android::ScopedJavaLocalRef; |
| 44 using base::android::ToJavaArrayOfStrings; | 44 using base::android::ToJavaArrayOfStrings; |
| 45 using base::android::CheckException; | |
| 46 using base::WeakPtr; | |
| 47 using content::BrowserThread; | 45 using content::BrowserThread; |
| 48 using history::TopSites; | 46 using history::TopSites; |
| 49 using suggestions::ChromeSuggestion; | 47 using suggestions::ChromeSuggestion; |
| 50 using suggestions::SuggestionsProfile; | 48 using suggestions::SuggestionsProfile; |
| 51 using suggestions::SuggestionsService; | 49 using suggestions::SuggestionsService; |
| 52 using suggestions::SuggestionsServiceFactory; | 50 using suggestions::SuggestionsServiceFactory; |
| 53 using suggestions::SyncState; | 51 using suggestions::SyncState; |
| 54 | 52 |
| 55 namespace { | 53 namespace { |
| 56 | 54 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 ProfileSyncService* sync = | 107 ProfileSyncService* sync = |
| 110 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); | 108 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); |
| 111 if (!sync) | 109 if (!sync) |
| 112 return SyncState::SYNC_OR_HISTORY_SYNC_DISABLED; | 110 return SyncState::SYNC_OR_HISTORY_SYNC_DISABLED; |
| 113 return suggestions::GetSyncState( | 111 return suggestions::GetSyncState( |
| 114 sync->CanSyncStart(), | 112 sync->CanSyncStart(), |
| 115 sync->IsSyncActive() && sync->ConfigurationDone(), | 113 sync->IsSyncActive() && sync->ConfigurationDone(), |
| 116 sync->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES)); | 114 sync->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES)); |
| 117 } | 115 } |
| 118 | 116 |
| 117 bool ShouldShowPopularSites() { | |
| 118 // Note: It's important to query the field trial state first, to ensure that | |
| 119 // UMA reports the correct group. | |
| 120 const std::string group_name = | |
| 121 base::FieldTrialList::FindFullName("NTPPopularSites"); | |
| 122 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | |
| 123 if (cmd_line->HasSwitch(switches::kDisableNTPPopularSites)) | |
| 124 return false; | |
| 125 if (cmd_line->HasSwitch(switches::kEnableNTPPopularSites)) | |
| 126 return true; | |
| 127 return group_name == "Enabled"; | |
| 128 } | |
| 129 | |
| 119 } // namespace | 130 } // namespace |
| 120 | 131 |
| 121 MostVisitedSites::MostVisitedSites(Profile* profile) | 132 MostVisitedSites::MostVisitedSites(Profile* profile) |
| 122 : profile_(profile), num_sites_(0), initial_load_done_(false), | 133 : profile_(profile), num_sites_(0), initial_load_done_(false), |
| 123 num_local_thumbs_(0), num_server_thumbs_(0), num_empty_thumbs_(0), | 134 num_local_thumbs_(0), num_server_thumbs_(0), num_empty_thumbs_(0), |
| 124 scoped_observer_(this), weak_ptr_factory_(this) { | 135 scoped_observer_(this), weak_ptr_factory_(this) { |
| 125 // Register the debugging page for the Suggestions Service and the thumbnails | 136 // Register the debugging page for the Suggestions Service and the thumbnails |
| 126 // debugging page. | 137 // debugging page. |
| 127 content::URLDataSource::Add(profile_, | 138 content::URLDataSource::Add(profile_, |
| 128 new suggestions::SuggestionsSource(profile_)); | 139 new suggestions::SuggestionsSource(profile_)); |
| 129 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); | 140 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); |
| 130 | 141 |
| 131 // Register this class as an observer to the sync service. It is important to | 142 // Register this class as an observer to the sync service. It is important to |
| 132 // be notified of changes in the sync state such as initialization, sync | 143 // be notified of changes in the sync state such as initialization, sync |
| 133 // being enabled or disabled, etc. | 144 // being enabled or disabled, etc. |
| 134 ProfileSyncService* profile_sync_service = | 145 ProfileSyncService* profile_sync_service = |
| 135 ProfileSyncServiceFactory::GetForProfile(profile_); | 146 ProfileSyncServiceFactory::GetForProfile(profile_); |
| 136 if (profile_sync_service) | 147 if (profile_sync_service) |
| 137 profile_sync_service->AddObserver(this); | 148 profile_sync_service->AddObserver(this); |
| 149 | |
| 150 if (ShouldShowPopularSites()) { | |
| 151 popular_sites_.reset(new PopularSites( | |
| 152 profile_->GetRequestContext(), | |
| 153 base::Bind(&MostVisitedSites::OnPopularSitesAvailable, | |
| 154 base::Unretained(this)))); | |
| 155 } | |
| 138 } | 156 } |
| 139 | 157 |
| 140 MostVisitedSites::~MostVisitedSites() { | 158 MostVisitedSites::~MostVisitedSites() { |
| 141 ProfileSyncService* profile_sync_service = | 159 ProfileSyncService* profile_sync_service = |
| 142 ProfileSyncServiceFactory::GetForProfile(profile_); | 160 ProfileSyncServiceFactory::GetForProfile(profile_); |
| 143 if (profile_sync_service && profile_sync_service->HasObserver(this)) | 161 if (profile_sync_service && profile_sync_service->HasObserver(this)) |
| 144 profile_sync_service->RemoveObserver(this); | 162 profile_sync_service->RemoveObserver(this); |
| 145 } | 163 } |
| 146 | 164 |
| 147 void MostVisitedSites::Destroy(JNIEnv* env, jobject obj) { | 165 void MostVisitedSites::Destroy(JNIEnv* env, jobject obj) { |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 344 urls.push_back(visited.url.spec()); | 362 urls.push_back(visited.url.spec()); |
| 345 } | 363 } |
| 346 | 364 |
| 347 // Only log impression metrics on the initial load of the NTP. | 365 // Only log impression metrics on the initial load of the NTP. |
| 348 if (!initial_load_done_) { | 366 if (!initial_load_done_) { |
| 349 for (int i = 0; i < num_tiles; ++i) { | 367 for (int i = 0; i < num_tiles; ++i) { |
| 350 UMA_HISTOGRAM_SPARSE_SLOWLY(kImpressionClientHistogramName, i); | 368 UMA_HISTOGRAM_SPARSE_SLOWLY(kImpressionClientHistogramName, i); |
| 351 } | 369 } |
| 352 } | 370 } |
| 353 mv_source_ = TOP_SITES; | 371 mv_source_ = TOP_SITES; |
| 372 AddPopularSites(&titles, &urls); | |
| 354 NotifyMostVisitedURLsObserver(titles, urls); | 373 NotifyMostVisitedURLsObserver(titles, urls); |
| 355 } | 374 } |
| 356 | 375 |
| 357 void MostVisitedSites::OnSuggestionsProfileAvailable( | 376 void MostVisitedSites::OnSuggestionsProfileAvailable( |
| 358 const SuggestionsProfile& suggestions_profile) { | 377 const SuggestionsProfile& suggestions_profile) { |
| 359 int num_tiles = suggestions_profile.suggestions_size(); | 378 int num_tiles = suggestions_profile.suggestions_size(); |
| 360 // With no server suggestions, fall back to local Most Visited. | 379 // With no server suggestions, fall back to local Most Visited. |
| 361 if (num_tiles == 0) { | 380 if (num_tiles == 0) { |
| 362 InitiateTopSitesQuery(); | 381 InitiateTopSitesQuery(); |
| 363 return; | 382 return; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 378 kImpressionServerHistogramFormat, suggestion.providers(0)); | 397 kImpressionServerHistogramFormat, suggestion.providers(0)); |
| 379 LogHistogramEvent(histogram, i, num_sites_); | 398 LogHistogramEvent(histogram, i, num_sites_); |
| 380 } else { | 399 } else { |
| 381 UMA_HISTOGRAM_SPARSE_SLOWLY(kImpressionServerHistogramName, i); | 400 UMA_HISTOGRAM_SPARSE_SLOWLY(kImpressionServerHistogramName, i); |
| 382 } | 401 } |
| 383 } | 402 } |
| 384 } | 403 } |
| 385 mv_source_ = SUGGESTIONS_SERVICE; | 404 mv_source_ = SUGGESTIONS_SERVICE; |
| 386 // Keep a copy of the suggestions for eventual logging. | 405 // Keep a copy of the suggestions for eventual logging. |
| 387 server_suggestions_ = suggestions_profile; | 406 server_suggestions_ = suggestions_profile; |
| 407 AddPopularSites(&titles, &urls); | |
| 388 NotifyMostVisitedURLsObserver(titles, urls); | 408 NotifyMostVisitedURLsObserver(titles, urls); |
| 389 } | 409 } |
| 390 | 410 |
| 411 void MostVisitedSites::AddPopularSites(std::vector<base::string16>* titles, | |
| 412 std::vector<std::string>* urls) { | |
| 413 if (!popular_sites_) | |
| 414 return; | |
| 415 | |
| 416 DCHECK_EQ(titles->size(), urls->size()); | |
| 417 if (static_cast<int>(titles->size()) >= num_sites_) | |
| 418 return; | |
| 419 | |
| 420 for (const PopularSites::Site& popular_site : popular_sites_->sites()) { | |
| 421 // Skip popular sites that are already in the suggestions. | |
| 422 auto it = std::find_if(urls->begin(), urls->end(), | |
| 423 [&popular_site](const std::string& url) { | |
| 424 return GURL(url).host() == GURL(popular_site.url).host(); | |
|
Bernhard Bauer
2015/08/03 17:04:50
Could you pull the GURL(popular_site.url).host() o
Marc Treib
2015/08/04 08:16:41
Obsolete now that it's already a GURL.
| |
| 425 }); | |
| 426 if (it != urls->end()) | |
| 427 continue; | |
| 428 | |
| 429 titles->push_back(base::UTF8ToUTF16(popular_site.title)); | |
| 430 urls->push_back(popular_site.url); | |
| 431 if (static_cast<int>(titles->size()) >= num_sites_) | |
| 432 break; | |
| 433 } | |
| 434 } | |
| 435 | |
| 391 void MostVisitedSites::NotifyMostVisitedURLsObserver( | 436 void MostVisitedSites::NotifyMostVisitedURLsObserver( |
| 392 const std::vector<base::string16>& titles, | 437 const std::vector<base::string16>& titles, |
| 393 const std::vector<std::string>& urls) { | 438 const std::vector<std::string>& urls) { |
| 394 DCHECK_EQ(titles.size(), urls.size()); | 439 DCHECK_EQ(titles.size(), urls.size()); |
| 395 if (!initial_load_done_) | 440 if (!initial_load_done_) |
| 396 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumTilesHistogramName, titles.size()); | 441 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumTilesHistogramName, titles.size()); |
| 397 initial_load_done_ = true; | 442 initial_load_done_ = true; |
| 398 JNIEnv* env = AttachCurrentThread(); | 443 JNIEnv* env = AttachCurrentThread(); |
| 399 Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable( | 444 Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable( |
| 400 env, observer_.obj(), ToJavaArrayOfStrings(env, titles).obj(), | 445 env, observer_.obj(), ToJavaArrayOfStrings(env, titles).obj(), |
| 401 ToJavaArrayOfStrings(env, urls).obj()); | 446 ToJavaArrayOfStrings(env, urls).obj()); |
| 402 } | 447 } |
| 403 | 448 |
| 449 void MostVisitedSites::OnPopularSitesAvailable(bool success) { | |
| 450 if (!success) { | |
| 451 LOG(WARNING) << "Download of popular sites failed"; | |
| 452 return; | |
| 453 } | |
| 454 | |
| 455 if (!observer_.is_null()) | |
| 456 QueryMostVisitedURLs(); | |
| 457 } | |
| 458 | |
| 404 void MostVisitedSites::RecordUMAMetrics() { | 459 void MostVisitedSites::RecordUMAMetrics() { |
| 405 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumLocalThumbnailTilesHistogramName, | 460 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumLocalThumbnailTilesHistogramName, |
| 406 num_local_thumbs_); | 461 num_local_thumbs_); |
| 407 num_local_thumbs_ = 0; | 462 num_local_thumbs_ = 0; |
| 408 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumEmptyTilesHistogramName, num_empty_thumbs_); | 463 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumEmptyTilesHistogramName, num_empty_thumbs_); |
| 409 num_empty_thumbs_ = 0; | 464 num_empty_thumbs_ = 0; |
| 410 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumServerTilesHistogramName, num_server_thumbs_); | 465 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumServerTilesHistogramName, num_server_thumbs_); |
| 411 num_server_thumbs_ = 0; | 466 num_server_thumbs_ = 0; |
| 412 } | 467 } |
| 413 | 468 |
| 414 void MostVisitedSites::TopSitesLoaded(history::TopSites* top_sites) { | 469 void MostVisitedSites::TopSitesLoaded(history::TopSites* top_sites) { |
| 415 } | 470 } |
| 416 | 471 |
| 417 void MostVisitedSites::TopSitesChanged(history::TopSites* top_sites, | 472 void MostVisitedSites::TopSitesChanged(history::TopSites* top_sites, |
| 418 ChangeReason change_reason) { | 473 ChangeReason change_reason) { |
| 419 if (mv_source_ == TOP_SITES) { | 474 if (mv_source_ == TOP_SITES) { |
| 420 // The displayed suggestions are invalidated. | 475 // The displayed suggestions are invalidated. |
| 421 QueryMostVisitedURLs(); | 476 QueryMostVisitedURLs(); |
| 422 } | 477 } |
| 423 } | 478 } |
| 424 | 479 |
| 425 static jlong Init(JNIEnv* env, jobject obj, jobject jprofile) { | 480 static jlong Init(JNIEnv* env, jobject obj, jobject jprofile) { |
| 426 MostVisitedSites* most_visited_sites = | 481 MostVisitedSites* most_visited_sites = |
| 427 new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile)); | 482 new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile)); |
| 428 return reinterpret_cast<intptr_t>(most_visited_sites); | 483 return reinterpret_cast<intptr_t>(most_visited_sites); |
| 429 } | 484 } |
| OLD | NEW |