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/ntp/most_visited_sites.h" | 5 #include "chrome/browser/android/ntp/most_visited_sites.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 | 175 |
| 176 MostVisitedSites::Suggestion::Suggestion(Suggestion&&) = default; | 176 MostVisitedSites::Suggestion::Suggestion(Suggestion&&) = default; |
| 177 MostVisitedSites::Suggestion& | 177 MostVisitedSites::Suggestion& |
| 178 MostVisitedSites::Suggestion::operator=(Suggestion&&) = default; | 178 MostVisitedSites::Suggestion::operator=(Suggestion&&) = default; |
| 179 | 179 |
| 180 MostVisitedSites::MostVisitedSites(Profile* profile) | 180 MostVisitedSites::MostVisitedSites(Profile* profile) |
| 181 : profile_(profile), top_sites_(TopSitesFactory::GetForProfile(profile)), | 181 : profile_(profile), top_sites_(TopSitesFactory::GetForProfile(profile)), |
| 182 suggestions_service_(SuggestionsServiceFactory::GetForProfile(profile_)), | 182 suggestions_service_(SuggestionsServiceFactory::GetForProfile(profile_)), |
| 183 observer_(nullptr), num_sites_(0), | 183 observer_(nullptr), num_sites_(0), |
| 184 received_most_visited_sites_(false), received_popular_sites_(false), | 184 received_most_visited_sites_(false), received_popular_sites_(false), |
| 185 recorded_uma_(false), scoped_observer_(this), weak_ptr_factory_(this) { | 185 recorded_uma_(false), scoped_observer_(this), |
| 186 mv_source_(SUGGESTIONS_SERVICE), weak_ptr_factory_(this) { | |
|
Marc Treib
2016/04/29 13:58:33
Unrelated, but this used to be uninitialized. Opti
| |
| 186 // Register the thumbnails debugging page. | 187 // Register the thumbnails debugging page. |
| 187 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); | 188 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); |
| 188 | 189 |
| 189 SupervisedUserService* supervised_user_service = | 190 SupervisedUserService* supervised_user_service = |
| 190 SupervisedUserServiceFactory::GetForProfile(profile_); | 191 SupervisedUserServiceFactory::GetForProfile(profile_); |
| 191 supervised_user_service->AddObserver(this); | 192 supervised_user_service->AddObserver(this); |
| 192 } | 193 } |
| 193 | 194 |
| 194 MostVisitedSites::~MostVisitedSites() { | 195 MostVisitedSites::~MostVisitedSites() { |
| 195 SupervisedUserService* supervised_user_service = | 196 SupervisedUserService* supervised_user_service = |
| 196 SupervisedUserServiceFactory::GetForProfile(profile_); | 197 SupervisedUserServiceFactory::GetForProfile(profile_); |
| 197 supervised_user_service->RemoveObserver(this); | 198 supervised_user_service->RemoveObserver(this); |
| 198 } | 199 } |
| 199 | 200 |
| 200 void MostVisitedSites::SetMostVisitedURLsObserver( | 201 void MostVisitedSites::SetMostVisitedURLsObserver( |
| 201 MostVisitedSites::Observer* observer, int num_sites) { | 202 MostVisitedSites::Observer* observer, int num_sites) { |
| 203 DCHECK(observer); | |
| 202 observer_ = observer; | 204 observer_ = observer; |
| 203 num_sites_ = num_sites; | 205 num_sites_ = num_sites; |
| 204 | 206 |
| 205 if (ShouldShowPopularSites() && | 207 if (ShouldShowPopularSites() && |
| 206 NeedPopularSites(profile_->GetPrefs(), num_sites_)) { | 208 NeedPopularSites(profile_->GetPrefs(), num_sites_)) { |
| 207 popular_sites_.reset(new PopularSites( | 209 popular_sites_.reset(new PopularSites( |
| 208 profile_->GetPrefs(), | 210 profile_->GetPrefs(), |
| 209 TemplateURLServiceFactory::GetForProfile(profile_), | 211 TemplateURLServiceFactory::GetForProfile(profile_), |
| 210 profile_->GetRequestContext(), | 212 profile_->GetRequestContext(), |
| 211 GetPopularSitesCountry(), | 213 GetPopularSitesCountry(), |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 224 | 226 |
| 225 // Register as TopSitesObserver so that we can update ourselves when the | 227 // Register as TopSitesObserver so that we can update ourselves when the |
| 226 // TopSites changes. | 228 // TopSites changes. |
| 227 scoped_observer_.Add(top_sites_.get()); | 229 scoped_observer_.Add(top_sites_.get()); |
| 228 } | 230 } |
| 229 | 231 |
| 230 suggestions_subscription_ = suggestions_service_->AddCallback( | 232 suggestions_subscription_ = suggestions_service_->AddCallback( |
| 231 base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, | 233 base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, |
| 232 base::Unretained(this))); | 234 base::Unretained(this))); |
| 233 | 235 |
| 234 // Immediately get the current suggestions from the cache. If the cache is | 236 // Immediately build the current suggestions, getting personal suggestions |
| 235 // empty, this will fall back to TopSites. | 237 // from the SuggestionsService's cache or, if that is empty, from TopSites. |
| 236 OnSuggestionsProfileAvailable( | 238 BuildCurrentSuggestions(); |
| 237 suggestions_service_->GetSuggestionsDataFromCache()); | |
| 238 // Also start a request for fresh suggestions. | 239 // Also start a request for fresh suggestions. |
| 239 suggestions_service_->FetchSuggestionsData(); | 240 suggestions_service_->FetchSuggestionsData(); |
| 240 } | 241 } |
| 241 | 242 |
| 242 void MostVisitedSites::GetURLThumbnail( | 243 void MostVisitedSites::GetURLThumbnail( |
| 243 const GURL& url, | 244 const GURL& url, |
| 244 const ThumbnailCallback& callback) { | 245 const ThumbnailCallback& callback) { |
| 245 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 246 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 246 | 247 |
| 247 BrowserThread::PostTaskAndReplyWithResult( | 248 BrowserThread::PostTaskAndReplyWithResult( |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 GetSourceHistogramName(current_suggestions_[index]).c_str()); | 342 GetSourceHistogramName(current_suggestions_[index]).c_str()); |
| 342 LogHistogramEvent(histogram, index, num_sites_); | 343 LogHistogramEvent(histogram, index, num_sites_); |
| 343 | 344 |
| 344 histogram = base::StringPrintf( | 345 histogram = base::StringPrintf( |
| 345 "NewTabPage.TileTypeClicked.%s", | 346 "NewTabPage.TileTypeClicked.%s", |
| 346 GetSourceHistogramName(current_suggestions_[index]).c_str()); | 347 GetSourceHistogramName(current_suggestions_[index]).c_str()); |
| 347 LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES); | 348 LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES); |
| 348 } | 349 } |
| 349 | 350 |
| 350 void MostVisitedSites::OnURLFilterChanged() { | 351 void MostVisitedSites::OnURLFilterChanged() { |
| 351 QueryMostVisitedURLs(); | 352 BuildCurrentSuggestions(); |
| 352 } | 353 } |
| 353 | 354 |
| 354 // static | 355 // static |
| 355 void MostVisitedSites::RegisterProfilePrefs( | 356 void MostVisitedSites::RegisterProfilePrefs( |
| 356 user_prefs::PrefRegistrySyncable* registry) { | 357 user_prefs::PrefRegistrySyncable* registry) { |
| 357 registry->RegisterListPref(ntp_tiles::prefs::kNTPSuggestionsURL); | 358 registry->RegisterListPref(ntp_tiles::prefs::kNTPSuggestionsURL); |
| 358 registry->RegisterListPref(ntp_tiles::prefs::kNTPSuggestionsIsPersonal); | 359 registry->RegisterListPref(ntp_tiles::prefs::kNTPSuggestionsIsPersonal); |
| 359 } | 360 } |
| 360 | 361 |
| 361 void MostVisitedSites::QueryMostVisitedURLs() { | 362 void MostVisitedSites::BuildCurrentSuggestions() { |
| 362 if (suggestions_service_->FetchSuggestionsData()) { | 363 // Get the current suggestions from cache. If the cache is empty, this will |
| 363 // A suggestions network request is on its way. We'll be called back via | 364 // fall back to TopSites. |
| 364 // OnSuggestionsProfileAvailable. | |
| 365 return; | |
|
Marc Treib
2016/04/29 13:58:33
This was the actual problem - we'd wait on the net
| |
| 366 } | |
| 367 // If no network request could be sent, try to get suggestions from the | |
| 368 // cache. If that also returns nothing, OnSuggestionsProfileAvailable will | |
| 369 // call InitiateTopSitesQuery. | |
| 370 OnSuggestionsProfileAvailable( | 365 OnSuggestionsProfileAvailable( |
| 371 suggestions_service_->GetSuggestionsDataFromCache()); | 366 suggestions_service_->GetSuggestionsDataFromCache()); |
| 372 } | 367 } |
| 373 | 368 |
| 374 void MostVisitedSites::InitiateTopSitesQuery() { | 369 void MostVisitedSites::InitiateTopSitesQuery() { |
| 375 if (!top_sites_) | 370 if (!top_sites_) |
| 376 return; | 371 return; |
| 377 | 372 |
| 378 top_sites_->GetMostVisitedURLs( | 373 top_sites_->GetMostVisitedURLs( |
| 379 base::Bind(&MostVisitedSites::OnMostVisitedURLsAvailable, | 374 base::Bind(&MostVisitedSites::OnMostVisitedURLsAvailable, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 | 418 |
| 424 received_most_visited_sites_ = true; | 419 received_most_visited_sites_ = true; |
| 425 mv_source_ = TOP_SITES; | 420 mv_source_ = TOP_SITES; |
| 426 SaveNewNTPSuggestions(&suggestions); | 421 SaveNewNTPSuggestions(&suggestions); |
| 427 NotifyMostVisitedURLsObserver(); | 422 NotifyMostVisitedURLsObserver(); |
| 428 } | 423 } |
| 429 | 424 |
| 430 void MostVisitedSites::OnSuggestionsProfileAvailable( | 425 void MostVisitedSites::OnSuggestionsProfileAvailable( |
| 431 const SuggestionsProfile& suggestions_profile) { | 426 const SuggestionsProfile& suggestions_profile) { |
| 432 int num_tiles = suggestions_profile.suggestions_size(); | 427 int num_tiles = suggestions_profile.suggestions_size(); |
| 433 // With no server suggestions, fall back to local Most Visited. | 428 // With no server suggestions, fall back to local TopSites. |
| 434 if (num_tiles == 0) { | 429 if (num_tiles == 0) { |
| 435 InitiateTopSitesQuery(); | 430 InitiateTopSitesQuery(); |
| 436 return; | 431 return; |
| 437 } | 432 } |
| 438 if (num_sites_ < num_tiles) | 433 if (num_sites_ < num_tiles) |
| 439 num_tiles = num_sites_; | 434 num_tiles = num_sites_; |
| 440 | 435 |
| 441 SupervisedUserURLFilter* url_filter = | 436 SupervisedUserURLFilter* url_filter = |
| 442 SupervisedUserServiceFactory::GetForProfile(profile_) | 437 SupervisedUserServiceFactory::GetForProfile(profile_) |
| 443 ->GetURLFilterForUIThread(); | 438 ->GetURLFilterForUIThread(); |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 723 size_t num_dests = dst_suggestions->size(); | 718 size_t num_dests = dst_suggestions->size(); |
| 724 | 719 |
| 725 size_t src_pos = 0; | 720 size_t src_pos = 0; |
| 726 size_t i = start_position; | 721 size_t i = start_position; |
| 727 for (; i < num_dests && src_pos < num_inserts; ++i) { | 722 for (; i < num_dests && src_pos < num_inserts; ++i) { |
| 728 if ((*dst_suggestions)[i] != nullptr) | 723 if ((*dst_suggestions)[i] != nullptr) |
| 729 continue; | 724 continue; |
| 730 size_t src = insert_positions[src_pos++]; | 725 size_t src = insert_positions[src_pos++]; |
| 731 std::swap((*dst_suggestions)[i], (*src_suggestions)[src]); | 726 std::swap((*dst_suggestions)[i], (*src_suggestions)[src]); |
| 732 } | 727 } |
| 733 // Return destination postions filled so far which becomes the start_position | 728 // Return destination positions filled so far which becomes the start_position |
| 734 // for future runs. | 729 // for future runs. |
| 735 return i; | 730 return i; |
| 736 } | 731 } |
| 737 | 732 |
| 738 void MostVisitedSites::NotifyMostVisitedURLsObserver() { | 733 void MostVisitedSites::NotifyMostVisitedURLsObserver() { |
| 739 size_t num_suggestions = current_suggestions_.size(); | 734 size_t num_suggestions = current_suggestions_.size(); |
| 740 if (received_most_visited_sites_ && received_popular_sites_ && | 735 if (received_most_visited_sites_ && received_popular_sites_ && |
| 741 !recorded_uma_) { | 736 !recorded_uma_) { |
| 742 RecordImpressionUMAMetrics(); | 737 RecordImpressionUMAMetrics(); |
| 743 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfTiles", num_suggestions); | 738 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfTiles", num_suggestions); |
| 744 recorded_uma_ = true; | 739 recorded_uma_ = true; |
| 745 } | 740 } |
| 746 | 741 |
| 747 if (!observer_) | 742 if (!observer_) |
| 748 return; | 743 return; |
| 749 | 744 |
| 750 observer_->OnMostVisitedURLsAvailable(current_suggestions_); | 745 observer_->OnMostVisitedURLsAvailable(current_suggestions_); |
| 751 } | 746 } |
| 752 | 747 |
| 753 void MostVisitedSites::OnPopularSitesAvailable(bool success) { | 748 void MostVisitedSites::OnPopularSitesAvailable(bool success) { |
| 754 received_popular_sites_ = true; | 749 received_popular_sites_ = true; |
| 755 | 750 |
| 756 if (!success) { | 751 if (!success) { |
| 757 LOG(WARNING) << "Download of popular sites failed"; | 752 LOG(WARNING) << "Download of popular sites failed"; |
| 758 return; | 753 return; |
| 759 } | 754 } |
| 760 | 755 |
| 761 if (!observer_) | 756 // Pass the popular sites to the observer. This will cause it to fetch any |
|
Marc Treib
2016/04/29 13:58:33
|observer_| can't be null here, since we only requ
| |
| 762 return; | 757 // missing icons, but will *not* cause it to display the popular sites. |
| 758 observer_->OnPopularURLsAvailable(popular_sites_->sites()); | |
| 763 | 759 |
| 764 observer_->OnPopularURLsAvailable(popular_sites_->sites()); | 760 // Re-build the suggestions list. Once done, this will notify the observer. |
| 765 QueryMostVisitedURLs(); | 761 BuildCurrentSuggestions(); |
| 766 } | 762 } |
| 767 | 763 |
| 768 void MostVisitedSites::RecordImpressionUMAMetrics() { | 764 void MostVisitedSites::RecordImpressionUMAMetrics() { |
| 769 for (size_t i = 0; i < current_suggestions_.size(); i++) { | 765 for (size_t i = 0; i < current_suggestions_.size(); i++) { |
| 770 std::string histogram = base::StringPrintf( | 766 std::string histogram = base::StringPrintf( |
| 771 "NewTabPage.SuggestionsImpression.%s", | 767 "NewTabPage.SuggestionsImpression.%s", |
| 772 GetSourceHistogramName(current_suggestions_[i]).c_str()); | 768 GetSourceHistogramName(current_suggestions_[i]).c_str()); |
| 773 LogHistogramEvent(histogram, static_cast<int>(i), num_sites_); | 769 LogHistogramEvent(histogram, static_cast<int>(i), num_sites_); |
| 774 } | 770 } |
| 775 } | 771 } |
| 776 | 772 |
| 777 void MostVisitedSites::TopSitesLoaded(TopSites* top_sites) {} | 773 void MostVisitedSites::TopSitesLoaded(TopSites* top_sites) {} |
| 778 | 774 |
| 779 void MostVisitedSites::TopSitesChanged(TopSites* top_sites, | 775 void MostVisitedSites::TopSitesChanged(TopSites* top_sites, |
| 780 ChangeReason change_reason) { | 776 ChangeReason change_reason) { |
| 781 if (mv_source_ == TOP_SITES) { | 777 if (mv_source_ == TOP_SITES) { |
| 782 // The displayed suggestions are invalidated. | 778 // The displayed suggestions are invalidated. |
| 783 InitiateTopSitesQuery(); | 779 InitiateTopSitesQuery(); |
| 784 } | 780 } |
| 785 } | 781 } |
| OLD | NEW |