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 |