| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 | 52 |
| 53 namespace { | 53 namespace { |
| 54 | 54 |
| 55 // Total number of tiles displayed. | 55 // Total number of tiles displayed. |
| 56 const char kNumTilesHistogramName[] = "NewTabPage.NumberOfTiles"; | 56 const char kNumTilesHistogramName[] = "NewTabPage.NumberOfTiles"; |
| 57 // Tracking thumbnails. | 57 // Tracking thumbnails. |
| 58 const char kNumLocalThumbnailTilesHistogramName[] = | 58 const char kNumLocalThumbnailTilesHistogramName[] = |
| 59 "NewTabPage.NumberOfThumbnailTiles"; | 59 "NewTabPage.NumberOfThumbnailTiles"; |
| 60 const char kNumEmptyTilesHistogramName[] = "NewTabPage.NumberOfGrayTiles"; | 60 const char kNumEmptyTilesHistogramName[] = "NewTabPage.NumberOfGrayTiles"; |
| 61 const char kNumServerTilesHistogramName[] = "NewTabPage.NumberOfExternalTiles"; | 61 const char kNumServerTilesHistogramName[] = "NewTabPage.NumberOfExternalTiles"; |
| 62 // Client suggestion opened. | 62 |
| 63 const char kOpenedItemClientHistogramName[] = "NewTabPage.MostVisited.client"; | 63 // Format for tile clicks histogram. |
| 64 // Server suggestion opened, no provider. | 64 const char kOpenedItemHistogramFormat[] = "NewTabPage.MostVisited.%s"; |
| 65 const char kOpenedItemServerHistogramName[] = "NewTabPage.MostVisited.server"; | 65 // Format for tile impressions histogram. |
| 66 // Server suggestion opened with provider. | 66 const char kImpressionHistogramFormat[] = "NewTabPage.SuggestionsImpression.%s"; |
| 67 const char kOpenedItemServerProviderHistogramFormat[] = | 67 // Identifiers for the various tile sources. |
| 68 "NewTabPage.MostVisited.server%d"; | 68 const char kHistogramClientName[] = "client"; |
| 69 // Client impression. | 69 const char kHistogramServerName[] = "server"; |
| 70 const char kImpressionClientHistogramName[] = | 70 const char kHistogramServerFormat[] = "server%d"; |
| 71 "NewTabPage.SuggestionsImpression.client"; | 71 const char kHistogramPopularName[] = "popular"; |
| 72 // Server suggestion impression, no provider. | |
| 73 const char kImpressionServerHistogramName[] = | |
| 74 "NewTabPage.SuggestionsImpression.server"; | |
| 75 // Server suggestion impression with provider. | |
| 76 const char kImpressionServerHistogramFormat[] = | |
| 77 "NewTabPage.SuggestionsImpression.server%d"; | |
| 78 | 72 |
| 79 const char kPopularSitesFieldTrialName[] = "NTPPopularSites"; | 73 const char kPopularSitesFieldTrialName[] = "NTPPopularSites"; |
| 80 | 74 |
| 81 scoped_ptr<SkBitmap> MaybeFetchLocalThumbnail( | 75 scoped_ptr<SkBitmap> MaybeFetchLocalThumbnail( |
| 82 const GURL& url, | 76 const GURL& url, |
| 83 const scoped_refptr<TopSites>& top_sites) { | 77 const scoped_refptr<TopSites>& top_sites) { |
| 84 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 78 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 85 scoped_refptr<base::RefCountedMemory> image; | 79 scoped_refptr<base::RefCountedMemory> image; |
| 86 scoped_ptr<SkBitmap> bitmap; | 80 scoped_ptr<SkBitmap> bitmap; |
| 87 if (top_sites && top_sites->GetPageThumbnail(url, false, &image)) | 81 if (top_sites && top_sites->GetPageThumbnail(url, false, &image)) |
| 88 bitmap.reset(gfx::JPEGCodec::Decode(image->front(), image->size())); | 82 bitmap.reset(gfx::JPEGCodec::Decode(image->front(), image->size())); |
| 89 return bitmap.Pass(); | 83 return bitmap.Pass(); |
| 90 } | 84 } |
| 91 | 85 |
| 92 // Log an event for a given |histogram| at a given element |position|. This | 86 // Log an event for a given |histogram| at a given element |position|. This |
| 93 // routine exists because regular histogram macros are cached thus can't be used | 87 // routine exists because regular histogram macros are cached thus can't be used |
| 94 // if the name of the histogram will change at a given call site. | 88 // if the name of the histogram will change at a given call site. |
| 95 void LogHistogramEvent(const std::string& histogram, int position, | 89 void LogHistogramEvent(const std::string& histogram, |
| 90 int position, |
| 96 int num_sites) { | 91 int num_sites) { |
| 97 base::HistogramBase* counter = base::LinearHistogram::FactoryGet( | 92 base::HistogramBase* counter = base::LinearHistogram::FactoryGet( |
| 98 histogram, | 93 histogram, |
| 99 1, | 94 1, |
| 100 num_sites, | 95 num_sites, |
| 101 num_sites + 1, | 96 num_sites + 1, |
| 102 base::Histogram::kUmaTargetedHistogramFlag); | 97 base::Histogram::kUmaTargetedHistogramFlag); |
| 103 if (counter) | 98 if (counter) |
| 104 counter->Add(position); | 99 counter->Add(position); |
| 105 } | 100 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 130 } | 125 } |
| 131 | 126 |
| 132 std::string GetPopularSitesFilename() { | 127 std::string GetPopularSitesFilename() { |
| 133 return variations::GetVariationParamValue(kPopularSitesFieldTrialName, | 128 return variations::GetVariationParamValue(kPopularSitesFieldTrialName, |
| 134 "filename"); | 129 "filename"); |
| 135 } | 130 } |
| 136 | 131 |
| 137 } // namespace | 132 } // namespace |
| 138 | 133 |
| 139 MostVisitedSites::MostVisitedSites(Profile* profile) | 134 MostVisitedSites::MostVisitedSites(Profile* profile) |
| 140 : profile_(profile), num_sites_(0), initial_load_done_(false), | 135 : profile_(profile), num_sites_(0), received_most_visited_sites_(false), |
| 136 received_popular_sites_(false), recorded_uma_(false), |
| 141 num_local_thumbs_(0), num_server_thumbs_(0), num_empty_thumbs_(0), | 137 num_local_thumbs_(0), num_server_thumbs_(0), num_empty_thumbs_(0), |
| 142 scoped_observer_(this), weak_ptr_factory_(this) { | 138 scoped_observer_(this), weak_ptr_factory_(this) { |
| 143 // Register the debugging page for the Suggestions Service and the thumbnails | 139 // Register the debugging page for the Suggestions Service and the thumbnails |
| 144 // debugging page. | 140 // debugging page. |
| 145 content::URLDataSource::Add(profile_, | 141 content::URLDataSource::Add(profile_, |
| 146 new suggestions::SuggestionsSource(profile_)); | 142 new suggestions::SuggestionsSource(profile_)); |
| 147 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); | 143 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); |
| 148 | 144 |
| 149 // Register this class as an observer to the sync service. It is important to | 145 // Register this class as an observer to the sync service. It is important to |
| 150 // be notified of changes in the sync state such as initialization, sync | 146 // be notified of changes in the sync state such as initialization, sync |
| 151 // being enabled or disabled, etc. | 147 // being enabled or disabled, etc. |
| 152 ProfileSyncService* profile_sync_service = | 148 ProfileSyncService* profile_sync_service = |
| 153 ProfileSyncServiceFactory::GetForProfile(profile_); | 149 ProfileSyncServiceFactory::GetForProfile(profile_); |
| 154 if (profile_sync_service) | 150 if (profile_sync_service) |
| 155 profile_sync_service->AddObserver(this); | 151 profile_sync_service->AddObserver(this); |
| 156 | 152 |
| 157 if (ShouldShowPopularSites()) { | 153 if (ShouldShowPopularSites()) { |
| 158 popular_sites_.reset(new PopularSites( | 154 popular_sites_.reset(new PopularSites( |
| 159 GetPopularSitesFilename(), | 155 GetPopularSitesFilename(), |
| 160 profile_->GetRequestContext(), | 156 profile_->GetRequestContext(), |
| 161 base::Bind(&MostVisitedSites::OnPopularSitesAvailable, | 157 base::Bind(&MostVisitedSites::OnPopularSitesAvailable, |
| 162 base::Unretained(this)))); | 158 base::Unretained(this)))); |
| 159 } else { |
| 160 received_popular_sites_ = true; |
| 163 } | 161 } |
| 164 } | 162 } |
| 165 | 163 |
| 166 MostVisitedSites::~MostVisitedSites() { | 164 MostVisitedSites::~MostVisitedSites() { |
| 167 ProfileSyncService* profile_sync_service = | 165 ProfileSyncService* profile_sync_service = |
| 168 ProfileSyncServiceFactory::GetForProfile(profile_); | 166 ProfileSyncServiceFactory::GetForProfile(profile_); |
| 169 if (profile_sync_service && profile_sync_service->HasObserver(this)) | 167 if (profile_sync_service && profile_sync_service->HasObserver(this)) |
| 170 profile_sync_service->RemoveObserver(this); | 168 profile_sync_service->RemoveObserver(this); |
| 171 } | 169 } |
| 172 | 170 |
| 173 void MostVisitedSites::Destroy(JNIEnv* env, jobject obj) { | 171 void MostVisitedSites::Destroy(JNIEnv* env, jobject obj) { |
| 174 delete this; | 172 delete this; |
| 175 } | 173 } |
| 176 | 174 |
| 177 void MostVisitedSites::OnLoadingComplete(JNIEnv* env, jobject obj) { | 175 void MostVisitedSites::OnLoadingComplete(JNIEnv* env, jobject obj) { |
| 178 RecordUMAMetrics(); | 176 RecordThumbnailUMAMetrics(); |
| 179 } | 177 } |
| 180 | 178 |
| 181 void MostVisitedSites::SetMostVisitedURLsObserver(JNIEnv* env, | 179 void MostVisitedSites::SetMostVisitedURLsObserver(JNIEnv* env, |
| 182 jobject obj, | 180 jobject obj, |
| 183 jobject j_observer, | 181 jobject j_observer, |
| 184 jint num_sites) { | 182 jint num_sites) { |
| 185 observer_.Reset(env, j_observer); | 183 observer_.Reset(env, j_observer); |
| 186 num_sites_ = num_sites; | 184 num_sites_ = num_sites; |
| 187 | 185 |
| 188 QueryMostVisitedURLs(); | 186 QueryMostVisitedURLs(); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 suggestions_service->BlacklistURL( | 283 suggestions_service->BlacklistURL( |
| 286 url, base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, | 284 url, base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, |
| 287 weak_ptr_factory_.GetWeakPtr()), | 285 weak_ptr_factory_.GetWeakPtr()), |
| 288 base::Closure()); | 286 base::Closure()); |
| 289 } | 287 } |
| 290 } | 288 } |
| 291 | 289 |
| 292 void MostVisitedSites::RecordOpenedMostVisitedItem(JNIEnv* env, | 290 void MostVisitedSites::RecordOpenedMostVisitedItem(JNIEnv* env, |
| 293 jobject obj, | 291 jobject obj, |
| 294 jint index) { | 292 jint index) { |
| 295 switch (mv_source_) { | 293 DCHECK_GE(index, 0); |
| 296 case TOP_SITES: { | 294 DCHECK_LT(index, static_cast<int>(tile_sources_.size())); |
| 297 UMA_HISTOGRAM_SPARSE_SLOWLY(kOpenedItemClientHistogramName, index); | 295 std::string histogram = base::StringPrintf(kOpenedItemHistogramFormat, |
| 298 break; | 296 tile_sources_[index].c_str()); |
| 299 } | 297 LogHistogramEvent(histogram, index, num_sites_); |
| 300 case SUGGESTIONS_SERVICE: { | |
| 301 if (server_suggestions_.suggestions_size() > index) { | |
| 302 if (server_suggestions_.suggestions(index).providers_size()) { | |
| 303 std::string histogram = base::StringPrintf( | |
| 304 kOpenedItemServerProviderHistogramFormat, | |
| 305 server_suggestions_.suggestions(index).providers(0)); | |
| 306 LogHistogramEvent(histogram, index, num_sites_); | |
| 307 } else { | |
| 308 UMA_HISTOGRAM_SPARSE_SLOWLY(kOpenedItemServerHistogramName, index); | |
| 309 } | |
| 310 } | |
| 311 break; | |
| 312 } | |
| 313 } | |
| 314 } | 298 } |
| 315 | 299 |
| 316 void MostVisitedSites::OnStateChanged() { | 300 void MostVisitedSites::OnStateChanged() { |
| 317 // There have been changes to the sync state. This class cares about a few | 301 // There have been changes to the sync state. This class cares about a few |
| 318 // (just initialized, enabled/disabled or history sync state changed). Re-run | 302 // (just initialized, enabled/disabled or history sync state changed). Re-run |
| 319 // the query code which will use the proper state. | 303 // the query code which will use the proper state. |
| 320 QueryMostVisitedURLs(); | 304 QueryMostVisitedURLs(); |
| 321 } | 305 } |
| 322 | 306 |
| 323 // static | 307 // static |
| (...skipping 23 matching lines...) Expand all Loading... |
| 347 top_sites->GetMostVisitedURLs( | 331 top_sites->GetMostVisitedURLs( |
| 348 base::Bind(&MostVisitedSites::OnMostVisitedURLsAvailable, | 332 base::Bind(&MostVisitedSites::OnMostVisitedURLsAvailable, |
| 349 weak_ptr_factory_.GetWeakPtr()), | 333 weak_ptr_factory_.GetWeakPtr()), |
| 350 false); | 334 false); |
| 351 } | 335 } |
| 352 | 336 |
| 353 void MostVisitedSites::OnMostVisitedURLsAvailable( | 337 void MostVisitedSites::OnMostVisitedURLsAvailable( |
| 354 const history::MostVisitedURLList& visited_list) { | 338 const history::MostVisitedURLList& visited_list) { |
| 355 std::vector<base::string16> titles; | 339 std::vector<base::string16> titles; |
| 356 std::vector<std::string> urls; | 340 std::vector<std::string> urls; |
| 341 tile_sources_.clear(); |
| 357 int num_tiles = std::min(static_cast<int>(visited_list.size()), num_sites_); | 342 int num_tiles = std::min(static_cast<int>(visited_list.size()), num_sites_); |
| 358 for (int i = 0; i < num_tiles; ++i) { | 343 for (int i = 0; i < num_tiles; ++i) { |
| 359 const history::MostVisitedURL& visited = visited_list[i]; | 344 const history::MostVisitedURL& visited = visited_list[i]; |
| 360 if (visited.url.is_empty()) { | 345 if (visited.url.is_empty()) { |
| 361 num_tiles = i; | 346 num_tiles = i; |
| 362 break; // This is the signal that there are no more real visited sites. | 347 break; // This is the signal that there are no more real visited sites. |
| 363 } | 348 } |
| 364 titles.push_back(visited.title); | 349 titles.push_back(visited.title); |
| 365 urls.push_back(visited.url.spec()); | 350 urls.push_back(visited.url.spec()); |
| 351 tile_sources_.push_back(kHistogramClientName); |
| 366 } | 352 } |
| 367 | 353 |
| 368 // Only log impression metrics on the initial load of the NTP. | 354 received_most_visited_sites_ = true; |
| 369 if (!initial_load_done_) { | |
| 370 for (int i = 0; i < num_tiles; ++i) { | |
| 371 UMA_HISTOGRAM_SPARSE_SLOWLY(kImpressionClientHistogramName, i); | |
| 372 } | |
| 373 } | |
| 374 mv_source_ = TOP_SITES; | 355 mv_source_ = TOP_SITES; |
| 375 AddPopularSites(&titles, &urls); | 356 AddPopularSites(&titles, &urls); |
| 376 NotifyMostVisitedURLsObserver(titles, urls); | 357 NotifyMostVisitedURLsObserver(titles, urls); |
| 377 } | 358 } |
| 378 | 359 |
| 379 void MostVisitedSites::OnSuggestionsProfileAvailable( | 360 void MostVisitedSites::OnSuggestionsProfileAvailable( |
| 380 const SuggestionsProfile& suggestions_profile) { | 361 const SuggestionsProfile& suggestions_profile) { |
| 381 int num_tiles = suggestions_profile.suggestions_size(); | 362 int num_tiles = suggestions_profile.suggestions_size(); |
| 382 // With no server suggestions, fall back to local Most Visited. | 363 // With no server suggestions, fall back to local Most Visited. |
| 383 if (num_tiles == 0) { | 364 if (num_tiles == 0) { |
| 384 InitiateTopSitesQuery(); | 365 InitiateTopSitesQuery(); |
| 385 return; | 366 return; |
| 386 } | 367 } |
| 387 if (num_sites_ < num_tiles) | 368 if (num_sites_ < num_tiles) |
| 388 num_tiles = num_sites_; | 369 num_tiles = num_sites_; |
| 389 | 370 |
| 390 std::vector<base::string16> titles; | 371 std::vector<base::string16> titles; |
| 391 std::vector<std::string> urls; | 372 std::vector<std::string> urls; |
| 373 tile_sources_.clear(); |
| 392 for (int i = 0; i < num_tiles; ++i) { | 374 for (int i = 0; i < num_tiles; ++i) { |
| 393 const ChromeSuggestion& suggestion = suggestions_profile.suggestions(i); | 375 const ChromeSuggestion& suggestion = suggestions_profile.suggestions(i); |
| 394 titles.push_back(base::UTF8ToUTF16(suggestion.title())); | 376 titles.push_back(base::UTF8ToUTF16(suggestion.title())); |
| 395 urls.push_back(suggestion.url()); | 377 urls.push_back(suggestion.url()); |
| 396 // Only log impression metrics on the initial NTP load. | 378 std::string tile_source; |
| 397 if (!initial_load_done_) { | 379 if (suggestion.providers_size() > 0) { |
| 398 if (suggestion.providers_size()) { | 380 tile_source = |
| 399 std::string histogram = base::StringPrintf( | 381 base::StringPrintf(kHistogramServerFormat, suggestion.providers(0)); |
| 400 kImpressionServerHistogramFormat, suggestion.providers(0)); | 382 } else { |
| 401 LogHistogramEvent(histogram, i, num_sites_); | 383 tile_source = kHistogramServerName; |
| 402 } else { | |
| 403 UMA_HISTOGRAM_SPARSE_SLOWLY(kImpressionServerHistogramName, i); | |
| 404 } | |
| 405 } | 384 } |
| 385 tile_sources_.push_back(tile_source); |
| 406 } | 386 } |
| 387 |
| 388 received_most_visited_sites_ = true; |
| 407 mv_source_ = SUGGESTIONS_SERVICE; | 389 mv_source_ = SUGGESTIONS_SERVICE; |
| 408 // Keep a copy of the suggestions for eventual logging. | |
| 409 server_suggestions_ = suggestions_profile; | |
| 410 AddPopularSites(&titles, &urls); | 390 AddPopularSites(&titles, &urls); |
| 411 NotifyMostVisitedURLsObserver(titles, urls); | 391 NotifyMostVisitedURLsObserver(titles, urls); |
| 412 } | 392 } |
| 413 | 393 |
| 414 void MostVisitedSites::AddPopularSites(std::vector<base::string16>* titles, | 394 void MostVisitedSites::AddPopularSites(std::vector<base::string16>* titles, |
| 415 std::vector<std::string>* urls) const { | 395 std::vector<std::string>* urls) { |
| 416 if (!popular_sites_) | 396 if (!popular_sites_) |
| 417 return; | 397 return; |
| 418 | 398 |
| 419 DCHECK_EQ(titles->size(), urls->size()); | 399 DCHECK_EQ(titles->size(), urls->size()); |
| 400 DCHECK_EQ(titles->size(), tile_sources_.size()); |
| 420 DCHECK_LE(static_cast<int>(titles->size()), num_sites_); | 401 DCHECK_LE(static_cast<int>(titles->size()), num_sites_); |
| 421 | 402 |
| 422 // Collect all non-blacklisted popular suggestions. | 403 // Collect all non-blacklisted popular suggestions. |
| 423 std::vector<base::string16> new_titles; | 404 std::vector<base::string16> popular_titles; |
| 424 std::vector<std::string> new_urls; | 405 std::vector<std::string> popular_urls; |
| 425 scoped_refptr<TopSites> top_sites(TopSitesFactory::GetForProfile(profile_)); | 406 scoped_refptr<TopSites> top_sites(TopSitesFactory::GetForProfile(profile_)); |
| 426 for (const PopularSites::Site& popular_site : popular_sites_->sites()) { | 407 for (const PopularSites::Site& popular_site : popular_sites_->sites()) { |
| 427 // Skip blacklisted sites. | 408 // Skip blacklisted sites. |
| 428 if (top_sites && top_sites->IsBlacklisted(popular_site.url)) | 409 if (top_sites && top_sites->IsBlacklisted(popular_site.url)) |
| 429 continue; | 410 continue; |
| 430 | 411 |
| 431 new_titles.push_back(popular_site.title); | 412 popular_titles.push_back(popular_site.title); |
| 432 new_urls.push_back(popular_site.url.spec()); | 413 popular_urls.push_back(popular_site.url.spec()); |
| 433 if (static_cast<int>(new_titles.size()) >= num_sites_) | 414 if (static_cast<int>(popular_titles.size()) >= num_sites_) |
| 434 break; | 415 break; |
| 435 } | 416 } |
| 436 | 417 |
| 437 AddPopularSitesImpl(num_sites_, titles, urls, new_titles, new_urls); | 418 AddPopularSitesImpl( |
| 419 num_sites_, popular_titles, popular_urls, titles, urls, &tile_sources_); |
| 438 } | 420 } |
| 439 | 421 |
| 440 // static | 422 // static |
| 441 void MostVisitedSites::AddPopularSitesImpl( | 423 void MostVisitedSites::AddPopularSitesImpl( |
| 442 int num_sites, | 424 int num_sites, |
| 425 const std::vector<base::string16>& popular_titles, |
| 426 const std::vector<std::string>& popular_urls, |
| 443 std::vector<base::string16>* titles, | 427 std::vector<base::string16>* titles, |
| 444 std::vector<std::string>* urls, | 428 std::vector<std::string>* urls, |
| 445 const std::vector<base::string16>& popular_titles, | 429 std::vector<std::string>* tile_sources) { |
| 446 const std::vector<std::string>& popular_urls) { | |
| 447 // Start off with the popular suggestions. | 430 // Start off with the popular suggestions. |
| 448 std::vector<base::string16> new_titles(popular_titles); | 431 std::vector<base::string16> new_titles(popular_titles); |
| 449 std::vector<std::string> new_urls(popular_urls); | 432 std::vector<std::string> new_urls(popular_urls); |
| 433 std::vector<std::string> new_tile_sources(new_titles.size(), |
| 434 kHistogramPopularName); |
| 450 | 435 |
| 451 // Now, go over the personalized suggestions and replace matching popular | 436 // Now, go over the personalized suggestions and replace matching popular |
| 452 // suggestions. This is so that when some of the popular suggestions become | 437 // suggestions. This is so that when some of the popular suggestions become |
| 453 // personal, they retain their absolute positions. | 438 // personal, they retain their absolute positions. |
| 454 std::vector<bool> new_is_personalized(new_titles.size(), false); | |
| 455 std::vector<base::string16> titles_to_insert; | 439 std::vector<base::string16> titles_to_insert; |
| 456 std::vector<std::string> urls_to_insert; | 440 std::vector<std::string> urls_to_insert; |
| 441 std::vector<std::string> tile_sources_to_insert; |
| 457 for (size_t site_index = 0; site_index < titles->size(); site_index++) { | 442 for (size_t site_index = 0; site_index < titles->size(); site_index++) { |
| 458 const base::string16& title = (*titles)[site_index]; | 443 const base::string16& title = (*titles)[site_index]; |
| 459 const std::string& url = (*urls)[site_index]; | 444 const std::string& url = (*urls)[site_index]; |
| 445 const std::string& tile_source = (*tile_sources)[site_index]; |
| 460 // See if we already have a matching popular site. | 446 // See if we already have a matching popular site. |
| 461 bool found = false; | 447 bool found = false; |
| 462 for (size_t i = 0; i < new_urls.size(); i++) { | 448 for (size_t i = 0; i < new_urls.size(); i++) { |
| 463 if (!new_is_personalized[i] && | 449 if (new_tile_sources[i] == kHistogramPopularName && |
| 464 GURL(new_urls[i]).host() == GURL(url).host()) { | 450 GURL(new_urls[i]).host() == GURL(url).host()) { |
| 465 // We have a matching popular sites suggestion. Replace it with the | 451 // We have a matching popular sites suggestion. Replace it with the |
| 466 // actual URL and title. | 452 // actual URL and title. |
| 467 new_titles[i] = title; | 453 new_titles[i] = title; |
| 468 new_urls[i] = url; | 454 new_urls[i] = url; |
| 469 new_is_personalized[i] = true; | 455 new_tile_sources[i] = tile_source; |
| 470 found = true; | 456 found = true; |
| 471 break; | 457 break; |
| 472 } | 458 } |
| 473 } | 459 } |
| 474 if (!found) { | 460 if (!found) { |
| 475 titles_to_insert.push_back(title); | 461 titles_to_insert.push_back(title); |
| 476 urls_to_insert.push_back(url); | 462 urls_to_insert.push_back(url); |
| 463 tile_sources_to_insert.push_back(tile_source); |
| 477 } | 464 } |
| 478 } | 465 } |
| 479 | 466 |
| 480 // Append personalized suggestions at the end if there's room. | 467 // Append personalized suggestions at the end if there's room. |
| 481 size_t num_to_append = | 468 size_t num_to_append = |
| 482 std::min(static_cast<size_t>(num_sites) - new_titles.size(), | 469 std::min(static_cast<size_t>(num_sites) - new_titles.size(), |
| 483 titles_to_insert.size()); | 470 titles_to_insert.size()); |
| 484 new_titles.insert(new_titles.end(), | 471 new_titles.insert(new_titles.end(), |
| 485 titles_to_insert.end() - num_to_append, | 472 titles_to_insert.end() - num_to_append, |
| 486 titles_to_insert.end()); | 473 titles_to_insert.end()); |
| 487 new_urls.insert(new_urls.end(), | 474 new_urls.insert(new_urls.end(), |
| 488 urls_to_insert.end() - num_to_append, | 475 urls_to_insert.end() - num_to_append, |
| 489 urls_to_insert.end()); | 476 urls_to_insert.end()); |
| 490 new_is_personalized.insert(new_is_personalized.end(), num_to_append, true); | 477 new_tile_sources.insert(new_tile_sources.end(), |
| 478 tile_sources_to_insert.end() - num_to_append, |
| 479 tile_sources_to_insert.end()); |
| 491 | 480 |
| 492 // Finally, go over the remaining personalized suggestions and evict popular | 481 // Finally, go over the remaining personalized suggestions and evict popular |
| 493 // suggestions to accommodate them. Do it in reverse order, so the least | 482 // suggestions to accommodate them. Do it in reverse order, so the least |
| 494 // important popular suggestions will be evicted. | 483 // important popular suggestions will be evicted. |
| 495 for (size_t i = titles_to_insert.size() - num_to_append; i > 0; --i) { | 484 for (size_t i = titles_to_insert.size() - num_to_append; i > 0; --i) { |
| 496 const base::string16& title = titles_to_insert[i - 1]; | 485 const base::string16& title = titles_to_insert[i - 1]; |
| 497 const std::string& url = urls_to_insert[i - 1]; | 486 const std::string& url = urls_to_insert[i - 1]; |
| 487 const std::string& tile_source = tile_sources_to_insert[i - 1]; |
| 498 for (size_t insert_i = new_titles.size(); insert_i > 0; --insert_i) { | 488 for (size_t insert_i = new_titles.size(); insert_i > 0; --insert_i) { |
| 499 size_t insert_index = insert_i - 1; | 489 size_t insert_index = insert_i - 1; |
| 500 if (!new_is_personalized[insert_index]) { | 490 if (new_tile_sources[insert_index] == kHistogramPopularName) { |
| 501 new_titles[insert_index] = title; | 491 new_titles[insert_index] = title; |
| 502 new_urls[insert_index] = url; | 492 new_urls[insert_index] = url; |
| 503 new_is_personalized[insert_index] = true; | 493 new_tile_sources[insert_index] = tile_source; |
| 504 break; | 494 break; |
| 505 } | 495 } |
| 506 } | 496 } |
| 507 } | 497 } |
| 508 | 498 |
| 509 titles->swap(new_titles); | 499 titles->swap(new_titles); |
| 510 urls->swap(new_urls); | 500 urls->swap(new_urls); |
| 501 tile_sources->swap(new_tile_sources); |
| 511 } | 502 } |
| 512 | 503 |
| 513 void MostVisitedSites::NotifyMostVisitedURLsObserver( | 504 void MostVisitedSites::NotifyMostVisitedURLsObserver( |
| 514 const std::vector<base::string16>& titles, | 505 const std::vector<base::string16>& titles, |
| 515 const std::vector<std::string>& urls) { | 506 const std::vector<std::string>& urls) { |
| 516 DCHECK_EQ(titles.size(), urls.size()); | 507 DCHECK_EQ(titles.size(), urls.size()); |
| 517 if (!initial_load_done_) | 508 if (received_most_visited_sites_ && received_popular_sites_ && |
| 509 !recorded_uma_) { |
| 510 RecordImpressionUMAMetrics(); |
| 518 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumTilesHistogramName, titles.size()); | 511 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumTilesHistogramName, titles.size()); |
| 519 initial_load_done_ = true; | 512 recorded_uma_ = true; |
| 513 } |
| 520 JNIEnv* env = AttachCurrentThread(); | 514 JNIEnv* env = AttachCurrentThread(); |
| 521 Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable( | 515 Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable( |
| 522 env, observer_.obj(), ToJavaArrayOfStrings(env, titles).obj(), | 516 env, observer_.obj(), ToJavaArrayOfStrings(env, titles).obj(), |
| 523 ToJavaArrayOfStrings(env, urls).obj()); | 517 ToJavaArrayOfStrings(env, urls).obj()); |
| 524 } | 518 } |
| 525 | 519 |
| 526 void MostVisitedSites::OnPopularSitesAvailable(bool success) { | 520 void MostVisitedSites::OnPopularSitesAvailable(bool success) { |
| 521 received_popular_sites_ = true; |
| 522 |
| 527 if (!success) { | 523 if (!success) { |
| 528 LOG(WARNING) << "Download of popular sites failed"; | 524 LOG(WARNING) << "Download of popular sites failed"; |
| 529 return; | 525 return; |
| 530 } | 526 } |
| 531 | 527 |
| 532 if (observer_.is_null()) | 528 if (observer_.is_null()) |
| 533 return; | 529 return; |
| 534 | 530 |
| 535 std::vector<std::string> urls; | 531 std::vector<std::string> urls; |
| 536 std::vector<std::string> favicon_urls; | 532 std::vector<std::string> favicon_urls; |
| 537 for (const PopularSites::Site& popular_site : popular_sites_->sites()) { | 533 for (const PopularSites::Site& popular_site : popular_sites_->sites()) { |
| 538 urls.push_back(popular_site.url.spec()); | 534 urls.push_back(popular_site.url.spec()); |
| 539 favicon_urls.push_back(popular_site.favicon_url.spec()); | 535 favicon_urls.push_back(popular_site.favicon_url.spec()); |
| 540 } | 536 } |
| 541 JNIEnv* env = AttachCurrentThread(); | 537 JNIEnv* env = AttachCurrentThread(); |
| 542 Java_MostVisitedURLsObserver_onPopularURLsAvailable( | 538 Java_MostVisitedURLsObserver_onPopularURLsAvailable( |
| 543 env, observer_.obj(), ToJavaArrayOfStrings(env, urls).obj(), | 539 env, observer_.obj(), ToJavaArrayOfStrings(env, urls).obj(), |
| 544 ToJavaArrayOfStrings(env, favicon_urls).obj()); | 540 ToJavaArrayOfStrings(env, favicon_urls).obj()); |
| 545 | 541 |
| 546 QueryMostVisitedURLs(); | 542 QueryMostVisitedURLs(); |
| 547 } | 543 } |
| 548 | 544 |
| 549 void MostVisitedSites::RecordUMAMetrics() { | 545 void MostVisitedSites::RecordThumbnailUMAMetrics() { |
| 550 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumLocalThumbnailTilesHistogramName, | 546 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumLocalThumbnailTilesHistogramName, |
| 551 num_local_thumbs_); | 547 num_local_thumbs_); |
| 552 num_local_thumbs_ = 0; | 548 num_local_thumbs_ = 0; |
| 553 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumEmptyTilesHistogramName, num_empty_thumbs_); | 549 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumEmptyTilesHistogramName, num_empty_thumbs_); |
| 554 num_empty_thumbs_ = 0; | 550 num_empty_thumbs_ = 0; |
| 555 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumServerTilesHistogramName, num_server_thumbs_); | 551 UMA_HISTOGRAM_SPARSE_SLOWLY(kNumServerTilesHistogramName, num_server_thumbs_); |
| 556 num_server_thumbs_ = 0; | 552 num_server_thumbs_ = 0; |
| 557 } | 553 } |
| 558 | 554 |
| 555 void MostVisitedSites::RecordImpressionUMAMetrics() { |
| 556 for (size_t i = 0; i < tile_sources_.size(); i++) { |
| 557 std::string histogram = base::StringPrintf(kImpressionHistogramFormat, |
| 558 tile_sources_[i].c_str()); |
| 559 LogHistogramEvent(histogram, static_cast<int>(i), num_sites_); |
| 560 } |
| 561 } |
| 562 |
| 559 void MostVisitedSites::TopSitesLoaded(history::TopSites* top_sites) { | 563 void MostVisitedSites::TopSitesLoaded(history::TopSites* top_sites) { |
| 560 } | 564 } |
| 561 | 565 |
| 562 void MostVisitedSites::TopSitesChanged(history::TopSites* top_sites, | 566 void MostVisitedSites::TopSitesChanged(history::TopSites* top_sites, |
| 563 ChangeReason change_reason) { | 567 ChangeReason change_reason) { |
| 564 if (mv_source_ == TOP_SITES) { | 568 if (mv_source_ == TOP_SITES) { |
| 565 // The displayed suggestions are invalidated. | 569 // The displayed suggestions are invalidated. |
| 566 QueryMostVisitedURLs(); | 570 QueryMostVisitedURLs(); |
| 567 } | 571 } |
| 568 } | 572 } |
| 569 | 573 |
| 570 static jlong Init(JNIEnv* env, jobject obj, jobject jprofile) { | 574 static jlong Init(JNIEnv* env, jobject obj, jobject jprofile) { |
| 571 MostVisitedSites* most_visited_sites = | 575 MostVisitedSites* most_visited_sites = |
| 572 new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile)); | 576 new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile)); |
| 573 return reinterpret_cast<intptr_t>(most_visited_sites); | 577 return reinterpret_cast<intptr_t>(most_visited_sites); |
| 574 } | 578 } |
| OLD | NEW |