Chromium Code Reviews| 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" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/md5.h" | 13 #include "base/md5.h" |
| 14 #include "base/memory/ref_counted_memory.h" | 14 #include "base/memory/ref_counted_memory.h" |
| 15 #include "base/message_loop/message_loop_proxy.h" | 15 #include "base/message_loop/message_loop_proxy.h" |
| 16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
| 17 #include "base/prefs/pref_service.h" | 17 #include "base/prefs/pref_service.h" |
| 18 #include "base/prefs/scoped_user_pref_update.h" | 18 #include "base/prefs/scoped_user_pref_update.h" |
| 19 #include "base/single_thread_task_runner.h" | |
| 19 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/task_runner.h" | 22 #include "base/task_runner.h" |
| 22 #include "base/values.h" | 23 #include "base/values.h" |
| 23 #include "chrome/browser/chrome_notification_types.h" | 24 #include "chrome/browser/chrome_notification_types.h" |
| 24 #include "chrome/browser/history/history_backend.h" | 25 #include "chrome/browser/history/history_backend.h" |
| 25 #include "chrome/browser/history/history_notifications.h" | 26 #include "chrome/browser/history/history_notifications.h" |
| 26 #include "chrome/browser/history/history_service_factory.h" | 27 #include "chrome/browser/history/history_service_factory.h" |
| 27 #include "chrome/browser/profiles/profile.h" | 28 #include "chrome/browser/profiles/profile.h" |
| 28 #include "chrome/common/pref_names.h" | 29 #include "chrome/common/pref_names.h" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 88 // Time from startup to first HistoryService query. | 89 // Time from startup to first HistoryService query. |
| 89 static const int64 kUpdateIntervalSecs = 15; | 90 static const int64 kUpdateIntervalSecs = 15; |
| 90 // Intervals between requests to HistoryService. | 91 // Intervals between requests to HistoryService. |
| 91 static const int64 kMinUpdateIntervalMinutes = 1; | 92 static const int64 kMinUpdateIntervalMinutes = 1; |
| 92 static const int64 kMaxUpdateIntervalMinutes = 60; | 93 static const int64 kMaxUpdateIntervalMinutes = 60; |
| 93 | 94 |
| 94 // Use 100 quality (highest quality) because we're very sensitive to | 95 // Use 100 quality (highest quality) because we're very sensitive to |
| 95 // artifacts for these small sized, highly detailed images. | 96 // artifacts for these small sized, highly detailed images. |
| 96 static const int kTopSitesImageQuality = 100; | 97 static const int kTopSitesImageQuality = 100; |
| 97 | 98 |
| 98 TopSitesImpl::TopSitesImpl(Profile* profile) | 99 TopSitesImpl::TopSitesImpl(Profile* profile, |
| 100 const PrepopulatedPageList& prepopulated_pages) | |
| 99 : backend_(NULL), | 101 : backend_(NULL), |
| 100 cache_(new TopSitesCache()), | 102 cache_(new TopSitesCache()), |
| 101 thread_safe_cache_(new TopSitesCache()), | 103 thread_safe_cache_(new TopSitesCache()), |
| 102 profile_(profile), | 104 profile_(profile), |
| 103 last_num_urls_changed_(0), | 105 last_num_urls_changed_(0), |
| 106 prepopulated_pages_(prepopulated_pages), | |
| 104 loaded_(false) { | 107 loaded_(false) { |
| 105 if (!profile_) | 108 if (!profile_) |
| 106 return; | 109 return; |
| 107 | 110 |
| 108 if (content::NotificationService::current()) { | 111 if (content::NotificationService::current()) { |
| 109 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, | 112 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, |
| 110 content::Source<Profile>(profile_)); | 113 content::Source<Profile>(profile_)); |
| 111 // Listen for any nav commits. We'll ignore those not related to this | 114 // Listen for any nav commits. We'll ignore those not related to this |
| 112 // profile when we get the notification. | 115 // profile when we get the notification. |
| 113 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 116 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 114 content::NotificationService::AllSources()); | 117 content::NotificationService::AllSources()); |
| 115 } | 118 } |
| 116 for (int i = 0; i < kPrepopulatedPagesCount; i++) { | |
| 117 int url_id = kPrepopulatedPages[i].url_id; | |
| 118 prepopulated_page_urls_.push_back( | |
| 119 GURL(l10n_util::GetStringUTF8(url_id))); | |
| 120 } | |
| 121 } | 119 } |
| 122 | 120 |
| 123 void TopSitesImpl::Init(const base::FilePath& db_name) { | 121 void TopSitesImpl::Init( |
| 122 const base::FilePath& db_name, | |
| 123 const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner) { | |
| 124 // Create the backend here, rather than in the constructor, so that | 124 // Create the backend here, rather than in the constructor, so that |
| 125 // unit tests that do not need the backend can run without a problem. | 125 // unit tests that do not need the backend can run without a problem. |
| 126 backend_ = new TopSitesBackend; | 126 backend_ = new TopSitesBackend(db_task_runner); |
| 127 backend_->Init(db_name); | 127 backend_->Init(db_name); |
| 128 backend_->GetMostVisitedThumbnails( | 128 backend_->GetMostVisitedThumbnails( |
| 129 base::Bind(&TopSitesImpl::OnGotMostVisitedThumbnails, | 129 base::Bind(&TopSitesImpl::OnGotMostVisitedThumbnails, |
| 130 base::Unretained(this)), | 130 base::Unretained(this)), |
| 131 &cancelable_task_tracker_); | 131 &cancelable_task_tracker_); |
| 132 } | 132 } |
| 133 | 133 |
| 134 bool TopSitesImpl::SetPageThumbnail(const GURL& url, | 134 bool TopSitesImpl::SetPageThumbnail(const GURL& url, |
| 135 const gfx::Image& thumbnail, | 135 const gfx::Image& thumbnail, |
| 136 const ThumbnailScore& score) { | 136 const ThumbnailScore& score) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 scoped_refptr<base::RefCountedMemory>* bytes) { | 238 scoped_refptr<base::RefCountedMemory>* bytes) { |
| 239 // WARNING: this may be invoked on any thread. | 239 // WARNING: this may be invoked on any thread. |
| 240 // Perform exact match. | 240 // Perform exact match. |
| 241 { | 241 { |
| 242 base::AutoLock lock(lock_); | 242 base::AutoLock lock(lock_); |
| 243 if (thread_safe_cache_->GetPageThumbnail(url, bytes)) | 243 if (thread_safe_cache_->GetPageThumbnail(url, bytes)) |
| 244 return true; | 244 return true; |
| 245 } | 245 } |
| 246 | 246 |
| 247 // Resource bundle is thread safe. | 247 // Resource bundle is thread safe. |
| 248 for (int i = 0; i < kPrepopulatedPagesCount; i++) { | 248 for (const auto& prepopulated_page : prepopulated_pages_) { |
| 249 if (url == prepopulated_page_urls_[i]) { | 249 if (url == prepopulated_page.url.url) { |
|
droger
2015/01/27 10:08:36
should this be something like:
prepopulated_page.m
sdefresne
2015/01/27 13:55:16
Changed to prepopulated.most_visited.url (though t
| |
| 250 *bytes = ResourceBundle::GetSharedInstance(). | 250 *bytes = |
| 251 LoadDataResourceBytesForScale( | 251 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( |
| 252 kPrepopulatedPages[i].thumbnail_id, | 252 prepopulated_page.thumbnail_id, ui::SCALE_FACTOR_100P); |
| 253 ui::SCALE_FACTOR_100P); | |
| 254 return true; | 253 return true; |
| 255 } | 254 } |
| 256 } | 255 } |
| 257 | 256 |
| 258 if (prefix_match) { | 257 if (prefix_match) { |
| 259 // If http or https, search with |url| first, then try the other one. | 258 // If http or https, search with |url| first, then try the other one. |
| 260 std::vector<GURL> url_list; | 259 std::vector<GURL> url_list; |
| 261 url_list.push_back(url); | 260 url_list.push_back(url); |
| 262 if (url.SchemeIsHTTPOrHTTPS()) | 261 if (url.SchemeIsHTTPOrHTTPS()) |
| 263 url_list.push_back(ToggleHTTPAndHTTPS(url)); | 262 url_list.push_back(ToggleHTTPAndHTTPS(url)); |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 584 int TopSitesImpl::GetRedirectDistanceForURL(const MostVisitedURL& most_visited, | 583 int TopSitesImpl::GetRedirectDistanceForURL(const MostVisitedURL& most_visited, |
| 585 const GURL& url) { | 584 const GURL& url) { |
| 586 for (size_t i = 0; i < most_visited.redirects.size(); i++) { | 585 for (size_t i = 0; i < most_visited.redirects.size(); i++) { |
| 587 if (most_visited.redirects[i] == url) | 586 if (most_visited.redirects[i] == url) |
| 588 return static_cast<int>(most_visited.redirects.size() - i - 1); | 587 return static_cast<int>(most_visited.redirects.size() - i - 1); |
| 589 } | 588 } |
| 590 NOTREACHED() << "URL should always be found."; | 589 NOTREACHED() << "URL should always be found."; |
| 591 return 0; | 590 return 0; |
| 592 } | 591 } |
| 593 | 592 |
| 594 MostVisitedURLList TopSitesImpl::GetPrepopulatePages() { | 593 PrepopulatedPageList TopSitesImpl::GetPrepopulatedPages() { |
| 595 MostVisitedURLList urls; | 594 return prepopulated_pages_; |
| 596 urls.resize(kPrepopulatedPagesCount); | |
| 597 for (int i = 0; i < kPrepopulatedPagesCount; ++i) { | |
| 598 MostVisitedURL& url = urls[i]; | |
| 599 url.url = GURL(prepopulated_page_urls_[i]); | |
| 600 url.redirects.push_back(url.url); | |
| 601 url.title = l10n_util::GetStringUTF16(kPrepopulatedPages[i].title_id); | |
| 602 } | |
| 603 return urls; | |
| 604 } | 595 } |
| 605 | 596 |
| 606 bool TopSitesImpl::loaded() const { | 597 bool TopSitesImpl::loaded() const { |
| 607 return loaded_; | 598 return loaded_; |
| 608 } | 599 } |
| 609 | 600 |
| 610 bool TopSitesImpl::AddForcedURL(const GURL& url, const base::Time& time) { | 601 bool TopSitesImpl::AddForcedURL(const GURL& url, const base::Time& time) { |
| 611 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 602 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 612 size_t num_forced = cache_->GetNumForcedURLs(); | 603 size_t num_forced = cache_->GetNumForcedURLs(); |
| 613 MostVisitedURLList new_list(cache_->top_sites()); | 604 MostVisitedURLList new_list(cache_->top_sites()); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 636 new_list.insert(mid, new_url); | 627 new_list.insert(mid, new_url); |
| 637 mid = new_list.begin() + num_forced; // Mid was invalidated. | 628 mid = new_list.begin() + num_forced; // Mid was invalidated. |
| 638 std::inplace_merge(new_list.begin(), mid, mid + 1, ForcedURLComparator); | 629 std::inplace_merge(new_list.begin(), mid, mid + 1, ForcedURLComparator); |
| 639 SetTopSites(new_list); | 630 SetTopSites(new_list); |
| 640 return true; | 631 return true; |
| 641 } | 632 } |
| 642 | 633 |
| 643 bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls, | 634 bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls, |
| 644 size_t num_forced_urls) { | 635 size_t num_forced_urls) { |
| 645 bool added = false; | 636 bool added = false; |
| 646 MostVisitedURLList prepopulate_urls = GetPrepopulatePages(); | 637 for (const auto& prepopulated_page : prepopulated_pages_) { |
| 647 for (size_t i = 0; i < prepopulate_urls.size(); ++i) { | |
| 648 if (urls->size() - num_forced_urls < kNonForcedTopSitesNumber && | 638 if (urls->size() - num_forced_urls < kNonForcedTopSitesNumber && |
| 649 IndexOf(*urls, prepopulate_urls[i].url) == -1) { | 639 IndexOf(*urls, prepopulated_page.url.url) == -1) { |
| 650 urls->push_back(prepopulate_urls[i]); | 640 urls->push_back(prepopulated_page.url); |
| 651 added = true; | 641 added = true; |
| 652 } | 642 } |
| 653 } | 643 } |
| 654 return added; | 644 return added; |
| 655 } | 645 } |
| 656 | 646 |
| 657 size_t TopSitesImpl::MergeCachedForcedURLs(MostVisitedURLList* new_list) { | 647 size_t TopSitesImpl::MergeCachedForcedURLs(MostVisitedURLList* new_list) { |
| 658 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 648 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 659 // Add all the new URLs for quick lookup. Take that opportunity to count the | 649 // Add all the new URLs for quick lookup. Take that opportunity to count the |
| 660 // number of forced URLs in |new_list|. | 650 // number of forced URLs in |new_list|. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 723 } | 713 } |
| 724 } | 714 } |
| 725 | 715 |
| 726 std::string TopSitesImpl::GetURLHash(const GURL& url) { | 716 std::string TopSitesImpl::GetURLHash(const GURL& url) { |
| 727 // We don't use canonical URLs here to be able to blacklist only one of | 717 // We don't use canonical URLs here to be able to blacklist only one of |
| 728 // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. | 718 // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. |
| 729 return base::MD5String(url.spec()); | 719 return base::MD5String(url.spec()); |
| 730 } | 720 } |
| 731 | 721 |
| 732 base::TimeDelta TopSitesImpl::GetUpdateDelay() { | 722 base::TimeDelta TopSitesImpl::GetUpdateDelay() { |
| 733 if (cache_->top_sites().size() <= kPrepopulatedPagesCount) | 723 if (cache_->top_sites().size() <= prepopulated_pages_.size()) |
| 734 return base::TimeDelta::FromSeconds(30); | 724 return base::TimeDelta::FromSeconds(30); |
| 735 | 725 |
| 736 int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes; | 726 int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes; |
| 737 int64 minutes = kMaxUpdateIntervalMinutes - | 727 int64 minutes = kMaxUpdateIntervalMinutes - |
| 738 last_num_urls_changed_ * range / cache_->top_sites().size(); | 728 last_num_urls_changed_ * range / cache_->top_sites().size(); |
| 739 return base::TimeDelta::FromMinutes(minutes); | 729 return base::TimeDelta::FromMinutes(minutes); |
| 740 } | 730 } |
| 741 | 731 |
| 742 void TopSitesImpl::Observe(int type, | 732 void TopSitesImpl::Observe(int type, |
| 743 const content::NotificationSource& source, | 733 const content::NotificationSource& source, |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 922 base::TimeDelta::FromSeconds(kUpdateIntervalSecs)); | 912 base::TimeDelta::FromSeconds(kUpdateIntervalSecs)); |
| 923 } | 913 } |
| 924 | 914 |
| 925 void TopSitesImpl::OnTopSitesAvailableFromHistory( | 915 void TopSitesImpl::OnTopSitesAvailableFromHistory( |
| 926 const MostVisitedURLList* pages) { | 916 const MostVisitedURLList* pages) { |
| 927 DCHECK(pages); | 917 DCHECK(pages); |
| 928 SetTopSites(*pages); | 918 SetTopSites(*pages); |
| 929 } | 919 } |
| 930 | 920 |
| 931 } // namespace history | 921 } // namespace history |
| OLD | NEW |