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; |
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 bool include_forced_urls) { |
198 MostVisitedURLList filtered_urls; | 214 MostVisitedURLList filtered_urls; |
199 { | 215 { |
200 base::AutoLock lock(lock_); | 216 base::AutoLock lock(lock_); |
201 if (!loaded_) { | 217 if (!loaded_) { |
202 // A request came in before we finished loading. Store the callback and | 218 // A request came in before we finished loading. Store the callback and |
203 // we'll run it on current thread when we finish loading. | 219 // we'll run it on current thread when we finish loading. |
204 pending_callbacks_.push_back( | 220 pending_callbacks_.push_back( |
205 base::Bind(&RunOrPostGetMostVisitedURLsCallback, | 221 base::Bind(&RunOrPostGetMostVisitedURLsCallback, |
206 base::MessageLoopProxy::current(), | 222 base::MessageLoopProxy::current(), |
| 223 include_forced_urls, |
207 callback)); | 224 callback)); |
208 return; | 225 return; |
209 } | 226 } |
210 filtered_urls = thread_safe_cache_->top_sites(); | 227 if (include_forced_urls) { |
| 228 filtered_urls = thread_safe_cache_->top_sites(); |
| 229 } else { |
| 230 filtered_urls.assign(thread_safe_cache_->top_sites().begin() + |
| 231 thread_safe_cache_->GetNumForcedURLs(), |
| 232 thread_safe_cache_->top_sites().end()); |
| 233 } |
211 } | 234 } |
212 callback.Run(filtered_urls); | 235 callback.Run(filtered_urls); |
213 } | 236 } |
214 | 237 |
215 bool TopSitesImpl::GetPageThumbnail( | 238 bool TopSitesImpl::GetPageThumbnail( |
216 const GURL& url, | 239 const GURL& url, |
217 bool prefix_match, | 240 bool prefix_match, |
218 scoped_refptr<base::RefCountedMemory>* bytes) { | 241 scoped_refptr<base::RefCountedMemory>* bytes) { |
219 // WARNING: this may be invoked on any thread. | 242 // WARNING: this may be invoked on any thread. |
220 // Perform exact match. | 243 // Perform exact match. |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 // invoked Shutdown (this could happen if we have a pending request and | 382 // invoked Shutdown (this could happen if we have a pending request and |
360 // Shutdown is invoked). | 383 // Shutdown is invoked). |
361 history_consumer_.CancelAllRequests(); | 384 history_consumer_.CancelAllRequests(); |
362 backend_->Shutdown(); | 385 backend_->Shutdown(); |
363 } | 386 } |
364 | 387 |
365 // static | 388 // static |
366 void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list, | 389 void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list, |
367 const MostVisitedURLList& new_list, | 390 const MostVisitedURLList& new_list, |
368 TopSitesDelta* delta) { | 391 TopSitesDelta* delta) { |
| 392 |
369 // Add all the old URLs for quick lookup. This maps URLs to the corresponding | 393 // Add all the old URLs for quick lookup. This maps URLs to the corresponding |
370 // index in the input. | 394 // index in the input. |
371 std::map<GURL, size_t> all_old_urls; | 395 std::map<GURL, size_t> all_old_urls; |
372 for (size_t i = 0; i < old_list.size(); i++) | 396 size_t num_old_forced = 0; |
| 397 for (size_t i = 0; i < old_list.size(); i++) { |
| 398 if (!old_list[i].last_forced_time.is_null()) |
| 399 num_old_forced++; |
| 400 DCHECK(old_list[i].last_forced_time.is_null() || i < num_old_forced) |
| 401 << "Forced URLs must all appear before non-forced URLs."; |
373 all_old_urls[old_list[i].url] = i; | 402 all_old_urls[old_list[i].url] = i; |
| 403 } |
374 | 404 |
375 // Check all the URLs in the new set to see which ones are new or just moved. | 405 // Check all the URLs in the new set to see which ones are new or just moved. |
376 // When we find a match in the old set, we'll reset its index to our special | 406 // When we find a match in the old set, we'll reset its index to our special |
377 // marker. This allows us to quickly identify the deleted ones in a later | 407 // marker. This allows us to quickly identify the deleted ones in a later |
378 // pass. | 408 // pass. |
379 const size_t kAlreadyFoundMarker = static_cast<size_t>(-1); | 409 const size_t kAlreadyFoundMarker = static_cast<size_t>(-1); |
| 410 int rank = -1; // Forced URLs have a rank of -1. |
380 for (size_t i = 0; i < new_list.size(); i++) { | 411 for (size_t i = 0; i < new_list.size(); i++) { |
| 412 // Increase the rank if we're going through forced URLs. This works because |
| 413 // non-forced URLs all come after forced URLs. |
| 414 if (new_list[i].last_forced_time.is_null()) |
| 415 rank++; |
| 416 DCHECK(new_list[i].last_forced_time.is_null() == (rank != -1)) |
| 417 << "Forced URLs must all appear before non-forced URLs."; |
381 std::map<GURL, size_t>::iterator found = all_old_urls.find(new_list[i].url); | 418 std::map<GURL, size_t>::iterator found = all_old_urls.find(new_list[i].url); |
382 if (found == all_old_urls.end()) { | 419 if (found == all_old_urls.end()) { |
383 MostVisitedURLWithRank added; | 420 MostVisitedURLWithRank added; |
384 added.url = new_list[i]; | 421 added.url = new_list[i]; |
385 added.rank = i; | 422 added.rank = rank; |
386 delta->added.push_back(added); | 423 delta->added.push_back(added); |
387 } else { | 424 } else { |
388 if (found->second != i) { | 425 DCHECK(found->second != kAlreadyFoundMarker) |
| 426 << "Same URL appears twice in the new list."; |
| 427 int old_rank = found->second >= num_old_forced ? |
| 428 found->second - num_old_forced : -1; |
| 429 if (old_rank != rank || |
| 430 old_list[found->second].last_forced_time != |
| 431 new_list[i].last_forced_time) { |
389 MostVisitedURLWithRank moved; | 432 MostVisitedURLWithRank moved; |
390 moved.url = new_list[i]; | 433 moved.url = new_list[i]; |
391 moved.rank = i; | 434 moved.rank = rank; |
392 delta->moved.push_back(moved); | 435 delta->moved.push_back(moved); |
393 } | 436 } |
394 found->second = kAlreadyFoundMarker; | 437 found->second = kAlreadyFoundMarker; |
395 } | 438 } |
396 } | 439 } |
397 | 440 |
398 // Any member without the special marker in the all_old_urls list means that | 441 // Any member without the special marker in the all_old_urls list means that |
399 // there wasn't a "new" URL that mapped to it, so it was deleted. | 442 // there wasn't a "new" URL that mapped to it, so it was deleted. |
400 for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin(); | 443 for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin(); |
401 i != all_old_urls.end(); ++i) { | 444 i != all_old_urls.end(); ++i) { |
(...skipping 22 matching lines...) Expand all Loading... |
424 } | 467 } |
425 | 468 |
426 bool TopSitesImpl::IsKnownURL(const GURL& url) { | 469 bool TopSitesImpl::IsKnownURL(const GURL& url) { |
427 return loaded_ && cache_->IsKnownURL(url); | 470 return loaded_ && cache_->IsKnownURL(url); |
428 } | 471 } |
429 | 472 |
430 const std::string& TopSitesImpl::GetCanonicalURLString(const GURL& url) const { | 473 const std::string& TopSitesImpl::GetCanonicalURLString(const GURL& url) const { |
431 return cache_->GetCanonicalURL(url).spec(); | 474 return cache_->GetCanonicalURL(url).spec(); |
432 } | 475 } |
433 | 476 |
434 bool TopSitesImpl::IsFull() { | 477 bool TopSitesImpl::IsNonForcedFull() { |
435 return loaded_ && cache_->top_sites().size() >= kTopSitesNumber; | 478 return loaded_ && cache_->GetNumNonForcedURLs() >= kNonForcedTopSitesNumber; |
| 479 } |
| 480 |
| 481 bool TopSitesImpl::IsForcedFull() { |
| 482 return loaded_ && cache_->GetNumForcedURLs() >= kForcedTopSitesNumber; |
436 } | 483 } |
437 | 484 |
438 TopSitesImpl::~TopSitesImpl() { | 485 TopSitesImpl::~TopSitesImpl() { |
439 } | 486 } |
440 | 487 |
441 bool TopSitesImpl::SetPageThumbnailNoDB( | 488 bool TopSitesImpl::SetPageThumbnailNoDB( |
442 const GURL& url, | 489 const GURL& url, |
443 const base::RefCountedMemory* thumbnail_data, | 490 const base::RefCountedMemory* thumbnail_data, |
444 const ThumbnailScore& score) { | 491 const ThumbnailScore& score) { |
445 // This should only be invoked when we know about the url. | 492 // This should only be invoked when we know about the url. |
(...skipping 27 matching lines...) Expand all Loading... |
473 const base::RefCountedMemory* thumbnail, | 520 const base::RefCountedMemory* thumbnail, |
474 const ThumbnailScore& score) { | 521 const ThumbnailScore& score) { |
475 if (!SetPageThumbnailNoDB(url, thumbnail, score)) | 522 if (!SetPageThumbnailNoDB(url, thumbnail, score)) |
476 return false; | 523 return false; |
477 | 524 |
478 // Update the database. | 525 // Update the database. |
479 if (!cache_->IsKnownURL(url)) | 526 if (!cache_->IsKnownURL(url)) |
480 return false; | 527 return false; |
481 | 528 |
482 size_t index = cache_->GetURLIndex(url); | 529 size_t index = cache_->GetURLIndex(url); |
| 530 int url_rank = index - cache_->GetNumForcedURLs(); |
483 const MostVisitedURL& most_visited = cache_->top_sites()[index]; | 531 const MostVisitedURL& most_visited = cache_->top_sites()[index]; |
484 backend_->SetPageThumbnail(most_visited, | 532 backend_->SetPageThumbnail(most_visited, |
485 index, | 533 url_rank < 0 ? -1 : url_rank, |
486 *(cache_->GetImage(most_visited.url))); | 534 *(cache_->GetImage(most_visited.url))); |
487 return true; | 535 return true; |
488 } | 536 } |
489 | 537 |
490 // static | 538 // static |
491 bool TopSitesImpl::EncodeBitmap(const gfx::Image& bitmap, | 539 bool TopSitesImpl::EncodeBitmap(const gfx::Image& bitmap, |
492 scoped_refptr<base::RefCountedBytes>* bytes) { | 540 scoped_refptr<base::RefCountedBytes>* bytes) { |
493 if (bitmap.IsEmpty()) | 541 if (bitmap.IsEmpty()) |
494 return false; | 542 return false; |
495 *bytes = new base::RefCountedBytes(); | 543 *bytes = new base::RefCountedBytes(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 url.redirects.push_back(url.url); | 600 url.redirects.push_back(url.url); |
553 url.title = l10n_util::GetStringUTF16(kPrepopulatedPages[i].title_id); | 601 url.title = l10n_util::GetStringUTF16(kPrepopulatedPages[i].title_id); |
554 } | 602 } |
555 return urls; | 603 return urls; |
556 } | 604 } |
557 | 605 |
558 bool TopSitesImpl::loaded() const { | 606 bool TopSitesImpl::loaded() const { |
559 return loaded_; | 607 return loaded_; |
560 } | 608 } |
561 | 609 |
562 bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls) { | 610 bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls, |
| 611 size_t num_forced_urls) { |
563 bool added = false; | 612 bool added = false; |
564 MostVisitedURLList prepopulate_urls = GetPrepopulatePages(); | 613 MostVisitedURLList prepopulate_urls = GetPrepopulatePages(); |
565 for (size_t i = 0; i < prepopulate_urls.size(); ++i) { | 614 for (size_t i = 0; i < prepopulate_urls.size(); ++i) { |
566 if (urls->size() < kTopSitesNumber && | 615 if (urls->size() - num_forced_urls < kNonForcedTopSitesNumber && |
567 IndexOf(*urls, prepopulate_urls[i].url) == -1) { | 616 IndexOf(*urls, prepopulate_urls[i].url) == -1) { |
568 urls->push_back(prepopulate_urls[i]); | 617 urls->push_back(prepopulate_urls[i]); |
569 added = true; | 618 added = true; |
570 } | 619 } |
571 } | 620 } |
572 return added; | 621 return added; |
573 } | 622 } |
574 | 623 |
| 624 size_t TopSitesImpl::MergeCachedForcedURLs(MostVisitedURLList* new_list) { |
| 625 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 626 // Add all the new URLs for quick lookup. Take that opportunity to count the |
| 627 // number of forced URLs in |new_list|. |
| 628 std::set<GURL> all_new_urls; |
| 629 size_t num_forced = 0; |
| 630 for (size_t i = 0; i < new_list->size(); ++i) { |
| 631 all_new_urls.insert((*new_list)[i].url); |
| 632 if (!(*new_list)[i].last_forced_time.is_null()) |
| 633 ++num_forced; |
| 634 } |
| 635 |
| 636 // Keep the forced URLs from |cache_| that are not found in |new_list|. |
| 637 MostVisitedURLList filtered_forced_urls; |
| 638 for (size_t i = 0; i < cache_->GetNumForcedURLs(); ++i) { |
| 639 if (all_new_urls.find(cache_->top_sites()[i].url) == all_new_urls.end()) |
| 640 filtered_forced_urls.push_back(cache_->top_sites()[i]); |
| 641 } |
| 642 num_forced += filtered_forced_urls.size(); |
| 643 |
| 644 // Prepend forced URLs and sort in order of ascending |last_forced_time|. |
| 645 new_list->insert(new_list->begin(), filtered_forced_urls.begin(), |
| 646 filtered_forced_urls.end()); |
| 647 std::inplace_merge( |
| 648 new_list->begin(), new_list->begin() + filtered_forced_urls.size(), |
| 649 new_list->begin() + num_forced, ForcedURLComparator); |
| 650 |
| 651 // Drop older forced URLs if the list overflows. Since forced URLs are always |
| 652 // sort in increasing order of |last_forced_time|, drop the first ones. |
| 653 if (num_forced > kForcedTopSitesNumber) { |
| 654 new_list->erase(new_list->begin(), |
| 655 new_list->begin() + (num_forced - kForcedTopSitesNumber)); |
| 656 num_forced = kForcedTopSitesNumber; |
| 657 } |
| 658 |
| 659 return num_forced; |
| 660 } |
| 661 |
575 void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls, | 662 void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls, |
576 MostVisitedURLList* out) { | 663 MostVisitedURLList* out) { |
577 // Log the number of times ApplyBlacklist is called so we can compute the | 664 // Log the number of times ApplyBlacklist is called so we can compute the |
578 // average number of blacklisted items per user. | 665 // average number of blacklisted items per user. |
579 const DictionaryValue* blacklist = | 666 const DictionaryValue* blacklist = |
580 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); | 667 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); |
581 UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true); | 668 UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true); |
582 UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems", | 669 UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems", |
583 (blacklist ? blacklist->size() : 0)); | 670 (blacklist ? blacklist->size() : 0)); |
584 for (size_t i = 0; i < urls.size() && i < kTopSitesNumber; ++i) { | 671 size_t num_non_forced_urls = 0; |
585 if (!IsBlacklisted(urls[i].url)) | 672 size_t num_forced_urls = 0; |
| 673 for (size_t i = 0; i < urls.size(); ++i) { |
| 674 if (!IsBlacklisted(urls[i].url)) { |
| 675 if (urls[i].last_forced_time.is_null()) { |
| 676 // Non-forced URL. |
| 677 if (num_non_forced_urls >= kNonForcedTopSitesNumber) |
| 678 continue; |
| 679 num_non_forced_urls++; |
| 680 } else { |
| 681 // Forced URL. |
| 682 if (num_forced_urls >= kForcedTopSitesNumber) |
| 683 continue; |
| 684 num_forced_urls++; |
| 685 } |
586 out->push_back(urls[i]); | 686 out->push_back(urls[i]); |
| 687 } |
587 } | 688 } |
588 } | 689 } |
589 | 690 |
590 std::string TopSitesImpl::GetURLHash(const GURL& url) { | 691 std::string TopSitesImpl::GetURLHash(const GURL& url) { |
591 // We don't use canonical URLs here to be able to blacklist only one of | 692 // We don't use canonical URLs here to be able to blacklist only one of |
592 // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. | 693 // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. |
593 return base::MD5String(url.spec()); | 694 return base::MD5String(url.spec()); |
594 } | 695 } |
595 | 696 |
596 base::TimeDelta TopSitesImpl::GetUpdateDelay() { | 697 base::TimeDelta TopSitesImpl::GetUpdateDelay() { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 new_top_sites.erase(new_top_sites.begin() + *i); | 732 new_top_sites.erase(new_top_sites.begin() + *i); |
632 } | 733 } |
633 SetTopSites(new_top_sites); | 734 SetTopSites(new_top_sites); |
634 } | 735 } |
635 StartQueryForMostVisited(); | 736 StartQueryForMostVisited(); |
636 } else if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) { | 737 } else if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) { |
637 NavigationController* controller = | 738 NavigationController* controller = |
638 content::Source<NavigationController>(source).ptr(); | 739 content::Source<NavigationController>(source).ptr(); |
639 Profile* profile = Profile::FromBrowserContext( | 740 Profile* profile = Profile::FromBrowserContext( |
640 controller->GetWebContents()->GetBrowserContext()); | 741 controller->GetWebContents()->GetBrowserContext()); |
641 if (profile == profile_ && !IsFull()) { | 742 if (profile == profile_ && !IsNonForcedFull()) { |
642 content::LoadCommittedDetails* load_details = | 743 content::LoadCommittedDetails* load_details = |
643 content::Details<content::LoadCommittedDetails>(details).ptr(); | 744 content::Details<content::LoadCommittedDetails>(details).ptr(); |
644 if (!load_details) | 745 if (!load_details) |
645 return; | 746 return; |
646 const GURL& url = load_details->entry->GetURL(); | 747 const GURL& url = load_details->entry->GetURL(); |
647 if (!cache_->IsKnownURL(url) && HistoryService::CanAddURL(url)) { | 748 if (!cache_->IsKnownURL(url) && HistoryService::CanAddURL(url)) { |
648 // To avoid slamming history we throttle requests when the url updates. | 749 // To avoid slamming history we throttle requests when the url updates. |
649 // To do otherwise negatively impacts perf tests. | 750 // To do otherwise negatively impacts perf tests. |
650 RestartQueryForTopSitesTimer(GetUpdateDelay()); | 751 RestartQueryForTopSitesTimer(GetUpdateDelay()); |
651 } | 752 } |
652 } | 753 } |
653 } | 754 } |
654 } | 755 } |
655 | 756 |
656 void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites) { | 757 void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites) { |
657 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 758 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
658 | 759 |
659 MostVisitedURLList top_sites(new_top_sites); | 760 MostVisitedURLList top_sites(new_top_sites); |
660 AddPrepopulatedPages(&top_sites); | 761 size_t num_forced_urls = MergeCachedForcedURLs(&top_sites); |
| 762 AddPrepopulatedPages(&top_sites, num_forced_urls); |
661 | 763 |
662 TopSitesDelta delta; | 764 TopSitesDelta delta; |
663 DiffMostVisited(cache_->top_sites(), top_sites, &delta); | 765 DiffMostVisited(cache_->top_sites(), top_sites, &delta); |
664 if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty()) { | 766 if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty()) { |
665 backend_->UpdateTopSites(delta); | 767 backend_->UpdateTopSites(delta); |
666 } | 768 } |
667 | 769 |
668 last_num_urls_changed_ = delta.added.size() + delta.moved.size(); | 770 last_num_urls_changed_ = delta.added.size() + delta.moved.size(); |
669 | 771 |
670 // We always do the following steps (setting top sites in cache, and resetting | 772 // We always do the following steps (setting top sites in cache, and resetting |
(...skipping 13 matching lines...) Expand all Loading... |
684 if (canonical_url == cache_->GetCanonicalURL(it->first)) { | 786 if (canonical_url == cache_->GetCanonicalURL(it->first)) { |
685 SetPageThumbnailEncoded( | 787 SetPageThumbnailEncoded( |
686 mv.url, it->second.thumbnail.get(), it->second.thumbnail_score); | 788 mv.url, it->second.thumbnail.get(), it->second.thumbnail_score); |
687 temp_images_.erase(it); | 789 temp_images_.erase(it); |
688 break; | 790 break; |
689 } | 791 } |
690 } | 792 } |
691 } | 793 } |
692 } | 794 } |
693 | 795 |
694 if (top_sites.size() >= kTopSitesNumber) | 796 if (top_sites.size() - num_forced_urls >= kNonForcedTopSitesNumber) |
695 temp_images_.clear(); | 797 temp_images_.clear(); |
696 | 798 |
697 ResetThreadSafeCache(); | 799 ResetThreadSafeCache(); |
698 ResetThreadSafeImageCache(); | 800 ResetThreadSafeImageCache(); |
699 NotifyTopSitesChanged(); | 801 NotifyTopSitesChanged(); |
700 | 802 |
701 // Restart the timer that queries history for top sites. This is done to | 803 // Restart the timer that queries history for top sites. This is done to |
702 // ensure we stay in sync with history. | 804 // ensure we stay in sync with history. |
703 RestartQueryForTopSitesTimer(GetUpdateDelay()); | 805 RestartQueryForTopSitesTimer(GetUpdateDelay()); |
704 } | 806 } |
705 | 807 |
706 int TopSitesImpl::num_results_to_request_from_history() const { | 808 int TopSitesImpl::num_results_to_request_from_history() const { |
707 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 809 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
708 | 810 |
709 const DictionaryValue* blacklist = | 811 const DictionaryValue* blacklist = |
710 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); | 812 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); |
711 return kTopSitesNumber + (blacklist ? blacklist->size() : 0); | 813 return kNonForcedTopSitesNumber + (blacklist ? blacklist->size() : 0); |
712 } | 814 } |
713 | 815 |
714 void TopSitesImpl::MoveStateToLoaded() { | 816 void TopSitesImpl::MoveStateToLoaded() { |
715 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 817 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
716 | 818 |
717 MostVisitedURLList filtered_urls; | 819 MostVisitedURLList filtered_urls_all; |
| 820 MostVisitedURLList filtered_urls_nonforced; |
718 PendingCallbacks pending_callbacks; | 821 PendingCallbacks pending_callbacks; |
719 { | 822 { |
720 base::AutoLock lock(lock_); | 823 base::AutoLock lock(lock_); |
721 | 824 |
722 if (loaded_) | 825 if (loaded_) |
723 return; // Don't do anything if we're already loaded. | 826 return; // Don't do anything if we're already loaded. |
724 loaded_ = true; | 827 loaded_ = true; |
725 | 828 |
726 // Now that we're loaded we can service the queued up callbacks. Copy them | 829 // Now that we're loaded we can service the queued up callbacks. Copy them |
727 // here and service them outside the lock. | 830 // here and service them outside the lock. |
728 if (!pending_callbacks_.empty()) { | 831 if (!pending_callbacks_.empty()) { |
729 filtered_urls = thread_safe_cache_->top_sites(); | 832 // We always filter out forced URLs because callers of GetMostVisitedURLs |
| 833 // are not interested in them. |
| 834 filtered_urls_all = thread_safe_cache_->top_sites(); |
| 835 filtered_urls_nonforced.assign(thread_safe_cache_->top_sites().begin() + |
| 836 thread_safe_cache_->GetNumForcedURLs(), |
| 837 thread_safe_cache_->top_sites().end()); |
730 pending_callbacks.swap(pending_callbacks_); | 838 pending_callbacks.swap(pending_callbacks_); |
731 } | 839 } |
732 } | 840 } |
733 | 841 |
734 for (size_t i = 0; i < pending_callbacks.size(); i++) | 842 for (size_t i = 0; i < pending_callbacks.size(); i++) |
735 pending_callbacks[i].Run(filtered_urls); | 843 pending_callbacks[i].Run(filtered_urls_all, filtered_urls_nonforced); |
736 | 844 |
737 content::NotificationService::current()->Notify( | 845 content::NotificationService::current()->Notify( |
738 chrome::NOTIFICATION_TOP_SITES_LOADED, | 846 chrome::NOTIFICATION_TOP_SITES_LOADED, |
739 content::Source<Profile>(profile_), | 847 content::Source<Profile>(profile_), |
740 content::Details<TopSites>(this)); | 848 content::Details<TopSites>(this)); |
741 } | 849 } |
742 | 850 |
743 void TopSitesImpl::ResetThreadSafeCache() { | 851 void TopSitesImpl::ResetThreadSafeCache() { |
744 base::AutoLock lock(lock_); | 852 base::AutoLock lock(lock_); |
745 MostVisitedURLList cached; | 853 MostVisitedURLList cached; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 SetTopSites(pages); | 903 SetTopSites(pages); |
796 | 904 |
797 // Used only in testing. | 905 // Used only in testing. |
798 content::NotificationService::current()->Notify( | 906 content::NotificationService::current()->Notify( |
799 chrome::NOTIFICATION_TOP_SITES_UPDATED, | 907 chrome::NOTIFICATION_TOP_SITES_UPDATED, |
800 content::Source<TopSitesImpl>(this), | 908 content::Source<TopSitesImpl>(this), |
801 content::Details<CancelableRequestProvider::Handle>(&handle)); | 909 content::Details<CancelableRequestProvider::Handle>(&handle)); |
802 } | 910 } |
803 | 911 |
804 } // namespace history | 912 } // namespace history |
OLD | NEW |