| 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 |