| 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_service_factory.h" | 26 #include "chrome/browser/history/history_service_factory.h" |
| 26 #include "chrome/browser/profiles/profile.h" | 27 #include "chrome/browser/profiles/profile.h" |
| 27 #include "chrome/common/pref_names.h" | 28 #include "chrome/common/pref_names.h" |
| 28 #include "components/history/core/browser/history_db_task.h" | 29 #include "components/history/core/browser/history_db_task.h" |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 // Time from startup to first HistoryService query. | 88 // Time from startup to first HistoryService query. |
| 88 static const int64 kUpdateIntervalSecs = 15; | 89 static const int64 kUpdateIntervalSecs = 15; |
| 89 // Intervals between requests to HistoryService. | 90 // Intervals between requests to HistoryService. |
| 90 static const int64 kMinUpdateIntervalMinutes = 1; | 91 static const int64 kMinUpdateIntervalMinutes = 1; |
| 91 static const int64 kMaxUpdateIntervalMinutes = 60; | 92 static const int64 kMaxUpdateIntervalMinutes = 60; |
| 92 | 93 |
| 93 // Use 100 quality (highest quality) because we're very sensitive to | 94 // Use 100 quality (highest quality) because we're very sensitive to |
| 94 // artifacts for these small sized, highly detailed images. | 95 // artifacts for these small sized, highly detailed images. |
| 95 static const int kTopSitesImageQuality = 100; | 96 static const int kTopSitesImageQuality = 100; |
| 96 | 97 |
| 97 TopSitesImpl::TopSitesImpl(Profile* profile) | 98 TopSitesImpl::TopSitesImpl(Profile* profile, |
| 99 const PrepopulatedPageList& prepopulated_pages) |
| 98 : backend_(NULL), | 100 : backend_(NULL), |
| 99 cache_(new TopSitesCache()), | 101 cache_(new TopSitesCache()), |
| 100 thread_safe_cache_(new TopSitesCache()), | 102 thread_safe_cache_(new TopSitesCache()), |
| 101 profile_(profile), | 103 profile_(profile), |
| 102 last_num_urls_changed_(0), | 104 last_num_urls_changed_(0), |
| 105 prepopulated_pages_(prepopulated_pages), |
| 103 loaded_(false), | 106 loaded_(false), |
| 104 history_service_observer_(this) { | 107 history_service_observer_(this) { |
| 105 if (!profile_) | 108 if (!profile_) |
| 106 return; | 109 return; |
| 107 | 110 |
| 108 if (content::NotificationService::current()) { | 111 if (content::NotificationService::current()) { |
| 109 // Listen for any nav commits. We'll ignore those not related to this | 112 // Listen for any nav commits. We'll ignore those not related to this |
| 110 // profile when we get the notification. | 113 // profile when we get the notification. |
| 111 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 114 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 112 content::NotificationService::AllSources()); | 115 content::NotificationService::AllSources()); |
| 113 } | 116 } |
| 114 for (int i = 0; i < kPrepopulatedPagesCount; i++) { | |
| 115 int url_id = kPrepopulatedPages[i].url_id; | |
| 116 prepopulated_page_urls_.push_back( | |
| 117 GURL(l10n_util::GetStringUTF8(url_id))); | |
| 118 } | |
| 119 } | 117 } |
| 120 | 118 |
| 121 void TopSitesImpl::Init(const base::FilePath& db_name) { | 119 void TopSitesImpl::Init( |
| 120 const base::FilePath& db_name, |
| 121 const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner) { |
| 122 // Create the backend here, rather than in the constructor, so that | 122 // Create the backend here, rather than in the constructor, so that |
| 123 // unit tests that do not need the backend can run without a problem. | 123 // unit tests that do not need the backend can run without a problem. |
| 124 backend_ = new TopSitesBackend; | 124 backend_ = new TopSitesBackend(db_task_runner); |
| 125 backend_->Init(db_name); | 125 backend_->Init(db_name); |
| 126 backend_->GetMostVisitedThumbnails( | 126 backend_->GetMostVisitedThumbnails( |
| 127 base::Bind(&TopSitesImpl::OnGotMostVisitedThumbnails, | 127 base::Bind(&TopSitesImpl::OnGotMostVisitedThumbnails, |
| 128 base::Unretained(this)), | 128 base::Unretained(this)), |
| 129 &cancelable_task_tracker_); | 129 &cancelable_task_tracker_); |
| 130 } | 130 } |
| 131 | 131 |
| 132 bool TopSitesImpl::SetPageThumbnail(const GURL& url, | 132 bool TopSitesImpl::SetPageThumbnail(const GURL& url, |
| 133 const gfx::Image& thumbnail, | 133 const gfx::Image& thumbnail, |
| 134 const ThumbnailScore& score) { | 134 const ThumbnailScore& score) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 scoped_refptr<base::RefCountedMemory>* bytes) { | 236 scoped_refptr<base::RefCountedMemory>* bytes) { |
| 237 // WARNING: this may be invoked on any thread. | 237 // WARNING: this may be invoked on any thread. |
| 238 // Perform exact match. | 238 // Perform exact match. |
| 239 { | 239 { |
| 240 base::AutoLock lock(lock_); | 240 base::AutoLock lock(lock_); |
| 241 if (thread_safe_cache_->GetPageThumbnail(url, bytes)) | 241 if (thread_safe_cache_->GetPageThumbnail(url, bytes)) |
| 242 return true; | 242 return true; |
| 243 } | 243 } |
| 244 | 244 |
| 245 // Resource bundle is thread safe. | 245 // Resource bundle is thread safe. |
| 246 for (int i = 0; i < kPrepopulatedPagesCount; i++) { | 246 for (const auto& prepopulated_page : prepopulated_pages_) { |
| 247 if (url == prepopulated_page_urls_[i]) { | 247 if (url == prepopulated_page.most_visited.url) { |
| 248 *bytes = ResourceBundle::GetSharedInstance(). | 248 *bytes = |
| 249 LoadDataResourceBytesForScale( | 249 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( |
| 250 kPrepopulatedPages[i].thumbnail_id, | 250 prepopulated_page.thumbnail_id, ui::SCALE_FACTOR_100P); |
| 251 ui::SCALE_FACTOR_100P); | |
| 252 return true; | 251 return true; |
| 253 } | 252 } |
| 254 } | 253 } |
| 255 | 254 |
| 256 if (prefix_match) { | 255 if (prefix_match) { |
| 257 // If http or https, search with |url| first, then try the other one. | 256 // If http or https, search with |url| first, then try the other one. |
| 258 std::vector<GURL> url_list; | 257 std::vector<GURL> url_list; |
| 259 url_list.push_back(url); | 258 url_list.push_back(url); |
| 260 if (url.SchemeIsHTTPOrHTTPS()) | 259 if (url.SchemeIsHTTPOrHTTPS()) |
| 261 url_list.push_back(ToggleHTTPAndHTTPS(url)); | 260 url_list.push_back(ToggleHTTPAndHTTPS(url)); |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 int TopSitesImpl::GetRedirectDistanceForURL(const MostVisitedURL& most_visited, | 580 int TopSitesImpl::GetRedirectDistanceForURL(const MostVisitedURL& most_visited, |
| 582 const GURL& url) { | 581 const GURL& url) { |
| 583 for (size_t i = 0; i < most_visited.redirects.size(); i++) { | 582 for (size_t i = 0; i < most_visited.redirects.size(); i++) { |
| 584 if (most_visited.redirects[i] == url) | 583 if (most_visited.redirects[i] == url) |
| 585 return static_cast<int>(most_visited.redirects.size() - i - 1); | 584 return static_cast<int>(most_visited.redirects.size() - i - 1); |
| 586 } | 585 } |
| 587 NOTREACHED() << "URL should always be found."; | 586 NOTREACHED() << "URL should always be found."; |
| 588 return 0; | 587 return 0; |
| 589 } | 588 } |
| 590 | 589 |
| 591 MostVisitedURLList TopSitesImpl::GetPrepopulatePages() { | 590 PrepopulatedPageList TopSitesImpl::GetPrepopulatedPages() { |
| 592 MostVisitedURLList urls; | 591 return prepopulated_pages_; |
| 593 urls.resize(kPrepopulatedPagesCount); | |
| 594 for (int i = 0; i < kPrepopulatedPagesCount; ++i) { | |
| 595 MostVisitedURL& url = urls[i]; | |
| 596 url.url = GURL(prepopulated_page_urls_[i]); | |
| 597 url.redirects.push_back(url.url); | |
| 598 url.title = l10n_util::GetStringUTF16(kPrepopulatedPages[i].title_id); | |
| 599 } | |
| 600 return urls; | |
| 601 } | 592 } |
| 602 | 593 |
| 603 bool TopSitesImpl::loaded() const { | 594 bool TopSitesImpl::loaded() const { |
| 604 return loaded_; | 595 return loaded_; |
| 605 } | 596 } |
| 606 | 597 |
| 607 bool TopSitesImpl::AddForcedURL(const GURL& url, const base::Time& time) { | 598 bool TopSitesImpl::AddForcedURL(const GURL& url, const base::Time& time) { |
| 608 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 599 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 609 size_t num_forced = cache_->GetNumForcedURLs(); | 600 size_t num_forced = cache_->GetNumForcedURLs(); |
| 610 MostVisitedURLList new_list(cache_->top_sites()); | 601 MostVisitedURLList new_list(cache_->top_sites()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 633 new_list.insert(mid, new_url); | 624 new_list.insert(mid, new_url); |
| 634 mid = new_list.begin() + num_forced; // Mid was invalidated. | 625 mid = new_list.begin() + num_forced; // Mid was invalidated. |
| 635 std::inplace_merge(new_list.begin(), mid, mid + 1, ForcedURLComparator); | 626 std::inplace_merge(new_list.begin(), mid, mid + 1, ForcedURLComparator); |
| 636 SetTopSites(new_list); | 627 SetTopSites(new_list); |
| 637 return true; | 628 return true; |
| 638 } | 629 } |
| 639 | 630 |
| 640 bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls, | 631 bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls, |
| 641 size_t num_forced_urls) { | 632 size_t num_forced_urls) { |
| 642 bool added = false; | 633 bool added = false; |
| 643 MostVisitedURLList prepopulate_urls = GetPrepopulatePages(); | 634 for (const auto& prepopulated_page : prepopulated_pages_) { |
| 644 for (size_t i = 0; i < prepopulate_urls.size(); ++i) { | |
| 645 if (urls->size() - num_forced_urls < kNonForcedTopSitesNumber && | 635 if (urls->size() - num_forced_urls < kNonForcedTopSitesNumber && |
| 646 IndexOf(*urls, prepopulate_urls[i].url) == -1) { | 636 IndexOf(*urls, prepopulated_page.most_visited.url) == -1) { |
| 647 urls->push_back(prepopulate_urls[i]); | 637 urls->push_back(prepopulated_page.most_visited); |
| 648 added = true; | 638 added = true; |
| 649 } | 639 } |
| 650 } | 640 } |
| 651 return added; | 641 return added; |
| 652 } | 642 } |
| 653 | 643 |
| 654 size_t TopSitesImpl::MergeCachedForcedURLs(MostVisitedURLList* new_list) { | 644 size_t TopSitesImpl::MergeCachedForcedURLs(MostVisitedURLList* new_list) { |
| 655 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 645 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 656 // Add all the new URLs for quick lookup. Take that opportunity to count the | 646 // Add all the new URLs for quick lookup. Take that opportunity to count the |
| 657 // number of forced URLs in |new_list|. | 647 // number of forced URLs in |new_list|. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 } | 710 } |
| 721 } | 711 } |
| 722 | 712 |
| 723 std::string TopSitesImpl::GetURLHash(const GURL& url) { | 713 std::string TopSitesImpl::GetURLHash(const GURL& url) { |
| 724 // We don't use canonical URLs here to be able to blacklist only one of | 714 // We don't use canonical URLs here to be able to blacklist only one of |
| 725 // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. | 715 // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. |
| 726 return base::MD5String(url.spec()); | 716 return base::MD5String(url.spec()); |
| 727 } | 717 } |
| 728 | 718 |
| 729 base::TimeDelta TopSitesImpl::GetUpdateDelay() { | 719 base::TimeDelta TopSitesImpl::GetUpdateDelay() { |
| 730 if (cache_->top_sites().size() <= kPrepopulatedPagesCount) | 720 if (cache_->top_sites().size() <= prepopulated_pages_.size()) |
| 731 return base::TimeDelta::FromSeconds(30); | 721 return base::TimeDelta::FromSeconds(30); |
| 732 | 722 |
| 733 int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes; | 723 int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes; |
| 734 int64 minutes = kMaxUpdateIntervalMinutes - | 724 int64 minutes = kMaxUpdateIntervalMinutes - |
| 735 last_num_urls_changed_ * range / cache_->top_sites().size(); | 725 last_num_urls_changed_ * range / cache_->top_sites().size(); |
| 736 return base::TimeDelta::FromMinutes(minutes); | 726 return base::TimeDelta::FromMinutes(minutes); |
| 737 } | 727 } |
| 738 | 728 |
| 739 void TopSitesImpl::Observe(int type, | 729 void TopSitesImpl::Observe(int type, |
| 740 const content::NotificationSource& source, | 730 const content::NotificationSource& source, |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 SetTopSites(new_top_sites); | 925 SetTopSites(new_top_sites); |
| 936 } | 926 } |
| 937 StartQueryForMostVisited(); | 927 StartQueryForMostVisited(); |
| 938 } | 928 } |
| 939 | 929 |
| 940 void TopSitesImpl::HistoryServiceBeingDeleted(HistoryService* history_service) { | 930 void TopSitesImpl::HistoryServiceBeingDeleted(HistoryService* history_service) { |
| 941 history_service_observer_.Remove(history_service); | 931 history_service_observer_.Remove(history_service); |
| 942 } | 932 } |
| 943 | 933 |
| 944 } // namespace history | 934 } // namespace history |
| OLD | NEW |