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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 SupervisedUserServiceFactory::GetForProfile(profile_); | 193 SupervisedUserServiceFactory::GetForProfile(profile_); |
| 194 supervised_user_service->AddObserver(this); | 194 supervised_user_service->AddObserver(this); |
| 195 } | 195 } |
| 196 | 196 |
| 197 MostVisitedSites::~MostVisitedSites() { | 197 MostVisitedSites::~MostVisitedSites() { |
| 198 SupervisedUserService* supervised_user_service = | 198 SupervisedUserService* supervised_user_service = |
| 199 SupervisedUserServiceFactory::GetForProfile(profile_); | 199 SupervisedUserServiceFactory::GetForProfile(profile_); |
| 200 supervised_user_service->RemoveObserver(this); | 200 supervised_user_service->RemoveObserver(this); |
| 201 } | 201 } |
| 202 | 202 |
| 203 void MostVisitedSites::SetMostVisitedURLsObserver( | 203 void MostVisitedSites::SetMostVisitedURLsObserver(Observer* observer, |
| 204 MostVisitedSites::Observer* observer, int num_sites) { | 204 int num_sites) { |
| 205 DCHECK(observer); | 205 DCHECK(observer); |
| 206 observer_ = observer; | 206 observer_ = observer; |
| 207 num_sites_ = num_sites; | 207 num_sites_ = num_sites; |
| 208 | 208 |
| 209 if (ShouldShowPopularSites() && | 209 if (ShouldShowPopularSites() && |
| 210 NeedPopularSites(prefs_, num_sites_)) { | 210 NeedPopularSites(prefs_, num_sites_)) { |
| 211 popular_sites_.reset(new PopularSites( | 211 popular_sites_.reset(new PopularSites( |
| 212 prefs_, | 212 prefs_, |
| 213 template_url_service_, | 213 template_url_service_, |
| 214 variations_service_, | 214 variations_service_, |
| 215 download_context_, | 215 download_context_, |
| 216 GetPopularSitesCountry(), | 216 GetPopularSitesCountry(), |
| 217 GetPopularSitesVersion(), | 217 GetPopularSitesVersion(), |
| 218 false, | 218 false, |
| 219 base::Bind(&MostVisitedSites::OnPopularSitesAvailable, | 219 base::Bind(&MostVisitedSites::OnPopularSitesAvailable, |
| 220 base::Unretained(this)))); | 220 base::Unretained(this)))); |
| 221 } else { | 221 } else { |
| 222 received_popular_sites_ = true; | 222 received_popular_sites_ = true; |
| 223 } | 223 } |
| 224 | 224 |
| 225 // TODO(treib): Can |top_sites_| ever be null? If not, remove these checks. | |
| 225 if (top_sites_) { | 226 if (top_sites_) { |
| 226 // TopSites updates itself after a delay. To ensure up-to-date results, | 227 // TopSites updates itself after a delay. To ensure up-to-date results, |
| 227 // force an update now. | 228 // force an update now. |
| 228 top_sites_->SyncWithHistory(); | 229 top_sites_->SyncWithHistory(); |
| 229 | 230 |
| 230 // Register as TopSitesObserver so that we can update ourselves when the | 231 // Register as TopSitesObserver so that we can update ourselves when the |
| 231 // TopSites changes. | 232 // TopSites changes. |
| 232 scoped_observer_.Add(top_sites_.get()); | 233 scoped_observer_.Add(top_sites_.get()); |
| 233 } | 234 } |
| 234 | 235 |
| 235 suggestions_subscription_ = suggestions_service_->AddCallback( | 236 suggestions_subscription_ = suggestions_service_->AddCallback( |
| 236 base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, | 237 base::Bind(&MostVisitedSites::OnSuggestionsProfileAvailable, |
| 237 base::Unretained(this))); | 238 base::Unretained(this))); |
| 238 | 239 |
| 239 // Immediately build the current suggestions, getting personal suggestions | 240 // Immediately build the current suggestions, getting personal suggestions |
| 240 // from the SuggestionsService's cache or, if that is empty, from TopSites. | 241 // from the SuggestionsService's cache or, if that is empty, from TopSites. |
| 241 BuildCurrentSuggestions(); | 242 BuildCurrentSuggestions(); |
| 242 // Also start a request for fresh suggestions. | 243 // Also start a request for fresh suggestions. |
| 243 suggestions_service_->FetchSuggestionsData(); | 244 suggestions_service_->FetchSuggestionsData(); |
| 244 } | 245 } |
| 245 | 246 |
| 246 void MostVisitedSites::GetURLThumbnail( | 247 void MostVisitedSites::GetURLThumbnail(const GURL& url, |
| 247 const GURL& url, | 248 const ThumbnailCallback& callback) { |
| 248 const ThumbnailCallback& callback) { | |
| 249 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 249 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 250 | 250 |
| 251 // TODO(treib): Move this to the blocking pool? Doesn't seem related to DB. | |
| 251 BrowserThread::PostTaskAndReplyWithResult( | 252 BrowserThread::PostTaskAndReplyWithResult( |
| 252 BrowserThread::DB, FROM_HERE, | 253 BrowserThread::DB, FROM_HERE, |
| 253 base::Bind(&MaybeFetchLocalThumbnail, url, top_sites_), | 254 base::Bind(&MaybeFetchLocalThumbnail, url, top_sites_), |
| 254 base::Bind(&MostVisitedSites::OnLocalThumbnailFetched, | 255 base::Bind(&MostVisitedSites::OnLocalThumbnailFetched, |
| 255 weak_ptr_factory_.GetWeakPtr(), url, callback)); | 256 weak_ptr_factory_.GetWeakPtr(), url, callback)); |
| 256 } | 257 } |
| 257 | 258 |
| 258 void MostVisitedSites::OnLocalThumbnailFetched( | 259 void MostVisitedSites::OnLocalThumbnailFetched( |
| 259 const GURL& url, | 260 const GURL& url, |
| 260 const ThumbnailCallback& callback, | 261 const ThumbnailCallback& callback, |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 281 } | 282 } |
| 282 if (mv_source_ == SUGGESTIONS_SERVICE) { | 283 if (mv_source_ == SUGGESTIONS_SERVICE) { |
| 283 return suggestions_service_->GetPageThumbnail( | 284 return suggestions_service_->GetPageThumbnail( |
| 284 url, base::Bind(&MostVisitedSites::OnObtainedThumbnail, | 285 url, base::Bind(&MostVisitedSites::OnObtainedThumbnail, |
| 285 weak_ptr_factory_.GetWeakPtr(), false, callback)); | 286 weak_ptr_factory_.GetWeakPtr(), false, callback)); |
| 286 } | 287 } |
| 287 } | 288 } |
| 288 OnObtainedThumbnail(true, callback, url, bitmap.get()); | 289 OnObtainedThumbnail(true, callback, url, bitmap.get()); |
| 289 } | 290 } |
| 290 | 291 |
| 291 void MostVisitedSites::OnObtainedThumbnail( | 292 void MostVisitedSites::OnObtainedThumbnail(bool is_local_thumbnail, |
| 292 bool is_local_thumbnail, | 293 const ThumbnailCallback& callback, |
| 293 const ThumbnailCallback& callback, | 294 const GURL& url, |
| 294 const GURL& url, | 295 const SkBitmap* bitmap) { |
| 295 const SkBitmap* bitmap) { | |
| 296 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 296 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 297 callback.Run(is_local_thumbnail, bitmap); | 297 callback.Run(is_local_thumbnail, bitmap); |
| 298 } | 298 } |
| 299 | 299 |
| 300 void MostVisitedSites::AddOrRemoveBlacklistedUrl( | 300 void MostVisitedSites::AddOrRemoveBlacklistedUrl(const GURL& url, |
| 301 const GURL& url, bool add_url) { | 301 bool add_url) { |
| 302 // Always blacklist in the local TopSites. | 302 // Always blacklist in the local TopSites. |
| 303 if (top_sites_) { | 303 if (top_sites_) { |
| 304 if (add_url) | 304 if (add_url) |
| 305 top_sites_->AddBlacklistedURL(url); | 305 top_sites_->AddBlacklistedURL(url); |
| 306 else | 306 else |
| 307 top_sites_->RemoveBlacklistedURL(url); | 307 top_sites_->RemoveBlacklistedURL(url); |
| 308 } | 308 } |
| 309 | 309 |
| 310 // Only blacklist in the server-side suggestions service if it's active. | 310 // Only blacklist in the server-side suggestions service if it's active. |
| 311 if (mv_source_ == SUGGESTIONS_SERVICE) { | 311 if (mv_source_ == SUGGESTIONS_SERVICE) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 351 LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES); | 351 LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES); |
| 352 } | 352 } |
| 353 | 353 |
| 354 void MostVisitedSites::OnURLFilterChanged() { | 354 void MostVisitedSites::OnURLFilterChanged() { |
| 355 BuildCurrentSuggestions(); | 355 BuildCurrentSuggestions(); |
| 356 } | 356 } |
| 357 | 357 |
| 358 // static | 358 // static |
| 359 void MostVisitedSites::RegisterProfilePrefs( | 359 void MostVisitedSites::RegisterProfilePrefs( |
| 360 user_prefs::PrefRegistrySyncable* registry) { | 360 user_prefs::PrefRegistrySyncable* registry) { |
| 361 // TODO(treib): Remove this, it's unused. Do we need migration code to clean | |
| 362 // up existing entries? | |
| 361 registry->RegisterListPref(ntp_tiles::prefs::kNTPSuggestionsURL); | 363 registry->RegisterListPref(ntp_tiles::prefs::kNTPSuggestionsURL); |
| 364 // TODO(treib): Remove this. It's only used to determine if we need | |
| 365 // PopularSites at all. Find a way to do that without prefs, or failing that, | |
| 366 // replace this list pref by a simple bool. | |
| 362 registry->RegisterListPref(ntp_tiles::prefs::kNTPSuggestionsIsPersonal); | 367 registry->RegisterListPref(ntp_tiles::prefs::kNTPSuggestionsIsPersonal); |
| 363 } | 368 } |
| 364 | 369 |
| 365 void MostVisitedSites::BuildCurrentSuggestions() { | 370 void MostVisitedSites::BuildCurrentSuggestions() { |
| 366 // Get the current suggestions from cache. If the cache is empty, this will | 371 // Get the current suggestions from cache. If the cache is empty, this will |
| 367 // fall back to TopSites. | 372 // fall back to TopSites. |
| 368 OnSuggestionsProfileAvailable( | 373 OnSuggestionsProfileAvailable( |
| 369 suggestions_service_->GetSuggestionsDataFromCache()); | 374 suggestions_service_->GetSuggestionsDataFromCache()); |
| 370 } | 375 } |
| 371 | 376 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 389 } | 394 } |
| 390 return base::FilePath(); | 395 return base::FilePath(); |
| 391 } | 396 } |
| 392 | 397 |
| 393 void MostVisitedSites::OnMostVisitedURLsAvailable( | 398 void MostVisitedSites::OnMostVisitedURLsAvailable( |
| 394 const history::MostVisitedURLList& visited_list) { | 399 const history::MostVisitedURLList& visited_list) { |
| 395 SupervisedUserURLFilter* url_filter = | 400 SupervisedUserURLFilter* url_filter = |
| 396 SupervisedUserServiceFactory::GetForProfile(profile_) | 401 SupervisedUserServiceFactory::GetForProfile(profile_) |
| 397 ->GetURLFilterForUIThread(); | 402 ->GetURLFilterForUIThread(); |
| 398 | 403 |
| 399 MostVisitedSites::SuggestionsPtrVector suggestions; | 404 SuggestionsPtrVector suggestions; |
| 400 size_t num_tiles = | 405 size_t num_tiles = |
| 401 std::min(visited_list.size(), static_cast<size_t>(num_sites_)); | 406 std::min(visited_list.size(), static_cast<size_t>(num_sites_)); |
| 402 for (size_t i = 0; i < num_tiles; ++i) { | 407 for (size_t i = 0; i < num_tiles; ++i) { |
| 403 const history::MostVisitedURL& visited = visited_list[i]; | 408 const history::MostVisitedURL& visited = visited_list[i]; |
| 404 if (visited.url.is_empty()) { | 409 if (visited.url.is_empty()) { |
| 405 num_tiles = i; | 410 num_tiles = i; |
| 406 break; // This is the signal that there are no more real visited sites. | 411 break; // This is the signal that there are no more real visited sites. |
| 407 } | 412 } |
| 408 if (url_filter->GetFilteringBehaviorForURL(visited.url) == | 413 if (url_filter->GetFilteringBehaviorForURL(visited.url) == |
| 409 SupervisedUserURLFilter::FilteringBehavior::BLOCK) { | 414 SupervisedUserURLFilter::FilteringBehavior::BLOCK) { |
| 410 continue; | 415 continue; |
| 411 } | 416 } |
| 412 | 417 |
| 413 std::unique_ptr<Suggestion> suggestion(new Suggestion()); | 418 std::unique_ptr<Suggestion> suggestion(new Suggestion()); |
| 414 suggestion->title = visited.title; | 419 suggestion->title = visited.title; |
| 415 suggestion->url = visited.url; | 420 suggestion->url = visited.url; |
| 416 suggestion->source = TOP_SITES; | 421 suggestion->source = TOP_SITES; |
| 417 suggestion->whitelist_icon_path = GetWhitelistLargeIconPath(visited.url); | 422 suggestion->whitelist_icon_path = GetWhitelistLargeIconPath(visited.url); |
| 418 | 423 |
| 419 suggestions.push_back(std::move(suggestion)); | 424 suggestions.push_back(std::move(suggestion)); |
| 420 } | 425 } |
| 421 | 426 |
| 422 received_most_visited_sites_ = true; | 427 received_most_visited_sites_ = true; |
| 423 mv_source_ = TOP_SITES; | 428 mv_source_ = TOP_SITES; |
| 424 SaveNewNTPSuggestions(&suggestions); | 429 SaveNewSuggestions(&suggestions); |
| 425 NotifyMostVisitedURLsObserver(); | 430 NotifyMostVisitedURLsObserver(); |
| 426 } | 431 } |
| 427 | 432 |
| 428 void MostVisitedSites::OnSuggestionsProfileAvailable( | 433 void MostVisitedSites::OnSuggestionsProfileAvailable( |
| 429 const SuggestionsProfile& suggestions_profile) { | 434 const SuggestionsProfile& suggestions_profile) { |
| 430 int num_tiles = suggestions_profile.suggestions_size(); | 435 int num_tiles = suggestions_profile.suggestions_size(); |
| 431 // With no server suggestions, fall back to local TopSites. | 436 // With no server suggestions, fall back to local TopSites. |
| 432 if (num_tiles == 0) { | 437 if (num_tiles == 0) { |
| 433 InitiateTopSitesQuery(); | 438 InitiateTopSitesQuery(); |
| 434 return; | 439 return; |
| 435 } | 440 } |
| 436 if (num_sites_ < num_tiles) | 441 if (num_sites_ < num_tiles) |
| 437 num_tiles = num_sites_; | 442 num_tiles = num_sites_; |
| 438 | 443 |
| 439 SupervisedUserURLFilter* url_filter = | 444 SupervisedUserURLFilter* url_filter = |
| 440 SupervisedUserServiceFactory::GetForProfile(profile_) | 445 SupervisedUserServiceFactory::GetForProfile(profile_) |
| 441 ->GetURLFilterForUIThread(); | 446 ->GetURLFilterForUIThread(); |
| 442 MostVisitedSites::SuggestionsPtrVector suggestions; | 447 SuggestionsPtrVector suggestions; |
| 443 for (int i = 0; i < num_tiles; ++i) { | 448 for (int i = 0; i < num_tiles; ++i) { |
| 444 const ChromeSuggestion& suggestion = suggestions_profile.suggestions(i); | 449 const ChromeSuggestion& suggestion = suggestions_profile.suggestions(i); |
| 445 if (url_filter->GetFilteringBehaviorForURL(GURL(suggestion.url())) == | 450 if (url_filter->GetFilteringBehaviorForURL(GURL(suggestion.url())) == |
| 446 SupervisedUserURLFilter::FilteringBehavior::BLOCK) { | 451 SupervisedUserURLFilter::FilteringBehavior::BLOCK) { |
| 447 continue; | 452 continue; |
| 448 } | 453 } |
| 449 | 454 |
| 450 std::unique_ptr<Suggestion> generated_suggestion(new Suggestion()); | 455 std::unique_ptr<Suggestion> generated_suggestion(new Suggestion()); |
| 451 generated_suggestion->title = base::UTF8ToUTF16(suggestion.title()); | 456 generated_suggestion->title = base::UTF8ToUTF16(suggestion.title()); |
| 452 generated_suggestion->url = GURL(suggestion.url()); | 457 generated_suggestion->url = GURL(suggestion.url()); |
| 453 generated_suggestion->source = SUGGESTIONS_SERVICE; | 458 generated_suggestion->source = SUGGESTIONS_SERVICE; |
| 454 generated_suggestion->whitelist_icon_path = GetWhitelistLargeIconPath( | 459 generated_suggestion->whitelist_icon_path = GetWhitelistLargeIconPath( |
| 455 GURL(suggestion.url())); | 460 GURL(suggestion.url())); |
| 456 if (suggestion.providers_size() > 0) | 461 if (suggestion.providers_size() > 0) |
| 457 generated_suggestion->provider_index = suggestion.providers(0); | 462 generated_suggestion->provider_index = suggestion.providers(0); |
| 458 | 463 |
| 459 suggestions.push_back(std::move(generated_suggestion)); | 464 suggestions.push_back(std::move(generated_suggestion)); |
| 460 } | 465 } |
| 461 | 466 |
| 462 received_most_visited_sites_ = true; | 467 received_most_visited_sites_ = true; |
| 463 mv_source_ = SUGGESTIONS_SERVICE; | 468 mv_source_ = SUGGESTIONS_SERVICE; |
| 464 SaveNewNTPSuggestions(&suggestions); | 469 SaveNewSuggestions(&suggestions); |
| 465 NotifyMostVisitedURLsObserver(); | 470 NotifyMostVisitedURLsObserver(); |
| 466 } | 471 } |
| 467 | 472 |
| 468 MostVisitedSites::SuggestionsPtrVector | 473 MostVisitedSites::SuggestionsPtrVector |
| 469 MostVisitedSites::CreateWhitelistEntryPointSuggestions( | 474 MostVisitedSites::CreateWhitelistEntryPointSuggestions( |
| 470 const MostVisitedSites::SuggestionsPtrVector& personal_suggestions) { | 475 const SuggestionsPtrVector& personal_suggestions) { |
| 471 size_t num_personal_suggestions = personal_suggestions.size(); | 476 size_t num_personal_suggestions = personal_suggestions.size(); |
| 472 DCHECK_LE(num_personal_suggestions, static_cast<size_t>(num_sites_)); | 477 DCHECK_LE(num_personal_suggestions, static_cast<size_t>(num_sites_)); |
| 473 | 478 |
| 474 size_t num_whitelist_suggestions = num_sites_ - num_personal_suggestions; | 479 size_t num_whitelist_suggestions = num_sites_ - num_personal_suggestions; |
| 475 MostVisitedSites::SuggestionsPtrVector whitelist_suggestions; | 480 SuggestionsPtrVector whitelist_suggestions; |
| 476 | 481 |
| 477 SupervisedUserService* supervised_user_service = | 482 SupervisedUserService* supervised_user_service = |
| 478 SupervisedUserServiceFactory::GetForProfile(profile_); | 483 SupervisedUserServiceFactory::GetForProfile(profile_); |
| 479 SupervisedUserURLFilter* url_filter = | 484 SupervisedUserURLFilter* url_filter = |
| 480 supervised_user_service->GetURLFilterForUIThread(); | 485 supervised_user_service->GetURLFilterForUIThread(); |
| 481 | 486 |
| 482 std::set<std::string> personal_hosts; | 487 std::set<std::string> personal_hosts; |
| 483 for (const auto& suggestion : personal_suggestions) | 488 for (const auto& suggestion : personal_suggestions) |
| 484 personal_hosts.insert(suggestion->url.host()); | 489 personal_hosts.insert(suggestion->url.host()); |
| 485 | 490 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 508 whitelist_suggestions.push_back(std::move(suggestion)); | 513 whitelist_suggestions.push_back(std::move(suggestion)); |
| 509 if (whitelist_suggestions.size() >= num_whitelist_suggestions) | 514 if (whitelist_suggestions.size() >= num_whitelist_suggestions) |
| 510 break; | 515 break; |
| 511 } | 516 } |
| 512 | 517 |
| 513 return whitelist_suggestions; | 518 return whitelist_suggestions; |
| 514 } | 519 } |
| 515 | 520 |
| 516 MostVisitedSites::SuggestionsPtrVector | 521 MostVisitedSites::SuggestionsPtrVector |
| 517 MostVisitedSites::CreatePopularSitesSuggestions( | 522 MostVisitedSites::CreatePopularSitesSuggestions( |
| 518 const MostVisitedSites::SuggestionsPtrVector& personal_suggestions, | 523 const SuggestionsPtrVector& personal_suggestions, |
| 519 const MostVisitedSites::SuggestionsPtrVector& whitelist_suggestions) { | 524 const SuggestionsPtrVector& whitelist_suggestions) { |
| 520 // For child accounts popular sites suggestions will not be added. | 525 // For child accounts popular sites suggestions will not be added. |
| 521 if (is_child_profile_) | 526 if (is_child_profile_) |
| 522 return MostVisitedSites::SuggestionsPtrVector(); | 527 return SuggestionsPtrVector(); |
| 523 | 528 |
| 524 size_t num_suggestions = | 529 size_t num_suggestions = |
| 525 personal_suggestions.size() + whitelist_suggestions.size(); | 530 personal_suggestions.size() + whitelist_suggestions.size(); |
| 526 DCHECK_LE(num_suggestions, static_cast<size_t>(num_sites_)); | 531 DCHECK_LE(num_suggestions, static_cast<size_t>(num_sites_)); |
| 527 | 532 |
| 528 // Collect non-blacklisted popular suggestions, skipping those already present | 533 // Collect non-blacklisted popular suggestions, skipping those already present |
| 529 // in the personal suggestions. | 534 // in the personal suggestions. |
| 530 size_t num_popular_sites_suggestions = num_sites_ - num_suggestions; | 535 size_t num_popular_sites_suggestions = num_sites_ - num_suggestions; |
| 531 MostVisitedSites::SuggestionsPtrVector popular_sites_suggestions; | 536 SuggestionsPtrVector popular_sites_suggestions; |
| 532 | 537 |
| 533 if (num_popular_sites_suggestions > 0 && popular_sites_) { | 538 if (num_popular_sites_suggestions > 0 && popular_sites_) { |
| 534 std::set<std::string> hosts; | 539 std::set<std::string> hosts; |
| 535 for (const auto& suggestion : personal_suggestions) | 540 for (const auto& suggestion : personal_suggestions) |
| 536 hosts.insert(suggestion->url.host()); | 541 hosts.insert(suggestion->url.host()); |
| 537 for (const auto& suggestion : whitelist_suggestions) | 542 for (const auto& suggestion : whitelist_suggestions) |
| 538 hosts.insert(suggestion->url.host()); | 543 hosts.insert(suggestion->url.host()); |
| 539 for (const PopularSites::Site& popular_site : popular_sites_->sites()) { | 544 for (const PopularSites::Site& popular_site : popular_sites_->sites()) { |
| 540 // Skip blacklisted sites. | 545 // Skip blacklisted sites. |
| 541 if (top_sites_ && top_sites_->IsBlacklisted(popular_site.url)) | 546 if (top_sites_ && top_sites_->IsBlacklisted(popular_site.url)) |
| 542 continue; | 547 continue; |
| 543 std::string host = popular_site.url.host(); | 548 std::string host = popular_site.url.host(); |
| 544 // Skip suggestions already present in personal or whitelists. | 549 // Skip suggestions already present in personal or whitelists. |
| 545 if (hosts.find(host) != hosts.end()) | 550 if (hosts.find(host) != hosts.end()) |
| 546 continue; | 551 continue; |
| 547 | 552 |
| 548 std::unique_ptr<Suggestion> suggestion(new Suggestion()); | 553 std::unique_ptr<Suggestion> suggestion(new Suggestion()); |
| 549 suggestion->title = popular_site.title; | 554 suggestion->title = popular_site.title; |
| 550 suggestion->url = GURL(popular_site.url); | 555 suggestion->url = GURL(popular_site.url); |
| 551 suggestion->source = POPULAR; | 556 suggestion->source = POPULAR; |
| 552 | 557 |
| 553 popular_sites_suggestions.push_back(std::move(suggestion)); | 558 popular_sites_suggestions.push_back(std::move(suggestion)); |
| 554 if (popular_sites_suggestions.size() >= num_popular_sites_suggestions) | 559 if (popular_sites_suggestions.size() >= num_popular_sites_suggestions) |
| 555 break; | 560 break; |
| 556 } | 561 } |
| 557 } | 562 } |
| 558 return popular_sites_suggestions; | 563 return popular_sites_suggestions; |
| 559 } | 564 } |
| 560 | 565 |
| 561 void MostVisitedSites::SaveNewNTPSuggestions( | 566 void MostVisitedSites::SaveNewSuggestions( |
| 562 MostVisitedSites::SuggestionsPtrVector* personal_suggestions) { | 567 SuggestionsPtrVector* personal_suggestions) { |
| 563 MostVisitedSites::SuggestionsPtrVector whitelist_suggestions = | 568 SuggestionsPtrVector whitelist_suggestions = |
| 564 CreateWhitelistEntryPointSuggestions(*personal_suggestions); | 569 CreateWhitelistEntryPointSuggestions(*personal_suggestions); |
| 565 MostVisitedSites::SuggestionsPtrVector popular_sites_suggestions = | 570 SuggestionsPtrVector popular_sites_suggestions = |
| 566 CreatePopularSitesSuggestions(*personal_suggestions, | 571 CreatePopularSitesSuggestions(*personal_suggestions, |
| 567 whitelist_suggestions); | 572 whitelist_suggestions); |
| 573 | |
| 568 size_t num_actual_tiles = personal_suggestions->size() + | 574 size_t num_actual_tiles = personal_suggestions->size() + |
| 569 whitelist_suggestions.size() + | 575 whitelist_suggestions.size() + |
| 570 popular_sites_suggestions.size(); | 576 popular_sites_suggestions.size(); |
| 571 std::vector<std::string> old_sites_url; | 577 DCHECK_LE(num_actual_tiles, static_cast<size_t>(num_sites_)); |
| 572 std::vector<bool> old_sites_is_personal; | 578 |
| 573 // TODO(treib): We used to call |GetPreviousNTPSites| here to populate | 579 SuggestionsPtrVector merged_suggestions = MergeSuggestions( |
| 574 // |old_sites_url| and |old_sites_is_personal|, but that caused problems | 580 personal_suggestions, &whitelist_suggestions, &popular_sites_suggestions); |
| 575 // (crbug.com/585391). Either figure out a way to fix them and re-enable, | |
| 576 // or properly remove the order-persisting code. crbug.com/601734 | |
| 577 MostVisitedSites::SuggestionsPtrVector merged_suggestions = MergeSuggestions( | |
| 578 personal_suggestions, &whitelist_suggestions, &popular_sites_suggestions, | |
| 579 old_sites_url, old_sites_is_personal); | |
| 580 DCHECK_EQ(num_actual_tiles, merged_suggestions.size()); | 581 DCHECK_EQ(num_actual_tiles, merged_suggestions.size()); |
| 582 | |
| 581 current_suggestions_.resize(merged_suggestions.size()); | 583 current_suggestions_.resize(merged_suggestions.size()); |
| 582 for (size_t i = 0; i < merged_suggestions.size(); ++i) | 584 for (size_t i = 0; i < merged_suggestions.size(); ++i) |
| 583 std::swap(*merged_suggestions[i], current_suggestions_[i]); | 585 std::swap(*merged_suggestions[i], current_suggestions_[i]); |
| 586 | |
| 584 if (received_popular_sites_) | 587 if (received_popular_sites_) |
| 585 SaveCurrentNTPSites(); | 588 SaveCurrentSuggestionsToPrefs(); |
| 586 } | 589 } |
| 587 | 590 |
| 588 // static | 591 // static |
| 589 MostVisitedSites::SuggestionsPtrVector MostVisitedSites::MergeSuggestions( | 592 MostVisitedSites::SuggestionsPtrVector MostVisitedSites::MergeSuggestions( |
| 590 MostVisitedSites::SuggestionsPtrVector* personal_suggestions, | 593 SuggestionsPtrVector* personal_suggestions, |
| 591 MostVisitedSites::SuggestionsPtrVector* whitelist_suggestions, | 594 SuggestionsPtrVector* whitelist_suggestions, |
| 592 MostVisitedSites::SuggestionsPtrVector* popular_suggestions, | 595 SuggestionsPtrVector* popular_suggestions) { |
| 593 const std::vector<std::string>& old_sites_url, | |
| 594 const std::vector<bool>& old_sites_is_personal) { | |
| 595 size_t num_personal_suggestions = personal_suggestions->size(); | 596 size_t num_personal_suggestions = personal_suggestions->size(); |
| 596 size_t num_whitelist_suggestions = whitelist_suggestions->size(); | 597 size_t num_whitelist_suggestions = whitelist_suggestions->size(); |
| 597 size_t num_popular_suggestions = popular_suggestions->size(); | 598 size_t num_popular_suggestions = popular_suggestions->size(); |
| 598 size_t num_tiles = num_popular_suggestions + num_whitelist_suggestions + | 599 size_t num_tiles = num_popular_suggestions + num_whitelist_suggestions + |
| 599 num_personal_suggestions; | 600 num_personal_suggestions; |
| 600 MostVisitedSites::SuggestionsPtrVector merged_suggestions; | 601 SuggestionsPtrVector merged_suggestions; |
| 601 merged_suggestions.resize(num_tiles); | 602 AppendSuggestions(personal_suggestions, &merged_suggestions); |
| 603 AppendSuggestions(whitelist_suggestions, &merged_suggestions); | |
| 604 AppendSuggestions(popular_suggestions, &merged_suggestions); | |
| 605 DCHECK_EQ(num_tiles, merged_suggestions.size()); | |
| 602 | 606 |
| 603 size_t num_old_tiles = old_sites_url.size(); | |
| 604 DCHECK_LE(num_old_tiles, num_tiles); | |
| 605 DCHECK_EQ(num_old_tiles, old_sites_is_personal.size()); | |
| 606 std::vector<std::string> old_sites_host; | |
| 607 old_sites_host.reserve(num_old_tiles); | |
| 608 // Only populate the hosts for popular suggestions as only they can be | |
| 609 // replaced by host. Personal suggestions require an exact url match to be | |
| 610 // replaced. | |
| 611 for (size_t i = 0; i < num_old_tiles; ++i) { | |
| 612 old_sites_host.push_back(old_sites_is_personal[i] | |
| 613 ? std::string() | |
| 614 : GURL(old_sites_url[i]).host()); | |
| 615 } | |
| 616 | |
| 617 // Insert personal suggestions if they existed previously. | |
| 618 std::vector<size_t> new_personal_suggestions = InsertMatchingSuggestions( | |
| 619 personal_suggestions, &merged_suggestions, old_sites_url, old_sites_host); | |
| 620 // Insert whitelist suggestions if they existed previously. | |
| 621 std::vector<size_t> new_whitelist_suggestions = | |
| 622 InsertMatchingSuggestions(whitelist_suggestions, &merged_suggestions, | |
| 623 old_sites_url, old_sites_host); | |
| 624 // Insert popular suggestions if they existed previously. | |
| 625 std::vector<size_t> new_popular_suggestions = InsertMatchingSuggestions( | |
| 626 popular_suggestions, &merged_suggestions, old_sites_url, old_sites_host); | |
| 627 // Insert leftover personal suggestions. | |
| 628 size_t filled_so_far = InsertAllSuggestions( | |
| 629 0, new_personal_suggestions, personal_suggestions, &merged_suggestions); | |
| 630 // Insert leftover whitelist suggestions. | |
| 631 filled_so_far = | |
| 632 InsertAllSuggestions(filled_so_far, new_whitelist_suggestions, | |
| 633 whitelist_suggestions, &merged_suggestions); | |
| 634 // Insert leftover popular suggestions. | |
| 635 InsertAllSuggestions(filled_so_far, new_popular_suggestions, | |
| 636 popular_suggestions, &merged_suggestions); | |
| 637 return merged_suggestions; | 607 return merged_suggestions; |
| 638 } | 608 } |
| 639 | 609 |
| 640 void MostVisitedSites::GetPreviousNTPSites( | 610 // static |
| 641 size_t num_tiles, | 611 void MostVisitedSites::AppendSuggestions(SuggestionsPtrVector* src, |
|
Bernhard Bauer
2016/05/18 10:13:31
Can we move this to an anonymous namespace? Heck,
Marc Treib
2016/05/18 10:47:59
Moving it into stl_util.h isn't worth it IMO.
We
Bernhard Bauer
2016/05/18 10:59:28
Ok, that's the next thing I'd have suggested 😉 Add
Marc Treib
2016/05/18 11:31:15
There is already a TODO in the header for the swit
| |
| 642 std::vector<std::string>* old_sites_url, | 612 SuggestionsPtrVector* dst) { |
| 643 std::vector<bool>* old_sites_is_personal) const { | 613 dst->insert(dst->end(), |
| 644 const base::ListValue* url_list = prefs_->GetList( | 614 std::make_move_iterator(src->begin()), |
| 645 ntp_tiles::prefs::kNTPSuggestionsURL); | 615 std::make_move_iterator(src->end())); |
| 646 const base::ListValue* source_list = | |
| 647 prefs_->GetList(ntp_tiles::prefs::kNTPSuggestionsIsPersonal); | |
| 648 DCHECK_EQ(url_list->GetSize(), source_list->GetSize()); | |
| 649 if (url_list->GetSize() < num_tiles) | |
| 650 num_tiles = url_list->GetSize(); | |
| 651 if (num_tiles == 0) { | |
| 652 // No fallback required as Personal suggestions take precedence anyway. | |
| 653 return; | |
| 654 } | |
| 655 old_sites_url->reserve(num_tiles); | |
| 656 old_sites_is_personal->reserve(num_tiles); | |
| 657 for (size_t i = 0; i < num_tiles; ++i) { | |
| 658 std::string url_string; | |
| 659 bool success = url_list->GetString(i, &url_string); | |
| 660 DCHECK(success); | |
| 661 old_sites_url->push_back(url_string); | |
| 662 bool is_personal; | |
| 663 success = source_list->GetBoolean(i, &is_personal); | |
| 664 DCHECK(success); | |
| 665 old_sites_is_personal->push_back(is_personal); | |
| 666 } | |
| 667 } | 616 } |
| 668 | 617 |
| 669 void MostVisitedSites::SaveCurrentNTPSites() { | 618 void MostVisitedSites::SaveCurrentSuggestionsToPrefs() { |
| 670 base::ListValue url_list; | 619 base::ListValue url_list; |
| 671 base::ListValue source_list; | 620 base::ListValue source_list; |
| 672 for (const auto& suggestion : current_suggestions_) { | 621 for (const auto& suggestion : current_suggestions_) { |
| 673 url_list.AppendString(suggestion.url.spec()); | 622 url_list.AppendString(suggestion.url.spec()); |
| 674 source_list.AppendBoolean(suggestion.source != MostVisitedSites::POPULAR); | 623 source_list.AppendBoolean(suggestion.source != POPULAR); |
| 675 } | 624 } |
| 676 prefs_->Set(ntp_tiles::prefs::kNTPSuggestionsIsPersonal, source_list); | 625 prefs_->Set(ntp_tiles::prefs::kNTPSuggestionsIsPersonal, source_list); |
| 677 prefs_->Set(ntp_tiles::prefs::kNTPSuggestionsURL, url_list); | 626 prefs_->Set(ntp_tiles::prefs::kNTPSuggestionsURL, url_list); |
| 678 } | 627 } |
| 679 | 628 |
| 680 // static | |
| 681 std::vector<size_t> MostVisitedSites::InsertMatchingSuggestions( | |
| 682 MostVisitedSites::SuggestionsPtrVector* src_suggestions, | |
| 683 MostVisitedSites::SuggestionsPtrVector* dst_suggestions, | |
| 684 const std::vector<std::string>& match_urls, | |
| 685 const std::vector<std::string>& match_hosts) { | |
| 686 std::vector<size_t> unmatched_suggestions; | |
| 687 size_t num_src_suggestions = src_suggestions->size(); | |
| 688 size_t num_matchers = match_urls.size(); | |
| 689 for (size_t i = 0; i < num_src_suggestions; ++i) { | |
| 690 size_t position; | |
| 691 for (position = 0; position < num_matchers; ++position) { | |
| 692 if ((*dst_suggestions)[position] != nullptr) | |
| 693 continue; | |
| 694 if (match_urls[position] == (*src_suggestions)[i]->url.spec()) | |
| 695 break; | |
| 696 // match_hosts is only populated for suggestions which can be replaced by | |
| 697 // host matching like popular suggestions. | |
| 698 if (match_hosts[position] == (*src_suggestions)[i]->url.host()) | |
| 699 break; | |
| 700 } | |
| 701 if (position == num_matchers) { | |
| 702 unmatched_suggestions.push_back(i); | |
| 703 } else { | |
| 704 // A move is required as the source and destination containers own the | |
| 705 // elements. | |
| 706 std::swap((*dst_suggestions)[position], (*src_suggestions)[i]); | |
| 707 } | |
| 708 } | |
| 709 return unmatched_suggestions; | |
| 710 } | |
| 711 | |
| 712 // static | |
| 713 size_t MostVisitedSites::InsertAllSuggestions( | |
| 714 size_t start_position, | |
| 715 const std::vector<size_t>& insert_positions, | |
| 716 std::vector<std::unique_ptr<Suggestion>>* src_suggestions, | |
| 717 std::vector<std::unique_ptr<Suggestion>>* dst_suggestions) { | |
| 718 size_t num_inserts = insert_positions.size(); | |
| 719 size_t num_dests = dst_suggestions->size(); | |
| 720 | |
| 721 size_t src_pos = 0; | |
| 722 size_t i = start_position; | |
| 723 for (; i < num_dests && src_pos < num_inserts; ++i) { | |
| 724 if ((*dst_suggestions)[i] != nullptr) | |
| 725 continue; | |
| 726 size_t src = insert_positions[src_pos++]; | |
| 727 std::swap((*dst_suggestions)[i], (*src_suggestions)[src]); | |
| 728 } | |
| 729 // Return destination positions filled so far which becomes the start_position | |
| 730 // for future runs. | |
| 731 return i; | |
| 732 } | |
| 733 | |
| 734 void MostVisitedSites::NotifyMostVisitedURLsObserver() { | 629 void MostVisitedSites::NotifyMostVisitedURLsObserver() { |
| 735 size_t num_suggestions = current_suggestions_.size(); | |
| 736 if (received_most_visited_sites_ && received_popular_sites_ && | 630 if (received_most_visited_sites_ && received_popular_sites_ && |
| 737 !recorded_uma_) { | 631 !recorded_uma_) { |
| 738 RecordImpressionUMAMetrics(); | 632 RecordImpressionUMAMetrics(); |
| 739 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfTiles", num_suggestions); | 633 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfTiles", |
| 634 current_suggestions_.size()); | |
| 740 recorded_uma_ = true; | 635 recorded_uma_ = true; |
| 741 } | 636 } |
| 742 | 637 |
| 743 if (!observer_) | 638 if (!observer_) |
| 744 return; | 639 return; |
| 745 | 640 |
| 746 observer_->OnMostVisitedURLsAvailable(current_suggestions_); | 641 observer_->OnMostVisitedURLsAvailable(current_suggestions_); |
| 747 } | 642 } |
| 748 | 643 |
| 749 void MostVisitedSites::OnPopularSitesAvailable(bool success) { | 644 void MostVisitedSites::OnPopularSitesAvailable(bool success) { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 773 | 668 |
| 774 void MostVisitedSites::TopSitesLoaded(TopSites* top_sites) {} | 669 void MostVisitedSites::TopSitesLoaded(TopSites* top_sites) {} |
| 775 | 670 |
| 776 void MostVisitedSites::TopSitesChanged(TopSites* top_sites, | 671 void MostVisitedSites::TopSitesChanged(TopSites* top_sites, |
| 777 ChangeReason change_reason) { | 672 ChangeReason change_reason) { |
| 778 if (mv_source_ == TOP_SITES) { | 673 if (mv_source_ == TOP_SITES) { |
| 779 // The displayed suggestions are invalidated. | 674 // The displayed suggestions are invalidated. |
| 780 InitiateTopSitesQuery(); | 675 InitiateTopSitesQuery(); |
| 781 } | 676 } |
| 782 } | 677 } |
| OLD | NEW |