OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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/history/top_sites_impl.h" | 5 #include "chrome/browser/history/top_sites_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 using base::DictionaryValue; | 48 using base::DictionaryValue; |
49 using content::BrowserThread; | 49 using content::BrowserThread; |
50 using content::NavigationController; | 50 using content::NavigationController; |
51 | 51 |
52 namespace history { | 52 namespace history { |
53 | 53 |
54 namespace { | 54 namespace { |
55 | 55 |
56 void RunOrPostGetMostVisitedURLsCallback( | 56 void RunOrPostGetMostVisitedURLsCallback( |
57 base::TaskRunner* task_runner, | 57 base::TaskRunner* task_runner, |
58 bool include_forced_urls, | |
58 const TopSitesImpl::GetMostVisitedURLsCallback& callback, | 59 const TopSitesImpl::GetMostVisitedURLsCallback& callback, |
59 const MostVisitedURLList& urls) { | 60 const MostVisitedURLList& all_urls, |
61 const MostVisitedURLList& nonforced_urls) { | |
62 const MostVisitedURLList* urls = | |
63 include_forced_urls ? &all_urls : &nonforced_urls; | |
brettw
2013/11/08 22:56:07
Indent 2 more spaces.
beaudoin
2013/11/11 21:58:09
Done.
| |
60 if (task_runner->RunsTasksOnCurrentThread()) | 64 if (task_runner->RunsTasksOnCurrentThread()) |
61 callback.Run(urls); | 65 callback.Run(*urls); |
62 else | 66 else |
63 task_runner->PostTask(FROM_HERE, base::Bind(callback, urls)); | 67 task_runner->PostTask(FROM_HERE, base::Bind(callback, *urls)); |
68 } | |
69 | |
70 // Compares two MostVisitedURL having a non-null |last_forced_time|. | |
71 bool ForcedURLComparator(const MostVisitedURL& first, | |
72 const MostVisitedURL& second) { | |
73 DCHECK(!first.last_forced_time.is_null() && | |
74 !second.last_forced_time.is_null()); | |
75 return first.last_forced_time < second.last_forced_time; | |
64 } | 76 } |
65 | 77 |
66 } // namespace | 78 } // namespace |
67 | 79 |
68 // How many top sites to store in the cache. | 80 // How many non-forced top sites to store in the cache. |
69 static const size_t kTopSitesNumber = 20; | 81 static const size_t kNonForcedTopSitesNumber = 20; |
82 | |
83 // How many forced top sites to store in the cache. | |
84 static const size_t kForcedTopSitesNumber = 20; | |
70 | 85 |
71 // Max number of temporary images we'll cache. See comment above | 86 // Max number of temporary images we'll cache. See comment above |
72 // temp_images_ for details. | 87 // temp_images_ for details. |
73 static const size_t kMaxTempTopImages = 8; | 88 static const size_t kMaxTempTopImages = 8; |
74 | 89 |
75 static const int kDaysOfHistory = 90; | 90 static const int kDaysOfHistory = 90; |
76 // Time from startup to first HistoryService query. | 91 // Time from startup to first HistoryService query. |
77 static const int64 kUpdateIntervalSecs = 15; | 92 static const int64 kUpdateIntervalSecs = 15; |
78 // Intervals between requests to HistoryService. | 93 // Intervals between requests to HistoryService. |
79 static const int64 kMinUpdateIntervalMinutes = 1; | 94 static const int64 kMinUpdateIntervalMinutes = 1; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
126 | 141 |
127 if (!loaded_) { | 142 if (!loaded_) { |
128 // TODO(sky): I need to cache these and apply them after the load | 143 // TODO(sky): I need to cache these and apply them after the load |
129 // completes. | 144 // completes. |
130 return false; | 145 return false; |
131 } | 146 } |
132 | 147 |
133 bool add_temp_thumbnail = false; | 148 bool add_temp_thumbnail = false; |
134 if (!IsKnownURL(url)) { | 149 if (!IsKnownURL(url)) { |
135 if (!IsFull()) { | 150 if (!IsNonForcedFull()) { |
136 add_temp_thumbnail = true; | 151 add_temp_thumbnail = true; |
137 } else { | 152 } else { |
138 return false; // This URL is not known to us. | 153 return false; // This URL is not known to us. |
139 } | 154 } |
140 } | 155 } |
141 | 156 |
142 if (!HistoryService::CanAddURL(url)) | 157 if (!HistoryService::CanAddURL(url)) |
143 return false; // It's not a real webpage. | 158 return false; // It's not a real webpage. |
144 | 159 |
145 scoped_refptr<base::RefCountedBytes> thumbnail_data; | 160 scoped_refptr<base::RefCountedBytes> thumbnail_data; |
(...skipping 18 matching lines...) Expand all Loading... | |
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
165 | 180 |
166 if (!loaded_) { | 181 if (!loaded_) { |
167 // TODO(sky): I need to cache these and apply them after the load | 182 // TODO(sky): I need to cache these and apply them after the load |
168 // completes. | 183 // completes. |
169 return false; | 184 return false; |
170 } | 185 } |
171 | 186 |
172 bool add_temp_thumbnail = false; | 187 bool add_temp_thumbnail = false; |
173 if (!IsKnownURL(url)) { | 188 if (!IsKnownURL(url)) { |
174 if (!IsFull()) { | 189 if (!IsNonForcedFull()) { |
175 add_temp_thumbnail = true; | 190 add_temp_thumbnail = true; |
176 } else { | 191 } else { |
177 return false; // This URL is not known to us. | 192 return false; // This URL is not known to us. |
178 } | 193 } |
179 } | 194 } |
180 | 195 |
181 if (!HistoryService::CanAddURL(url)) | 196 if (!HistoryService::CanAddURL(url)) |
182 return false; // It's not a real webpage. | 197 return false; // It's not a real webpage. |
183 | 198 |
184 if (add_temp_thumbnail) { | 199 if (add_temp_thumbnail) { |
185 // Always remove the existing entry and then add it back. That way if we end | 200 // Always remove the existing entry and then add it back. That way if we end |
186 // up with too many temp thumbnails we'll prune the oldest first. | 201 // up with too many temp thumbnails we'll prune the oldest first. |
187 RemoveTemporaryThumbnailByURL(url); | 202 RemoveTemporaryThumbnailByURL(url); |
188 AddTemporaryThumbnail(url, memory, score); | 203 AddTemporaryThumbnail(url, memory, score); |
189 return true; | 204 return true; |
190 } | 205 } |
191 | 206 |
192 return SetPageThumbnailEncoded(url, memory, score); | 207 return SetPageThumbnailEncoded(url, memory, score); |
193 } | 208 } |
194 | 209 |
195 // WARNING: this function may be invoked on any thread. | 210 // WARNING: this function may be invoked on any thread. |
196 void TopSitesImpl::GetMostVisitedURLs( | 211 void TopSitesImpl::GetMostVisitedURLs( |
197 const GetMostVisitedURLsCallback& callback) { | 212 const GetMostVisitedURLsCallback& callback) { |
213 GetAllMostVisitedURLs(callback, false); | |
214 } | |
215 | |
216 // WARNING: this function may be invoked on any thread. | |
217 void TopSitesImpl::GetAllMostVisitedURLs( | |
218 const GetMostVisitedURLsCallback& callback, | |
219 bool include_forced_urls) { | |
198 MostVisitedURLList filtered_urls; | 220 MostVisitedURLList filtered_urls; |
199 { | 221 { |
200 base::AutoLock lock(lock_); | 222 base::AutoLock lock(lock_); |
201 if (!loaded_) { | 223 if (!loaded_) { |
202 // A request came in before we finished loading. Store the callback and | 224 // A request came in before we finished loading. Store the callback and |
203 // we'll run it on current thread when we finish loading. | 225 // we'll run it on current thread when we finish loading. |
204 pending_callbacks_.push_back( | 226 pending_callbacks_.push_back( |
205 base::Bind(&RunOrPostGetMostVisitedURLsCallback, | 227 base::Bind(&RunOrPostGetMostVisitedURLsCallback, |
206 base::MessageLoopProxy::current(), | 228 base::MessageLoopProxy::current(), |
229 include_forced_urls, | |
207 callback)); | 230 callback)); |
208 return; | 231 return; |
209 } | 232 } |
210 filtered_urls = thread_safe_cache_->top_sites(); | 233 if (include_forced_urls) { |
234 filtered_urls = thread_safe_cache_->top_sites(); | |
235 } else { | |
236 filtered_urls.assign(thread_safe_cache_->top_sites().begin() + | |
237 thread_safe_cache_->GetNbForcedURLs(), | |
238 thread_safe_cache_->top_sites().end()); | |
239 } | |
211 } | 240 } |
212 callback.Run(filtered_urls); | 241 callback.Run(filtered_urls); |
213 } | 242 } |
214 | 243 |
215 bool TopSitesImpl::GetPageThumbnail( | 244 bool TopSitesImpl::GetPageThumbnail( |
216 const GURL& url, | 245 const GURL& url, |
217 bool prefix_match, | 246 bool prefix_match, |
218 scoped_refptr<base::RefCountedMemory>* bytes) { | 247 scoped_refptr<base::RefCountedMemory>* bytes) { |
219 // WARNING: this may be invoked on any thread. | 248 // WARNING: this may be invoked on any thread. |
220 // Perform exact match. | 249 // Perform exact match. |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
366 // invoked Shutdown (this could happen if we have a pending request and | 395 // invoked Shutdown (this could happen if we have a pending request and |
367 // Shutdown is invoked). | 396 // Shutdown is invoked). |
368 history_consumer_.CancelAllRequests(); | 397 history_consumer_.CancelAllRequests(); |
369 backend_->Shutdown(); | 398 backend_->Shutdown(); |
370 } | 399 } |
371 | 400 |
372 // static | 401 // static |
373 void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list, | 402 void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list, |
374 const MostVisitedURLList& new_list, | 403 const MostVisitedURLList& new_list, |
375 TopSitesDelta* delta) { | 404 TopSitesDelta* delta) { |
405 | |
376 // Add all the old URLs for quick lookup. This maps URLs to the corresponding | 406 // Add all the old URLs for quick lookup. This maps URLs to the corresponding |
377 // index in the input. | 407 // index in the input. |
378 std::map<GURL, size_t> all_old_urls; | 408 std::map<GURL, size_t> all_old_urls; |
379 for (size_t i = 0; i < old_list.size(); i++) | 409 size_t nb_old_forced = 0; |
410 for (size_t i = 0; i < old_list.size(); i++) { | |
411 if (!old_list[i].last_forced_time.is_null()) | |
412 nb_old_forced++; | |
413 DCHECK(old_list[i].last_forced_time.is_null() || i < nb_old_forced) | |
414 << "Forced URLs must all appear before non-forced URLs."; | |
380 all_old_urls[old_list[i].url] = i; | 415 all_old_urls[old_list[i].url] = i; |
416 } | |
381 | 417 |
382 // Check all the URLs in the new set to see which ones are new or just moved. | 418 // Check all the URLs in the new set to see which ones are new or just moved. |
383 // When we find a match in the old set, we'll reset its index to our special | 419 // When we find a match in the old set, we'll reset its index to our special |
384 // marker. This allows us to quickly identify the deleted ones in a later | 420 // marker. This allows us to quickly identify the deleted ones in a later |
385 // pass. | 421 // pass. |
386 const size_t kAlreadyFoundMarker = static_cast<size_t>(-1); | 422 const size_t kAlreadyFoundMarker = static_cast<size_t>(-1); |
423 int rank = -1; // Forced URLs have a rank of -1. | |
387 for (size_t i = 0; i < new_list.size(); i++) { | 424 for (size_t i = 0; i < new_list.size(); i++) { |
425 // Increase the rank if we're going through forced URLs. This works because | |
426 // non-forced URLs all come after forced URLs. | |
427 if (new_list[i].last_forced_time.is_null()) | |
428 rank++; | |
429 DCHECK(new_list[i].last_forced_time.is_null() == (rank != -1)) | |
430 << "Forced URLs must all appear before non-forced URLs."; | |
388 std::map<GURL, size_t>::iterator found = all_old_urls.find(new_list[i].url); | 431 std::map<GURL, size_t>::iterator found = all_old_urls.find(new_list[i].url); |
389 if (found == all_old_urls.end()) { | 432 if (found == all_old_urls.end()) { |
390 MostVisitedURLWithRank added; | 433 MostVisitedURLWithRank added; |
391 added.url = new_list[i]; | 434 added.url = new_list[i]; |
392 added.rank = i; | 435 added.rank = rank; |
393 delta->added.push_back(added); | 436 delta->added.push_back(added); |
394 } else { | 437 } else { |
395 if (found->second != i) { | 438 DCHECK(found->second != kAlreadyFoundMarker) |
439 << "Same URL appears twice in the new list."; | |
440 int oldRank = found->second >= nb_old_forced ? | |
brettw
2013/11/08 23:14:58
Style: oldRank -> old_rank
beaudoin
2013/11/11 21:58:09
Sorry! :|
Done.
| |
441 found->second - nb_old_forced : -1; | |
442 if (oldRank != rank || | |
443 old_list[found->second].last_forced_time != | |
444 new_list[i].last_forced_time) { | |
396 MostVisitedURLWithRank moved; | 445 MostVisitedURLWithRank moved; |
397 moved.url = new_list[i]; | 446 moved.url = new_list[i]; |
398 moved.rank = i; | 447 moved.rank = rank; |
399 delta->moved.push_back(moved); | 448 delta->moved.push_back(moved); |
400 } | 449 } |
401 found->second = kAlreadyFoundMarker; | 450 found->second = kAlreadyFoundMarker; |
402 } | 451 } |
403 } | 452 } |
404 | 453 |
405 // Any member without the special marker in the all_old_urls list means that | 454 // Any member without the special marker in the all_old_urls list means that |
406 // there wasn't a "new" URL that mapped to it, so it was deleted. | 455 // there wasn't a "new" URL that mapped to it, so it was deleted. |
407 for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin(); | 456 for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin(); |
408 i != all_old_urls.end(); ++i) { | 457 i != all_old_urls.end(); ++i) { |
(...skipping 22 matching lines...) Expand all Loading... | |
431 } | 480 } |
432 | 481 |
433 bool TopSitesImpl::IsKnownURL(const GURL& url) { | 482 bool TopSitesImpl::IsKnownURL(const GURL& url) { |
434 return loaded_ && cache_->IsKnownURL(url); | 483 return loaded_ && cache_->IsKnownURL(url); |
435 } | 484 } |
436 | 485 |
437 const std::string& TopSitesImpl::GetCanonicalURLString(const GURL& url) const { | 486 const std::string& TopSitesImpl::GetCanonicalURLString(const GURL& url) const { |
438 return cache_->GetCanonicalURL(url).spec(); | 487 return cache_->GetCanonicalURL(url).spec(); |
439 } | 488 } |
440 | 489 |
441 bool TopSitesImpl::IsFull() { | 490 bool TopSitesImpl::IsNonForcedFull() { |
442 return loaded_ && cache_->top_sites().size() >= kTopSitesNumber; | 491 return loaded_ && cache_->GetNbNonForcedURLs() >= kNonForcedTopSitesNumber; |
492 } | |
493 | |
494 bool TopSitesImpl::IsForcedFull() { | |
495 return loaded_ && cache_->GetNbForcedURLs() >= kForcedTopSitesNumber; | |
443 } | 496 } |
444 | 497 |
445 TopSitesImpl::~TopSitesImpl() { | 498 TopSitesImpl::~TopSitesImpl() { |
446 } | 499 } |
447 | 500 |
448 bool TopSitesImpl::SetPageThumbnailNoDB( | 501 bool TopSitesImpl::SetPageThumbnailNoDB( |
449 const GURL& url, | 502 const GURL& url, |
450 const base::RefCountedMemory* thumbnail_data, | 503 const base::RefCountedMemory* thumbnail_data, |
451 const ThumbnailScore& score) { | 504 const ThumbnailScore& score) { |
452 // This should only be invoked when we know about the url. | 505 // This should only be invoked when we know about the url. |
(...skipping 27 matching lines...) Expand all Loading... | |
480 const base::RefCountedMemory* thumbnail, | 533 const base::RefCountedMemory* thumbnail, |
481 const ThumbnailScore& score) { | 534 const ThumbnailScore& score) { |
482 if (!SetPageThumbnailNoDB(url, thumbnail, score)) | 535 if (!SetPageThumbnailNoDB(url, thumbnail, score)) |
483 return false; | 536 return false; |
484 | 537 |
485 // Update the database. | 538 // Update the database. |
486 if (!cache_->IsKnownURL(url)) | 539 if (!cache_->IsKnownURL(url)) |
487 return false; | 540 return false; |
488 | 541 |
489 size_t index = cache_->GetURLIndex(url); | 542 size_t index = cache_->GetURLIndex(url); |
543 int url_rank = index - cache_->GetNbForcedURLs(); | |
490 const MostVisitedURL& most_visited = cache_->top_sites()[index]; | 544 const MostVisitedURL& most_visited = cache_->top_sites()[index]; |
491 backend_->SetPageThumbnail(most_visited, | 545 backend_->SetPageThumbnail(most_visited, |
492 index, | 546 url_rank < 0 ? -1 : url_rank, |
493 *(cache_->GetImage(most_visited.url))); | 547 *(cache_->GetImage(most_visited.url))); |
494 return true; | 548 return true; |
495 } | 549 } |
496 | 550 |
497 // static | 551 // static |
498 bool TopSitesImpl::EncodeBitmap(const gfx::Image& bitmap, | 552 bool TopSitesImpl::EncodeBitmap(const gfx::Image& bitmap, |
499 scoped_refptr<base::RefCountedBytes>* bytes) { | 553 scoped_refptr<base::RefCountedBytes>* bytes) { |
500 if (bitmap.IsEmpty()) | 554 if (bitmap.IsEmpty()) |
501 return false; | 555 return false; |
502 *bytes = new base::RefCountedBytes(); | 556 *bytes = new base::RefCountedBytes(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
559 url.redirects.push_back(url.url); | 613 url.redirects.push_back(url.url); |
560 url.title = l10n_util::GetStringUTF16(kPrepopulatedPages[i].title_id); | 614 url.title = l10n_util::GetStringUTF16(kPrepopulatedPages[i].title_id); |
561 } | 615 } |
562 return urls; | 616 return urls; |
563 } | 617 } |
564 | 618 |
565 bool TopSitesImpl::loaded() const { | 619 bool TopSitesImpl::loaded() const { |
566 return loaded_; | 620 return loaded_; |
567 } | 621 } |
568 | 622 |
569 bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls) { | 623 bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls, |
624 size_t nb_forced_urls) { | |
570 bool added = false; | 625 bool added = false; |
571 MostVisitedURLList prepopulate_urls = GetPrepopulatePages(); | 626 MostVisitedURLList prepopulate_urls = GetPrepopulatePages(); |
572 for (size_t i = 0; i < prepopulate_urls.size(); ++i) { | 627 for (size_t i = 0; i < prepopulate_urls.size(); ++i) { |
573 if (urls->size() < kTopSitesNumber && | 628 if (urls->size() - nb_forced_urls < kNonForcedTopSitesNumber && |
574 IndexOf(*urls, prepopulate_urls[i].url) == -1) { | 629 IndexOf(*urls, prepopulate_urls[i].url) == -1) { |
575 urls->push_back(prepopulate_urls[i]); | 630 urls->push_back(prepopulate_urls[i]); |
576 added = true; | 631 added = true; |
577 } | 632 } |
578 } | 633 } |
579 return added; | 634 return added; |
580 } | 635 } |
581 | 636 |
637 size_t TopSitesImpl::MergeCachedForcedURLs(MostVisitedURLList* new_list) { | |
638 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
639 // Add all the new URLs for quick lookup. Take that opportunity to count the | |
640 // number of forced URLs in |new_list|. | |
641 std::set<GURL> all_new_urls; | |
642 size_t nb_forced = 0; | |
643 for (size_t i = 0; i < new_list->size(); ++i) { | |
644 all_new_urls.insert((*new_list)[i].url); | |
645 if (!(*new_list)[i].last_forced_time.is_null()) | |
646 ++nb_forced; | |
647 } | |
648 | |
649 // Keep the forced URLs from |cache_| that are not found in |new_list|. | |
650 MostVisitedURLList filtered_forced_urls; | |
651 for (size_t i = 0; i < cache_->GetNbForcedURLs(); ++i) { | |
652 if (all_new_urls.find(cache_->top_sites()[i].url) == all_new_urls.end()) | |
653 filtered_forced_urls.push_back(cache_->top_sites()[i]); | |
654 } | |
655 nb_forced += filtered_forced_urls.size(); | |
656 | |
657 // Prepend forced URLs and sort. | |
658 new_list->insert(new_list->begin(), filtered_forced_urls.begin(), | |
659 filtered_forced_urls.end()); | |
660 std::inplace_merge( | |
661 new_list->begin(), new_list->begin() + filtered_forced_urls.size(), | |
662 new_list->begin() + nb_forced, ForcedURLComparator); | |
663 | |
664 // Drop older forced URLs if the list overflows. | |
brettw
2013/11/08 23:14:58
It might be worth mentioning somewhere (either her
beaudoin
2013/11/11 21:58:09
Done.
| |
665 if (nb_forced > kForcedTopSitesNumber) { | |
666 new_list->erase(new_list->begin(), | |
667 new_list->begin() + (nb_forced - kForcedTopSitesNumber)); | |
668 nb_forced = kForcedTopSitesNumber; | |
669 } | |
670 | |
671 return nb_forced; | |
672 } | |
673 | |
brettw
2013/11/08 23:14:58
Style nit: only one blank line here
beaudoin
2013/11/11 21:58:09
Done.
| |
674 | |
582 void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls, | 675 void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls, |
583 MostVisitedURLList* out) { | 676 MostVisitedURLList* out) { |
584 // Log the number of times ApplyBlacklist is called so we can compute the | 677 // Log the number of times ApplyBlacklist is called so we can compute the |
585 // average number of blacklisted items per user. | 678 // average number of blacklisted items per user. |
586 const DictionaryValue* blacklist = | 679 const DictionaryValue* blacklist = |
587 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); | 680 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); |
588 UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true); | 681 UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true); |
589 UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems", | 682 UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems", |
590 (blacklist ? blacklist->size() : 0)); | 683 (blacklist ? blacklist->size() : 0)); |
591 for (size_t i = 0; i < urls.size() && i < kTopSitesNumber; ++i) { | 684 size_t nb_non_forced_urls = 0; |
592 if (!IsBlacklisted(urls[i].url)) | 685 size_t nb_forced_urls = 0; |
686 for (size_t i = 0; i < urls.size(); ++i) { | |
687 if (!IsBlacklisted(urls[i].url)) { | |
688 if (urls[i].last_forced_time.is_null()) { | |
689 // Non-forced URL. | |
690 if (nb_non_forced_urls >= kNonForcedTopSitesNumber) | |
691 continue; | |
692 nb_non_forced_urls++; | |
693 } else { | |
694 // Forced URL. | |
695 if (nb_forced_urls >= kForcedTopSitesNumber) | |
696 continue; | |
697 nb_forced_urls++; | |
698 } | |
593 out->push_back(urls[i]); | 699 out->push_back(urls[i]); |
700 } | |
594 } | 701 } |
595 } | 702 } |
596 | 703 |
597 std::string TopSitesImpl::GetURLHash(const GURL& url) { | 704 std::string TopSitesImpl::GetURLHash(const GURL& url) { |
598 // We don't use canonical URLs here to be able to blacklist only one of | 705 // We don't use canonical URLs here to be able to blacklist only one of |
599 // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. | 706 // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. |
600 return base::MD5String(url.spec()); | 707 return base::MD5String(url.spec()); |
601 } | 708 } |
602 | 709 |
603 base::TimeDelta TopSitesImpl::GetUpdateDelay() { | 710 base::TimeDelta TopSitesImpl::GetUpdateDelay() { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
638 new_top_sites.erase(new_top_sites.begin() + *i); | 745 new_top_sites.erase(new_top_sites.begin() + *i); |
639 } | 746 } |
640 SetTopSites(new_top_sites); | 747 SetTopSites(new_top_sites); |
641 } | 748 } |
642 StartQueryForMostVisited(); | 749 StartQueryForMostVisited(); |
643 } else if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) { | 750 } else if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) { |
644 NavigationController* controller = | 751 NavigationController* controller = |
645 content::Source<NavigationController>(source).ptr(); | 752 content::Source<NavigationController>(source).ptr(); |
646 Profile* profile = Profile::FromBrowserContext( | 753 Profile* profile = Profile::FromBrowserContext( |
647 controller->GetWebContents()->GetBrowserContext()); | 754 controller->GetWebContents()->GetBrowserContext()); |
648 if (profile == profile_ && !IsFull()) { | 755 if (profile == profile_ && !IsNonForcedFull()) { |
649 content::LoadCommittedDetails* load_details = | 756 content::LoadCommittedDetails* load_details = |
650 content::Details<content::LoadCommittedDetails>(details).ptr(); | 757 content::Details<content::LoadCommittedDetails>(details).ptr(); |
651 if (!load_details) | 758 if (!load_details) |
652 return; | 759 return; |
653 const GURL& url = load_details->entry->GetURL(); | 760 const GURL& url = load_details->entry->GetURL(); |
654 if (!cache_->IsKnownURL(url) && HistoryService::CanAddURL(url)) { | 761 if (!cache_->IsKnownURL(url) && HistoryService::CanAddURL(url)) { |
655 // To avoid slamming history we throttle requests when the url updates. | 762 // To avoid slamming history we throttle requests when the url updates. |
656 // To do otherwise negatively impacts perf tests. | 763 // To do otherwise negatively impacts perf tests. |
657 RestartQueryForTopSitesTimer(GetUpdateDelay()); | 764 RestartQueryForTopSitesTimer(GetUpdateDelay()); |
658 } | 765 } |
659 } | 766 } |
660 } | 767 } |
661 } | 768 } |
662 | 769 |
663 void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites) { | 770 void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites) { |
664 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 771 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
665 | 772 |
666 MostVisitedURLList top_sites(new_top_sites); | 773 MostVisitedURLList top_sites(new_top_sites); |
667 AddPrepopulatedPages(&top_sites); | 774 size_t nb_forced_urls = MergeCachedForcedURLs(&top_sites); |
775 AddPrepopulatedPages(&top_sites, nb_forced_urls); | |
668 | 776 |
669 TopSitesDelta delta; | 777 TopSitesDelta delta; |
670 DiffMostVisited(cache_->top_sites(), top_sites, &delta); | 778 DiffMostVisited(cache_->top_sites(), top_sites, &delta); |
671 if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty()) { | 779 if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty()) { |
672 backend_->UpdateTopSites(delta); | 780 backend_->UpdateTopSites(delta); |
673 } | 781 } |
674 | 782 |
675 last_num_urls_changed_ = delta.added.size() + delta.moved.size(); | 783 last_num_urls_changed_ = delta.added.size() + delta.moved.size(); |
676 | 784 |
677 // We always do the following steps (setting top sites in cache, and resetting | 785 // We always do the following steps (setting top sites in cache, and resetting |
(...skipping 13 matching lines...) Expand all Loading... | |
691 if (canonical_url == cache_->GetCanonicalURL(it->first)) { | 799 if (canonical_url == cache_->GetCanonicalURL(it->first)) { |
692 SetPageThumbnailEncoded( | 800 SetPageThumbnailEncoded( |
693 mv.url, it->second.thumbnail.get(), it->second.thumbnail_score); | 801 mv.url, it->second.thumbnail.get(), it->second.thumbnail_score); |
694 temp_images_.erase(it); | 802 temp_images_.erase(it); |
695 break; | 803 break; |
696 } | 804 } |
697 } | 805 } |
698 } | 806 } |
699 } | 807 } |
700 | 808 |
701 if (top_sites.size() >= kTopSitesNumber) | 809 if (top_sites.size() - nb_forced_urls >= kNonForcedTopSitesNumber) |
702 temp_images_.clear(); | 810 temp_images_.clear(); |
703 | 811 |
704 ResetThreadSafeCache(); | 812 ResetThreadSafeCache(); |
705 ResetThreadSafeImageCache(); | 813 ResetThreadSafeImageCache(); |
706 NotifyTopSitesChanged(); | 814 NotifyTopSitesChanged(); |
707 | 815 |
708 // Restart the timer that queries history for top sites. This is done to | 816 // Restart the timer that queries history for top sites. This is done to |
709 // ensure we stay in sync with history. | 817 // ensure we stay in sync with history. |
710 RestartQueryForTopSitesTimer(GetUpdateDelay()); | 818 RestartQueryForTopSitesTimer(GetUpdateDelay()); |
711 } | 819 } |
712 | 820 |
713 int TopSitesImpl::num_results_to_request_from_history() const { | 821 int TopSitesImpl::num_results_to_request_from_history() const { |
714 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 822 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
715 | 823 |
716 const DictionaryValue* blacklist = | 824 const DictionaryValue* blacklist = |
717 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); | 825 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); |
718 return kTopSitesNumber + (blacklist ? blacklist->size() : 0); | 826 return kNonForcedTopSitesNumber + (blacklist ? blacklist->size() : 0); |
719 } | 827 } |
720 | 828 |
721 void TopSitesImpl::MoveStateToLoaded() { | 829 void TopSitesImpl::MoveStateToLoaded() { |
722 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 830 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
723 | 831 |
724 MostVisitedURLList filtered_urls; | 832 MostVisitedURLList filtered_urls_all; |
833 MostVisitedURLList filtered_urls_nonforced; | |
725 PendingCallbacks pending_callbacks; | 834 PendingCallbacks pending_callbacks; |
726 { | 835 { |
727 base::AutoLock lock(lock_); | 836 base::AutoLock lock(lock_); |
728 | 837 |
729 if (loaded_) | 838 if (loaded_) |
730 return; // Don't do anything if we're already loaded. | 839 return; // Don't do anything if we're already loaded. |
731 loaded_ = true; | 840 loaded_ = true; |
732 | 841 |
733 // Now that we're loaded we can service the queued up callbacks. Copy them | 842 // Now that we're loaded we can service the queued up callbacks. Copy them |
734 // here and service them outside the lock. | 843 // here and service them outside the lock. |
735 if (!pending_callbacks_.empty()) { | 844 if (!pending_callbacks_.empty()) { |
736 filtered_urls = thread_safe_cache_->top_sites(); | 845 // We always filter out forced URLs because callers of GetMostVisitedURLs |
846 // are not interested in them. | |
847 filtered_urls_all = thread_safe_cache_->top_sites(); | |
848 filtered_urls_nonforced.assign(thread_safe_cache_->top_sites().begin() + | |
849 thread_safe_cache_->GetNbForcedURLs(), | |
850 thread_safe_cache_->top_sites().end()); | |
737 pending_callbacks.swap(pending_callbacks_); | 851 pending_callbacks.swap(pending_callbacks_); |
738 } | 852 } |
739 } | 853 } |
740 | 854 |
741 for (size_t i = 0; i < pending_callbacks.size(); i++) | 855 for (size_t i = 0; i < pending_callbacks.size(); i++) |
742 pending_callbacks[i].Run(filtered_urls); | 856 pending_callbacks[i].Run(filtered_urls_all, filtered_urls_nonforced); |
743 | 857 |
744 content::NotificationService::current()->Notify( | 858 content::NotificationService::current()->Notify( |
745 chrome::NOTIFICATION_TOP_SITES_LOADED, | 859 chrome::NOTIFICATION_TOP_SITES_LOADED, |
746 content::Source<Profile>(profile_), | 860 content::Source<Profile>(profile_), |
747 content::Details<TopSites>(this)); | 861 content::Details<TopSites>(this)); |
748 } | 862 } |
749 | 863 |
750 void TopSitesImpl::ResetThreadSafeCache() { | 864 void TopSitesImpl::ResetThreadSafeCache() { |
751 base::AutoLock lock(lock_); | 865 base::AutoLock lock(lock_); |
752 MostVisitedURLList cached; | 866 MostVisitedURLList cached; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
802 SetTopSites(pages); | 916 SetTopSites(pages); |
803 | 917 |
804 // Used only in testing. | 918 // Used only in testing. |
805 content::NotificationService::current()->Notify( | 919 content::NotificationService::current()->Notify( |
806 chrome::NOTIFICATION_TOP_SITES_UPDATED, | 920 chrome::NOTIFICATION_TOP_SITES_UPDATED, |
807 content::Source<TopSitesImpl>(this), | 921 content::Source<TopSitesImpl>(this), |
808 content::Details<CancelableRequestProvider::Handle>(&handle)); | 922 content::Details<CancelableRequestProvider::Handle>(&handle)); |
809 } | 923 } |
810 | 924 |
811 } // namespace history | 925 } // namespace history |
OLD | NEW |