[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "chrome/browser/android/most_visited_sites.h" |
| 6 | |
| 7 | #include "base/android/jni_android.h" |
| 8 | #include "base/android/jni_array.h" |
| 9 | #include "base/android/jni_string.h" |
| 10 | #include "base/android/scoped_java_ref.h" |
[email protected] | d33adb40d | 2014-06-03 21:38:46 | [diff] [blame] | 11 | #include "base/callback.h" |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 12 | #include "base/command_line.h" |
[email protected] | 9ed2f5c | 2014-06-13 14:55:24 | [diff] [blame] | 13 | #include "base/metrics/histogram.h" |
[email protected] | 1d778e1 | 2014-06-17 02:28:51 | [diff] [blame] | 14 | #include "base/metrics/sparse_histogram.h" |
[email protected] | 9ed2f5c | 2014-06-13 14:55:24 | [diff] [blame] | 15 | #include "base/strings/string_number_conversions.h" |
treib | eba6cee | 2015-09-09 13:25:59 | [diff] [blame^] | 16 | #include "base/strings/string_util.h" |
[email protected] | 9ed2f5c | 2014-06-13 14:55:24 | [diff] [blame] | 17 | #include "base/strings/stringprintf.h" |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 18 | #include "base/strings/utf_string_conversions.h" |
[email protected] | 6d21c70 | 2014-05-15 06:10:21 | [diff] [blame] | 19 | #include "base/time/time.h" |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 20 | #include "chrome/browser/android/popular_sites.h" |
jitendra.ks | 30f0339 | 2015-01-28 09:47:18 | [diff] [blame] | 21 | #include "chrome/browser/history/top_sites_factory.h" |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 22 | #include "chrome/browser/profiles/profile.h" |
| 23 | #include "chrome/browser/profiles/profile_android.h" |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 24 | #include "chrome/browser/search/suggestions/suggestions_service_factory.h" |
[email protected] | 81e09e7 | 2014-05-07 13:41:22 | [diff] [blame] | 25 | #include "chrome/browser/search/suggestions/suggestions_source.h" |
[email protected] | 1d1ab15 | 2014-08-21 17:14:12 | [diff] [blame] | 26 | #include "chrome/browser/sync/profile_sync_service.h" |
| 27 | #include "chrome/browser/sync/profile_sync_service_factory.h" |
[email protected] | 81e09e7 | 2014-05-07 13:41:22 | [diff] [blame] | 28 | #include "chrome/browser/thumbnails/thumbnail_list_source.h" |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 29 | #include "chrome/common/chrome_switches.h" |
sdefresne | 0da3bc0 | 2015-01-29 18:26:35 | [diff] [blame] | 30 | #include "components/history/core/browser/top_sites.h" |
[email protected] | bdceb3ba | 2014-07-25 16:47:48 | [diff] [blame] | 31 | #include "components/suggestions/suggestions_service.h" |
[email protected] | 1d1ab15 | 2014-08-21 17:14:12 | [diff] [blame] | 32 | #include "components/suggestions/suggestions_utils.h" |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 33 | #include "content/public/browser/browser_thread.h" |
[email protected] | 81e09e7 | 2014-05-07 13:41:22 | [diff] [blame] | 34 | #include "content/public/browser/url_data_source.h" |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 35 | #include "jni/MostVisitedSites_jni.h" |
| 36 | #include "third_party/skia/include/core/SkBitmap.h" |
| 37 | #include "ui/gfx/android/java_bitmap.h" |
| 38 | #include "ui/gfx/codec/jpeg_codec.h" |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 39 | #include "url/gurl.h" |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 40 | |
| 41 | using base::android::AttachCurrentThread; |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 42 | using base::android::ConvertJavaStringToUTF8; |
| 43 | using base::android::ScopedJavaGlobalRef; |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 44 | using base::android::ScopedJavaLocalRef; |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 45 | using base::android::ToJavaArrayOfStrings; |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 46 | using content::BrowserThread; |
| 47 | using history::TopSites; |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 48 | using suggestions::ChromeSuggestion; |
| 49 | using suggestions::SuggestionsProfile; |
| 50 | using suggestions::SuggestionsService; |
| 51 | using suggestions::SuggestionsServiceFactory; |
[email protected] | 1d1ab15 | 2014-08-21 17:14:12 | [diff] [blame] | 52 | using suggestions::SyncState; |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 53 | |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 54 | namespace { |
| 55 | |
[email protected] | 92a59882 | 2014-06-17 10:25:56 | [diff] [blame] | 56 | // Total number of tiles displayed. |
[email protected] | 9ed2f5c | 2014-06-13 14:55:24 | [diff] [blame] | 57 | const char kNumTilesHistogramName[] = "NewTabPage.NumberOfTiles"; |
[email protected] | 92a59882 | 2014-06-17 10:25:56 | [diff] [blame] | 58 | // Tracking thumbnails. |
[email protected] | 1d778e1 | 2014-06-17 02:28:51 | [diff] [blame] | 59 | const char kNumLocalThumbnailTilesHistogramName[] = |
| 60 | "NewTabPage.NumberOfThumbnailTiles"; |
| 61 | const char kNumEmptyTilesHistogramName[] = "NewTabPage.NumberOfGrayTiles"; |
| 62 | const char kNumServerTilesHistogramName[] = "NewTabPage.NumberOfExternalTiles"; |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 63 | |
| 64 | // Format for tile clicks histogram. |
| 65 | const char kOpenedItemHistogramFormat[] = "NewTabPage.MostVisited.%s"; |
| 66 | // Format for tile impressions histogram. |
| 67 | const char kImpressionHistogramFormat[] = "NewTabPage.SuggestionsImpression.%s"; |
| 68 | // Identifiers for the various tile sources. |
| 69 | const char kHistogramClientName[] = "client"; |
| 70 | const char kHistogramServerName[] = "server"; |
| 71 | const char kHistogramServerFormat[] = "server%d"; |
| 72 | const char kHistogramPopularName[] = "popular"; |
[email protected] | 9ed2f5c | 2014-06-13 14:55:24 | [diff] [blame] | 73 | |
treib | 508939a | 2015-08-25 10:07:56 | [diff] [blame] | 74 | const char kPopularSitesFieldTrialName[] = "NTPPopularSites"; |
| 75 | |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 76 | scoped_ptr<SkBitmap> MaybeFetchLocalThumbnail( |
| 77 | const GURL& url, |
| 78 | const scoped_refptr<TopSites>& top_sites) { |
| 79 | DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 80 | scoped_refptr<base::RefCountedMemory> image; |
| 81 | scoped_ptr<SkBitmap> bitmap; |
| 82 | if (top_sites && top_sites->GetPageThumbnail(url, false, &image)) |
| 83 | bitmap.reset(gfx::JPEGCodec::Decode(image->front(), image->size())); |
| 84 | return bitmap.Pass(); |
[email protected] | d33adb40d | 2014-06-03 21:38:46 | [diff] [blame] | 85 | } |
| 86 | |
[email protected] | 92a59882 | 2014-06-17 10:25:56 | [diff] [blame] | 87 | // Log an event for a given |histogram| at a given element |position|. This |
| 88 | // routine exists because regular histogram macros are cached thus can't be used |
| 89 | // if the name of the histogram will change at a given call site. |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 90 | void LogHistogramEvent(const std::string& histogram, |
| 91 | int position, |
[email protected] | 92a59882 | 2014-06-17 10:25:56 | [diff] [blame] | 92 | int num_sites) { |
[email protected] | 9ed2f5c | 2014-06-13 14:55:24 | [diff] [blame] | 93 | base::HistogramBase* counter = base::LinearHistogram::FactoryGet( |
[email protected] | 92a59882 | 2014-06-17 10:25:56 | [diff] [blame] | 94 | histogram, |
[email protected] | 9ed2f5c | 2014-06-13 14:55:24 | [diff] [blame] | 95 | 1, |
| 96 | num_sites, |
| 97 | num_sites + 1, |
| 98 | base::Histogram::kUmaTargetedHistogramFlag); |
[email protected] | 6f67448 | 2014-08-11 22:50:49 | [diff] [blame] | 99 | if (counter) |
| 100 | counter->Add(position); |
[email protected] | 9ed2f5c | 2014-06-13 14:55:24 | [diff] [blame] | 101 | } |
| 102 | |
[email protected] | 1d1ab15 | 2014-08-21 17:14:12 | [diff] [blame] | 103 | // Return the current SyncState for use with the SuggestionsService. |
| 104 | SyncState GetSyncState(Profile* profile) { |
| 105 | ProfileSyncService* sync = |
| 106 | ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); |
| 107 | if (!sync) |
| 108 | return SyncState::SYNC_OR_HISTORY_SYNC_DISABLED; |
| 109 | return suggestions::GetSyncState( |
maxbogue | 96b7d27 | 2015-06-16 02:59:58 | [diff] [blame] | 110 | sync->CanSyncStart(), |
maxbogue | 192b360 | 2015-06-04 00:33:55 | [diff] [blame] | 111 | sync->IsSyncActive() && sync->ConfigurationDone(), |
[email protected] | 1d1ab15 | 2014-08-21 17:14:12 | [diff] [blame] | 112 | sync->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES)); |
| 113 | } |
| 114 | |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 115 | bool ShouldShowPopularSites() { |
| 116 | // Note: It's important to query the field trial state first, to ensure that |
| 117 | // UMA reports the correct group. |
| 118 | const std::string group_name = |
treib | 508939a | 2015-08-25 10:07:56 | [diff] [blame] | 119 | base::FieldTrialList::FindFullName(kPopularSitesFieldTrialName); |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 120 | base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| 121 | if (cmd_line->HasSwitch(switches::kDisableNTPPopularSites)) |
| 122 | return false; |
| 123 | if (cmd_line->HasSwitch(switches::kEnableNTPPopularSites)) |
| 124 | return true; |
treib | eba6cee | 2015-09-09 13:25:59 | [diff] [blame^] | 125 | return base::StartsWith(group_name, "Enabled", |
| 126 | base::CompareCase::INSENSITIVE_ASCII); |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 127 | } |
| 128 | |
treib | 508939a | 2015-08-25 10:07:56 | [diff] [blame] | 129 | std::string GetPopularSitesFilename() { |
| 130 | return variations::GetVariationParamValue(kPopularSitesFieldTrialName, |
| 131 | "filename"); |
| 132 | } |
| 133 | |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 134 | } // namespace |
| 135 | |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 136 | MostVisitedSites::MostVisitedSites(Profile* profile) |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 137 | : profile_(profile), num_sites_(0), received_most_visited_sites_(false), |
| 138 | received_popular_sites_(false), recorded_uma_(false), |
mathp | d91e8eb | 2015-03-24 17:37:47 | [diff] [blame] | 139 | num_local_thumbs_(0), num_server_thumbs_(0), num_empty_thumbs_(0), |
| 140 | scoped_observer_(this), weak_ptr_factory_(this) { |
[email protected] | 81e09e7 | 2014-05-07 13:41:22 | [diff] [blame] | 141 | // Register the debugging page for the Suggestions Service and the thumbnails |
| 142 | // debugging page. |
| 143 | content::URLDataSource::Add(profile_, |
| 144 | new suggestions::SuggestionsSource(profile_)); |
| 145 | content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); |
[email protected] | 1d1ab15 | 2014-08-21 17:14:12 | [diff] [blame] | 146 | |
| 147 | // Register this class as an observer to the sync service. It is important to |
| 148 | // be notified of changes in the sync state such as initialization, sync |
| 149 | // being enabled or disabled, etc. |
| 150 | ProfileSyncService* profile_sync_service = |
| 151 | ProfileSyncServiceFactory::GetForProfile(profile_); |
| 152 | if (profile_sync_service) |
| 153 | profile_sync_service->AddObserver(this); |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 154 | |
| 155 | if (ShouldShowPopularSites()) { |
| 156 | popular_sites_.reset(new PopularSites( |
maybelle | a18d7d0 | 2015-09-08 14:28:25 | [diff] [blame] | 157 | profile, |
treib | 508939a | 2015-08-25 10:07:56 | [diff] [blame] | 158 | GetPopularSitesFilename(), |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 159 | profile_->GetRequestContext(), |
| 160 | base::Bind(&MostVisitedSites::OnPopularSitesAvailable, |
| 161 | base::Unretained(this)))); |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 162 | } else { |
| 163 | received_popular_sites_ = true; |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 164 | } |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 165 | } |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 166 | |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 167 | MostVisitedSites::~MostVisitedSites() { |
feng | 94a4210 | 2014-08-26 23:42:39 | [diff] [blame] | 168 | ProfileSyncService* profile_sync_service = |
| 169 | ProfileSyncServiceFactory::GetForProfile(profile_); |
| 170 | if (profile_sync_service && profile_sync_service->HasObserver(this)) |
| 171 | profile_sync_service->RemoveObserver(this); |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 172 | } |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 173 | |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 174 | void MostVisitedSites::Destroy(JNIEnv* env, jobject obj) { |
| 175 | delete this; |
| 176 | } |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 177 | |
[email protected] | 1d778e1 | 2014-06-17 02:28:51 | [diff] [blame] | 178 | void MostVisitedSites::OnLoadingComplete(JNIEnv* env, jobject obj) { |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 179 | RecordThumbnailUMAMetrics(); |
[email protected] | 1d778e1 | 2014-06-17 02:28:51 | [diff] [blame] | 180 | } |
| 181 | |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 182 | void MostVisitedSites::SetMostVisitedURLsObserver(JNIEnv* env, |
| 183 | jobject obj, |
| 184 | jobject j_observer, |
| 185 | jint num_sites) { |
| 186 | observer_.Reset(env, j_observer); |
| 187 | num_sites_ = num_sites; |
[email protected] | 852fc79 | 2013-10-04 04:15:12 | [diff] [blame] | 188 | |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 189 | QueryMostVisitedURLs(); |
| 190 | |
jitendra.ks | 30f0339 | 2015-01-28 09:47:18 | [diff] [blame] | 191 | scoped_refptr<history::TopSites> top_sites = |
| 192 | TopSitesFactory::GetForProfile(profile_); |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 193 | if (top_sites) { |
| 194 | // TopSites updates itself after a delay. To ensure up-to-date results, |
| 195 | // force an update now. |
| 196 | top_sites->SyncWithHistory(); |
| 197 | |
sdefresne | edf9e01f | 2015-01-13 19:45:41 | [diff] [blame] | 198 | // Register as TopSitesObserver so that we can update ourselves when the |
| 199 | // TopSites changes. |
jitendra.ks | 30f0339 | 2015-01-28 09:47:18 | [diff] [blame] | 200 | scoped_observer_.Add(top_sites.get()); |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 201 | } |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 202 | } |
| 203 | |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 204 | void MostVisitedSites::GetURLThumbnail(JNIEnv* env, |
| 205 | jobject obj, |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 206 | jstring j_url, |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 207 | jobject j_callback_obj) { |
mostynb | 351bf98 | 2015-03-25 22:26:58 | [diff] [blame] | 208 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 209 | scoped_ptr<ScopedJavaGlobalRef<jobject>> j_callback( |
| 210 | new ScopedJavaGlobalRef<jobject>()); |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 211 | j_callback->Reset(env, j_callback_obj); |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 212 | |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 213 | GURL url(ConvertJavaStringToUTF8(env, j_url)); |
jitendra.ks | 30f0339 | 2015-01-28 09:47:18 | [diff] [blame] | 214 | scoped_refptr<TopSites> top_sites(TopSitesFactory::GetForProfile(profile_)); |
[email protected] | d33adb40d | 2014-06-03 21:38:46 | [diff] [blame] | 215 | |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 216 | BrowserThread::PostTaskAndReplyWithResult( |
[email protected] | d33adb40d | 2014-06-03 21:38:46 | [diff] [blame] | 217 | BrowserThread::DB, FROM_HERE, |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 218 | base::Bind(&MaybeFetchLocalThumbnail, url, top_sites), |
| 219 | base::Bind(&MostVisitedSites::OnLocalThumbnailFetched, |
| 220 | weak_ptr_factory_.GetWeakPtr(), url, |
| 221 | base::Passed(&j_callback))); |
| 222 | } |
| 223 | |
| 224 | void MostVisitedSites::OnLocalThumbnailFetched( |
| 225 | const GURL& url, |
| 226 | scoped_ptr<ScopedJavaGlobalRef<jobject>> j_callback, |
| 227 | scoped_ptr<SkBitmap> bitmap) { |
| 228 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 229 | if (!bitmap.get()) { |
| 230 | // A thumbnail is not locally available for |url|. Make sure it is put in |
| 231 | // the list to be fetched at the next visit to this site. |
| 232 | scoped_refptr<TopSites> top_sites(TopSitesFactory::GetForProfile(profile_)); |
| 233 | if (top_sites) |
| 234 | top_sites->AddForcedURL(url, base::Time::Now()); |
treib | ac5372f | 2015-09-09 09:08:22 | [diff] [blame] | 235 | // Also fetch a remote thumbnail if possible. PopularSites or the |
| 236 | // SuggestionsService can supply a thumbnail download URL. |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 237 | SuggestionsService* suggestions_service = |
treib | ac5372f | 2015-09-09 09:08:22 | [diff] [blame] | 238 | SuggestionsServiceFactory::GetForProfile(profile_); |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 239 | if (suggestions_service) { |
treib | ac5372f | 2015-09-09 09:08:22 | [diff] [blame] | 240 | if (popular_sites_) { |
| 241 | const std::vector<PopularSites::Site>& sites = popular_sites_->sites(); |
| 242 | auto it = std::find_if(sites.begin(), sites.end(), |
| 243 | [&url](const PopularSites::Site& site) { |
| 244 | return site.url == url; |
| 245 | }); |
| 246 | if (it != sites.end() && it->thumbnail_url.is_valid()) { |
| 247 | return suggestions_service->GetPageThumbnailWithURL( |
| 248 | url, it->thumbnail_url, |
| 249 | base::Bind(&MostVisitedSites::OnObtainedThumbnail, |
| 250 | weak_ptr_factory_.GetWeakPtr(), false, |
| 251 | base::Passed(&j_callback))); |
| 252 | } |
| 253 | } |
| 254 | if (mv_source_ == SUGGESTIONS_SERVICE) { |
| 255 | return suggestions_service->GetPageThumbnail( |
| 256 | url, base::Bind(&MostVisitedSites::OnObtainedThumbnail, |
| 257 | weak_ptr_factory_.GetWeakPtr(), false, |
| 258 | base::Passed(&j_callback))); |
| 259 | } |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 260 | } |
| 261 | } |
| 262 | OnObtainedThumbnail(true, j_callback.Pass(), url, bitmap.get()); |
| 263 | } |
| 264 | |
| 265 | void MostVisitedSites::OnObtainedThumbnail( |
| 266 | bool is_local_thumbnail, |
| 267 | scoped_ptr<ScopedJavaGlobalRef<jobject>> j_callback, |
| 268 | const GURL& url, |
| 269 | const SkBitmap* bitmap) { |
| 270 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 271 | JNIEnv* env = AttachCurrentThread(); |
| 272 | ScopedJavaLocalRef<jobject> j_bitmap; |
| 273 | if (bitmap) { |
| 274 | j_bitmap = gfx::ConvertToJavaBitmap(bitmap); |
| 275 | if (is_local_thumbnail) { |
| 276 | ++num_local_thumbs_; |
| 277 | } else { |
| 278 | ++num_server_thumbs_; |
| 279 | } |
| 280 | } else { |
| 281 | ++num_empty_thumbs_; |
| 282 | } |
| 283 | Java_ThumbnailCallback_onMostVisitedURLsThumbnailAvailable( |
| 284 | env, j_callback->obj(), j_bitmap.obj()); |
[email protected] | c764b282 | 2013-07-03 04:16:48 | [diff] [blame] | 285 | } |
[email protected] | a4c2f28 | 2013-07-20 05:26:05 | [diff] [blame] | 286 | |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 287 | void MostVisitedSites::BlacklistUrl(JNIEnv* env, |
| 288 | jobject obj, |
| 289 | jstring j_url) { |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 290 | GURL url(ConvertJavaStringToUTF8(env, j_url)); |
[email protected] | a4c2f28 | 2013-07-20 05:26:05 | [diff] [blame] | 291 | |
treib | fac7519 | 2015-08-17 13:21:24 | [diff] [blame] | 292 | // Always blacklist in the local TopSites. |
| 293 | scoped_refptr<TopSites> top_sites = TopSitesFactory::GetForProfile(profile_); |
| 294 | if (top_sites) |
| 295 | top_sites->AddBlacklistedURL(url); |
[email protected] | d497524 | 2014-06-02 18:16:20 | [diff] [blame] | 296 | |
treib | fac7519 | 2015-08-17 13:21:24 | [diff] [blame] | 297 | // Only blacklist in the server-side suggestions service if it's active. |
| 298 | if (mv_source_ == SUGGESTIONS_SERVICE) { |
| 299 | SuggestionsService* suggestions_service = |
| 300 | SuggestionsServiceFactory::GetForProfile(profile_); |
| 301 | DCHECK(suggestions_service); |
| 302 | suggestions_service->BlacklistURL( |
| 303 | url, base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, |
| 304 | weak_ptr_factory_.GetWeakPtr()), |
| 305 | base::Closure()); |
[email protected] | d497524 | 2014-06-02 18:16:20 | [diff] [blame] | 306 | } |
[email protected] | a4c2f28 | 2013-07-20 05:26:05 | [diff] [blame] | 307 | } |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 308 | |
[email protected] | 92a59882 | 2014-06-17 10:25:56 | [diff] [blame] | 309 | void MostVisitedSites::RecordOpenedMostVisitedItem(JNIEnv* env, |
| 310 | jobject obj, |
| 311 | jint index) { |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 312 | DCHECK_GE(index, 0); |
| 313 | DCHECK_LT(index, static_cast<int>(tile_sources_.size())); |
| 314 | std::string histogram = base::StringPrintf(kOpenedItemHistogramFormat, |
| 315 | tile_sources_[index].c_str()); |
| 316 | LogHistogramEvent(histogram, index, num_sites_); |
[email protected] | 92a59882 | 2014-06-17 10:25:56 | [diff] [blame] | 317 | } |
| 318 | |
[email protected] | 1d1ab15 | 2014-08-21 17:14:12 | [diff] [blame] | 319 | void MostVisitedSites::OnStateChanged() { |
| 320 | // There have been changes to the sync state. This class cares about a few |
| 321 | // (just initialized, enabled/disabled or history sync state changed). Re-run |
| 322 | // the query code which will use the proper state. |
| 323 | QueryMostVisitedURLs(); |
| 324 | } |
| 325 | |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 326 | // static |
| 327 | bool MostVisitedSites::Register(JNIEnv* env) { |
| 328 | return RegisterNativesImpl(env); |
| 329 | } |
| 330 | |
| 331 | void MostVisitedSites::QueryMostVisitedURLs() { |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 332 | SuggestionsService* suggestions_service = |
[email protected] | d497524 | 2014-06-02 18:16:20 | [diff] [blame] | 333 | SuggestionsServiceFactory::GetForProfile(profile_); |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 334 | if (suggestions_service) { |
| 335 | // Suggestions service is enabled, initiate a query. |
| 336 | suggestions_service->FetchSuggestionsData( |
[email protected] | 1d1ab15 | 2014-08-21 17:14:12 | [diff] [blame] | 337 | GetSyncState(profile_), |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 338 | base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, |
| 339 | weak_ptr_factory_.GetWeakPtr())); |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 340 | } else { |
| 341 | InitiateTopSitesQuery(); |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | void MostVisitedSites::InitiateTopSitesQuery() { |
jitendra.ks | 30f0339 | 2015-01-28 09:47:18 | [diff] [blame] | 346 | scoped_refptr<TopSites> top_sites = TopSitesFactory::GetForProfile(profile_); |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 347 | if (!top_sites) |
| 348 | return; |
| 349 | |
| 350 | top_sites->GetMostVisitedURLs( |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 351 | base::Bind(&MostVisitedSites::OnMostVisitedURLsAvailable, |
| 352 | weak_ptr_factory_.GetWeakPtr()), |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 353 | false); |
| 354 | } |
| 355 | |
[email protected] | d497524 | 2014-06-02 18:16:20 | [diff] [blame] | 356 | void MostVisitedSites::OnMostVisitedURLsAvailable( |
[email protected] | d497524 | 2014-06-02 18:16:20 | [diff] [blame] | 357 | const history::MostVisitedURLList& visited_list) { |
| 358 | std::vector<base::string16> titles; |
| 359 | std::vector<std::string> urls; |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 360 | tile_sources_.clear(); |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 361 | int num_tiles = std::min(static_cast<int>(visited_list.size()), num_sites_); |
| 362 | for (int i = 0; i < num_tiles; ++i) { |
| 363 | const history::MostVisitedURL& visited = visited_list[i]; |
| 364 | if (visited.url.is_empty()) { |
| 365 | num_tiles = i; |
| 366 | break; // This is the signal that there are no more real visited sites. |
| 367 | } |
| 368 | titles.push_back(visited.title); |
| 369 | urls.push_back(visited.url.spec()); |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 370 | tile_sources_.push_back(kHistogramClientName); |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 371 | } |
[email protected] | d497524 | 2014-06-02 18:16:20 | [diff] [blame] | 372 | |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 373 | received_most_visited_sites_ = true; |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 374 | mv_source_ = TOP_SITES; |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 375 | AddPopularSites(&titles, &urls); |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 376 | NotifyMostVisitedURLsObserver(titles, urls); |
[email protected] | d497524 | 2014-06-02 18:16:20 | [diff] [blame] | 377 | } |
| 378 | |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 379 | void MostVisitedSites::OnSuggestionsProfileAvailable( |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 380 | const SuggestionsProfile& suggestions_profile) { |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 381 | int num_tiles = suggestions_profile.suggestions_size(); |
mathp | d91e8eb | 2015-03-24 17:37:47 | [diff] [blame] | 382 | // With no server suggestions, fall back to local Most Visited. |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 383 | if (num_tiles == 0) { |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 384 | InitiateTopSitesQuery(); |
| 385 | return; |
| 386 | } |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 387 | if (num_sites_ < num_tiles) |
| 388 | num_tiles = num_sites_; |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 389 | |
| 390 | std::vector<base::string16> titles; |
| 391 | std::vector<std::string> urls; |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 392 | tile_sources_.clear(); |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 393 | for (int i = 0; i < num_tiles; ++i) { |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 394 | const ChromeSuggestion& suggestion = suggestions_profile.suggestions(i); |
| 395 | titles.push_back(base::UTF8ToUTF16(suggestion.title())); |
| 396 | urls.push_back(suggestion.url()); |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 397 | std::string tile_source; |
| 398 | if (suggestion.providers_size() > 0) { |
| 399 | tile_source = |
| 400 | base::StringPrintf(kHistogramServerFormat, suggestion.providers(0)); |
| 401 | } else { |
| 402 | tile_source = kHistogramServerName; |
[email protected] | 9ed2f5c | 2014-06-13 14:55:24 | [diff] [blame] | 403 | } |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 404 | tile_sources_.push_back(tile_source); |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 405 | } |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 406 | |
| 407 | received_most_visited_sites_ = true; |
[email protected] | d497524 | 2014-06-02 18:16:20 | [diff] [blame] | 408 | mv_source_ = SUGGESTIONS_SERVICE; |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 409 | AddPopularSites(&titles, &urls); |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 410 | NotifyMostVisitedURLsObserver(titles, urls); |
| 411 | } |
[email protected] | d497524 | 2014-06-02 18:16:20 | [diff] [blame] | 412 | |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 413 | void MostVisitedSites::AddPopularSites(std::vector<base::string16>* titles, |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 414 | std::vector<std::string>* urls) { |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 415 | if (!popular_sites_) |
| 416 | return; |
| 417 | |
| 418 | DCHECK_EQ(titles->size(), urls->size()); |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 419 | DCHECK_EQ(titles->size(), tile_sources_.size()); |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 420 | DCHECK_LE(static_cast<int>(titles->size()), num_sites_); |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 421 | |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 422 | // Collect all non-blacklisted popular suggestions. |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 423 | std::vector<base::string16> popular_titles; |
| 424 | std::vector<std::string> popular_urls; |
treib | fac7519 | 2015-08-17 13:21:24 | [diff] [blame] | 425 | scoped_refptr<TopSites> top_sites(TopSitesFactory::GetForProfile(profile_)); |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 426 | for (const PopularSites::Site& popular_site : popular_sites_->sites()) { |
treib | fac7519 | 2015-08-17 13:21:24 | [diff] [blame] | 427 | // Skip blacklisted sites. |
| 428 | if (top_sites && top_sites->IsBlacklisted(popular_site.url)) |
| 429 | continue; |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 430 | |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 431 | popular_titles.push_back(popular_site.title); |
| 432 | popular_urls.push_back(popular_site.url.spec()); |
| 433 | if (static_cast<int>(popular_titles.size()) >= num_sites_) |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 434 | break; |
| 435 | } |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 436 | |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 437 | AddPopularSitesImpl( |
| 438 | num_sites_, popular_titles, popular_urls, titles, urls, &tile_sources_); |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 439 | } |
| 440 | |
| 441 | // static |
| 442 | void MostVisitedSites::AddPopularSitesImpl( |
| 443 | int num_sites, |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 444 | const std::vector<base::string16>& popular_titles, |
| 445 | const std::vector<std::string>& popular_urls, |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 446 | std::vector<base::string16>* titles, |
| 447 | std::vector<std::string>* urls, |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 448 | std::vector<std::string>* tile_sources) { |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 449 | // Start off with the popular suggestions. |
| 450 | std::vector<base::string16> new_titles(popular_titles); |
| 451 | std::vector<std::string> new_urls(popular_urls); |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 452 | std::vector<std::string> new_tile_sources(new_titles.size(), |
| 453 | kHistogramPopularName); |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 454 | |
| 455 | // Now, go over the personalized suggestions and replace matching popular |
| 456 | // suggestions. This is so that when some of the popular suggestions become |
| 457 | // personal, they retain their absolute positions. |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 458 | std::vector<base::string16> titles_to_insert; |
| 459 | std::vector<std::string> urls_to_insert; |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 460 | std::vector<std::string> tile_sources_to_insert; |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 461 | for (size_t site_index = 0; site_index < titles->size(); site_index++) { |
| 462 | const base::string16& title = (*titles)[site_index]; |
| 463 | const std::string& url = (*urls)[site_index]; |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 464 | const std::string& tile_source = (*tile_sources)[site_index]; |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 465 | // See if we already have a matching popular site. |
| 466 | bool found = false; |
| 467 | for (size_t i = 0; i < new_urls.size(); i++) { |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 468 | if (new_tile_sources[i] == kHistogramPopularName && |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 469 | GURL(new_urls[i]).host() == GURL(url).host()) { |
| 470 | // We have a matching popular sites suggestion. Replace it with the |
| 471 | // actual URL and title. |
| 472 | new_titles[i] = title; |
| 473 | new_urls[i] = url; |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 474 | new_tile_sources[i] = tile_source; |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 475 | found = true; |
| 476 | break; |
| 477 | } |
| 478 | } |
| 479 | if (!found) { |
| 480 | titles_to_insert.push_back(title); |
| 481 | urls_to_insert.push_back(url); |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 482 | tile_sources_to_insert.push_back(tile_source); |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 483 | } |
| 484 | } |
| 485 | |
| 486 | // Append personalized suggestions at the end if there's room. |
| 487 | size_t num_to_append = |
| 488 | std::min(static_cast<size_t>(num_sites) - new_titles.size(), |
| 489 | titles_to_insert.size()); |
| 490 | new_titles.insert(new_titles.end(), |
| 491 | titles_to_insert.end() - num_to_append, |
| 492 | titles_to_insert.end()); |
| 493 | new_urls.insert(new_urls.end(), |
| 494 | urls_to_insert.end() - num_to_append, |
| 495 | urls_to_insert.end()); |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 496 | new_tile_sources.insert(new_tile_sources.end(), |
| 497 | tile_sources_to_insert.end() - num_to_append, |
| 498 | tile_sources_to_insert.end()); |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 499 | |
| 500 | // Finally, go over the remaining personalized suggestions and evict popular |
| 501 | // suggestions to accommodate them. Do it in reverse order, so the least |
| 502 | // important popular suggestions will be evicted. |
| 503 | for (size_t i = titles_to_insert.size() - num_to_append; i > 0; --i) { |
| 504 | const base::string16& title = titles_to_insert[i - 1]; |
| 505 | const std::string& url = urls_to_insert[i - 1]; |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 506 | const std::string& tile_source = tile_sources_to_insert[i - 1]; |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 507 | for (size_t insert_i = new_titles.size(); insert_i > 0; --insert_i) { |
| 508 | size_t insert_index = insert_i - 1; |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 509 | if (new_tile_sources[insert_index] == kHistogramPopularName) { |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 510 | new_titles[insert_index] = title; |
| 511 | new_urls[insert_index] = url; |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 512 | new_tile_sources[insert_index] = tile_source; |
treib | cf674e6 | 2015-08-17 15:43:01 | [diff] [blame] | 513 | break; |
| 514 | } |
| 515 | } |
| 516 | } |
| 517 | |
| 518 | titles->swap(new_titles); |
| 519 | urls->swap(new_urls); |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 520 | tile_sources->swap(new_tile_sources); |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 521 | } |
| 522 | |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 523 | void MostVisitedSites::NotifyMostVisitedURLsObserver( |
| 524 | const std::vector<base::string16>& titles, |
| 525 | const std::vector<std::string>& urls) { |
| 526 | DCHECK_EQ(titles.size(), urls.size()); |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 527 | if (received_most_visited_sites_ && received_popular_sites_ && |
| 528 | !recorded_uma_) { |
| 529 | RecordImpressionUMAMetrics(); |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 530 | UMA_HISTOGRAM_SPARSE_SLOWLY(kNumTilesHistogramName, titles.size()); |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 531 | recorded_uma_ = true; |
| 532 | } |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 533 | JNIEnv* env = AttachCurrentThread(); |
| 534 | Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable( |
knn | 6cf777fc | 2015-05-06 13:21:48 | [diff] [blame] | 535 | env, observer_.obj(), ToJavaArrayOfStrings(env, titles).obj(), |
[email protected] | bc093e8 | 2014-03-04 21:49:11 | [diff] [blame] | 536 | ToJavaArrayOfStrings(env, urls).obj()); |
| 537 | } |
| 538 | |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 539 | void MostVisitedSites::OnPopularSitesAvailable(bool success) { |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 540 | received_popular_sites_ = true; |
| 541 | |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 542 | if (!success) { |
| 543 | LOG(WARNING) << "Download of popular sites failed"; |
| 544 | return; |
| 545 | } |
| 546 | |
treib | 7f5cf87 | 2015-08-11 13:11:47 | [diff] [blame] | 547 | if (observer_.is_null()) |
| 548 | return; |
| 549 | |
| 550 | std::vector<std::string> urls; |
| 551 | std::vector<std::string> favicon_urls; |
| 552 | for (const PopularSites::Site& popular_site : popular_sites_->sites()) { |
| 553 | urls.push_back(popular_site.url.spec()); |
| 554 | favicon_urls.push_back(popular_site.favicon_url.spec()); |
| 555 | } |
| 556 | JNIEnv* env = AttachCurrentThread(); |
| 557 | Java_MostVisitedURLsObserver_onPopularURLsAvailable( |
| 558 | env, observer_.obj(), ToJavaArrayOfStrings(env, urls).obj(), |
| 559 | ToJavaArrayOfStrings(env, favicon_urls).obj()); |
| 560 | |
| 561 | QueryMostVisitedURLs(); |
treib | cffa650 | 2015-08-06 09:12:27 | [diff] [blame] | 562 | } |
| 563 | |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 564 | void MostVisitedSites::RecordThumbnailUMAMetrics() { |
[email protected] | 32809e9e | 2014-06-19 01:10:58 | [diff] [blame] | 565 | UMA_HISTOGRAM_SPARSE_SLOWLY(kNumLocalThumbnailTilesHistogramName, |
| 566 | num_local_thumbs_); |
[email protected] | 1d778e1 | 2014-06-17 02:28:51 | [diff] [blame] | 567 | num_local_thumbs_ = 0; |
[email protected] | 32809e9e | 2014-06-19 01:10:58 | [diff] [blame] | 568 | UMA_HISTOGRAM_SPARSE_SLOWLY(kNumEmptyTilesHistogramName, num_empty_thumbs_); |
[email protected] | 1d778e1 | 2014-06-17 02:28:51 | [diff] [blame] | 569 | num_empty_thumbs_ = 0; |
[email protected] | 32809e9e | 2014-06-19 01:10:58 | [diff] [blame] | 570 | UMA_HISTOGRAM_SPARSE_SLOWLY(kNumServerTilesHistogramName, num_server_thumbs_); |
[email protected] | 1d778e1 | 2014-06-17 02:28:51 | [diff] [blame] | 571 | num_server_thumbs_ = 0; |
| 572 | } |
| 573 | |
treib | 783a337 | 2015-08-25 16:24:39 | [diff] [blame] | 574 | void MostVisitedSites::RecordImpressionUMAMetrics() { |
| 575 | for (size_t i = 0; i < tile_sources_.size(); i++) { |
| 576 | std::string histogram = base::StringPrintf(kImpressionHistogramFormat, |
| 577 | tile_sources_[i].c_str()); |
| 578 | LogHistogramEvent(histogram, static_cast<int>(i), num_sites_); |
| 579 | } |
| 580 | } |
| 581 | |
sdefresne | edf9e01f | 2015-01-13 19:45:41 | [diff] [blame] | 582 | void MostVisitedSites::TopSitesLoaded(history::TopSites* top_sites) { |
| 583 | } |
| 584 | |
fserb | db57511 | 2015-06-29 21:31:59 | [diff] [blame] | 585 | void MostVisitedSites::TopSitesChanged(history::TopSites* top_sites, |
| 586 | ChangeReason change_reason) { |
sdefresne | edf9e01f | 2015-01-13 19:45:41 | [diff] [blame] | 587 | if (mv_source_ == TOP_SITES) { |
| 588 | // The displayed suggestions are invalidated. |
| 589 | QueryMostVisitedURLs(); |
| 590 | } |
| 591 | } |
| 592 | |
torne | 89cc5d9 | 2015-09-04 11:16:35 | [diff] [blame] | 593 | static jlong Init(JNIEnv* env, |
| 594 | const JavaParamRef<jobject>& obj, |
| 595 | const JavaParamRef<jobject>& jprofile) { |
[email protected] | 7ceb4e3 | 2013-12-06 04:13:04 | [diff] [blame] | 596 | MostVisitedSites* most_visited_sites = |
| 597 | new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile)); |
| 598 | return reinterpret_cast<intptr_t>(most_visited_sites); |
| 599 | } |