| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_service.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" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 46 using content::BrowserThread; | 46 using content::BrowserThread; |
| 47 using content::NavigationController; | 47 using content::NavigationController; |
| 48 | 48 |
| 49 namespace history { | 49 namespace history { |
| 50 | 50 |
| 51 namespace { | 51 namespace { |
| 52 | 52 |
| 53 void RunOrPostGetMostVisitedURLsCallback( | 53 void RunOrPostGetMostVisitedURLsCallback( |
| 54 base::TaskRunner* task_runner, | 54 base::TaskRunner* task_runner, |
| 55 bool include_forced_urls, | 55 bool include_forced_urls, |
| 56 const TopSitesImpl::GetMostVisitedURLsCallback& callback, | 56 const TopSitesService::GetMostVisitedURLsCallback& callback, |
| 57 const MostVisitedURLList& all_urls, | 57 const MostVisitedURLList& all_urls, |
| 58 const MostVisitedURLList& nonforced_urls) { | 58 const MostVisitedURLList& nonforced_urls) { |
| 59 const MostVisitedURLList* urls = | 59 const MostVisitedURLList* urls = |
| 60 include_forced_urls ? &all_urls : &nonforced_urls; | 60 include_forced_urls ? &all_urls : &nonforced_urls; |
| 61 if (task_runner->RunsTasksOnCurrentThread()) | 61 if (task_runner->RunsTasksOnCurrentThread()) |
| 62 callback.Run(*urls); | 62 callback.Run(*urls); |
| 63 else | 63 else |
| 64 task_runner->PostTask(FROM_HERE, base::Bind(callback, *urls)); | 64 task_runner->PostTask(FROM_HERE, base::Bind(callback, *urls)); |
| 65 } | 65 } |
| 66 | 66 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 88 // Time from startup to first HistoryService query. | 88 // Time from startup to first HistoryService query. |
| 89 static const int64 kUpdateIntervalSecs = 15; | 89 static const int64 kUpdateIntervalSecs = 15; |
| 90 // Intervals between requests to HistoryService. | 90 // Intervals between requests to HistoryService. |
| 91 static const int64 kMinUpdateIntervalMinutes = 1; | 91 static const int64 kMinUpdateIntervalMinutes = 1; |
| 92 static const int64 kMaxUpdateIntervalMinutes = 60; | 92 static const int64 kMaxUpdateIntervalMinutes = 60; |
| 93 | 93 |
| 94 // Use 100 quality (highest quality) because we're very sensitive to | 94 // Use 100 quality (highest quality) because we're very sensitive to |
| 95 // artifacts for these small sized, highly detailed images. | 95 // artifacts for these small sized, highly detailed images. |
| 96 static const int kTopSitesImageQuality = 100; | 96 static const int kTopSitesImageQuality = 100; |
| 97 | 97 |
| 98 TopSitesImpl::TopSitesImpl(Profile* profile) | 98 TopSitesService::TopSitesService(Profile* profile) |
| 99 : backend_(NULL), | 99 : backend_(NULL), |
| 100 cache_(new TopSitesCache()), | 100 cache_(new TopSitesCache()), |
| 101 thread_safe_cache_(new TopSitesCache()), | 101 thread_safe_cache_(new TopSitesCache()), |
| 102 profile_(profile), | 102 profile_(profile), |
| 103 last_num_urls_changed_(0), | 103 last_num_urls_changed_(0), |
| 104 loaded_(false) { | 104 loaded_(false) { |
| 105 if (!profile_) | 105 if (!profile_) |
| 106 return; | 106 return; |
| 107 | 107 |
| 108 if (content::NotificationService::current()) { | 108 if (content::NotificationService::current()) { |
| 109 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, | 109 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, |
| 110 content::Source<Profile>(profile_)); | 110 content::Source<Profile>(profile_)); |
| 111 // Listen for any nav commits. We'll ignore those not related to this | 111 // Listen for any nav commits. We'll ignore those not related to this |
| 112 // profile when we get the notification. | 112 // profile when we get the notification. |
| 113 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 113 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 114 content::NotificationService::AllSources()); | 114 content::NotificationService::AllSources()); |
| 115 } | 115 } |
| 116 for (int i = 0; i < kPrepopulatedPagesCount; i++) { | 116 for (int i = 0; i < kPrepopulatedPagesCount; i++) { |
| 117 int url_id = kPrepopulatedPages[i].url_id; | 117 int url_id = kPrepopulatedPages[i].url_id; |
| 118 prepopulated_page_urls_.push_back( | 118 prepopulated_page_urls_.push_back(GURL(l10n_util::GetStringUTF8(url_id))); |
| 119 GURL(l10n_util::GetStringUTF8(url_id))); | |
| 120 } | 119 } |
| 121 } | 120 } |
| 122 | 121 |
| 123 void TopSitesImpl::Init(const base::FilePath& db_name) { | 122 void TopSitesService::Init(const base::FilePath& db_name) { |
| 124 // Create the backend here, rather than in the constructor, so that | 123 // 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. | 124 // unit tests that do not need the backend can run without a problem. |
| 126 backend_ = new TopSitesBackend; | 125 backend_ = new TopSitesBackend; |
| 127 backend_->Init(db_name); | 126 backend_->Init(db_name); |
| 128 backend_->GetMostVisitedThumbnails( | 127 backend_->GetMostVisitedThumbnails( |
| 129 base::Bind(&TopSitesImpl::OnGotMostVisitedThumbnails, | 128 base::Bind(&TopSitesService::OnGotMostVisitedThumbnails, |
| 130 base::Unretained(this)), | 129 base::Unretained(this)), |
| 131 &cancelable_task_tracker_); | 130 &cancelable_task_tracker_); |
| 132 } | 131 } |
| 133 | 132 |
| 134 bool TopSitesImpl::SetPageThumbnail(const GURL& url, | 133 bool TopSitesService::SetPageThumbnail(const GURL& url, |
| 135 const gfx::Image& thumbnail, | 134 const gfx::Image& thumbnail, |
| 136 const ThumbnailScore& score) { | 135 const ThumbnailScore& score) { |
| 137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 138 | 137 |
| 139 if (!loaded_) { | 138 if (!loaded_) { |
| 140 // TODO(sky): I need to cache these and apply them after the load | 139 // TODO(sky): I need to cache these and apply them after the load |
| 141 // completes. | 140 // completes. |
| 142 return false; | 141 return false; |
| 143 } | 142 } |
| 144 | 143 |
| 145 bool add_temp_thumbnail = false; | 144 bool add_temp_thumbnail = false; |
| 146 if (!IsKnownURL(url)) { | 145 if (!IsKnownURL(url)) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 162 // Always remove the existing entry and then add it back. That way if we end | 161 // Always remove the existing entry and then add it back. That way if we end |
| 163 // up with too many temp thumbnails we'll prune the oldest first. | 162 // up with too many temp thumbnails we'll prune the oldest first. |
| 164 RemoveTemporaryThumbnailByURL(url); | 163 RemoveTemporaryThumbnailByURL(url); |
| 165 AddTemporaryThumbnail(url, thumbnail_data.get(), score); | 164 AddTemporaryThumbnail(url, thumbnail_data.get(), score); |
| 166 return true; | 165 return true; |
| 167 } | 166 } |
| 168 | 167 |
| 169 return SetPageThumbnailEncoded(url, thumbnail_data.get(), score); | 168 return SetPageThumbnailEncoded(url, thumbnail_data.get(), score); |
| 170 } | 169 } |
| 171 | 170 |
| 172 bool TopSitesImpl::SetPageThumbnailToJPEGBytes( | 171 bool TopSitesService::SetPageThumbnailToJPEGBytes( |
| 173 const GURL& url, | 172 const GURL& url, |
| 174 const base::RefCountedMemory* memory, | 173 const base::RefCountedMemory* memory, |
| 175 const ThumbnailScore& score) { | 174 const ThumbnailScore& score) { |
| 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 177 | 176 |
| 178 if (!loaded_) { | 177 if (!loaded_) { |
| 179 // TODO(sky): I need to cache these and apply them after the load | 178 // TODO(sky): I need to cache these and apply them after the load |
| 180 // completes. | 179 // completes. |
| 181 return false; | 180 return false; |
| 182 } | 181 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 198 // up with too many temp thumbnails we'll prune the oldest first. | 197 // up with too many temp thumbnails we'll prune the oldest first. |
| 199 RemoveTemporaryThumbnailByURL(url); | 198 RemoveTemporaryThumbnailByURL(url); |
| 200 AddTemporaryThumbnail(url, memory, score); | 199 AddTemporaryThumbnail(url, memory, score); |
| 201 return true; | 200 return true; |
| 202 } | 201 } |
| 203 | 202 |
| 204 return SetPageThumbnailEncoded(url, memory, score); | 203 return SetPageThumbnailEncoded(url, memory, score); |
| 205 } | 204 } |
| 206 | 205 |
| 207 // WARNING: this function may be invoked on any thread. | 206 // WARNING: this function may be invoked on any thread. |
| 208 void TopSitesImpl::GetMostVisitedURLs( | 207 void TopSitesService::GetMostVisitedURLs( |
| 209 const GetMostVisitedURLsCallback& callback, | 208 const GetMostVisitedURLsCallback& callback, |
| 210 bool include_forced_urls) { | 209 bool include_forced_urls) { |
| 211 MostVisitedURLList filtered_urls; | 210 MostVisitedURLList filtered_urls; |
| 212 { | 211 { |
| 213 base::AutoLock lock(lock_); | 212 base::AutoLock lock(lock_); |
| 214 if (!loaded_) { | 213 if (!loaded_) { |
| 215 // A request came in before we finished loading. Store the callback and | 214 // A request came in before we finished loading. Store the callback and |
| 216 // we'll run it on current thread when we finish loading. | 215 // we'll run it on current thread when we finish loading. |
| 217 pending_callbacks_.push_back( | 216 pending_callbacks_.push_back(base::Bind( |
| 218 base::Bind(&RunOrPostGetMostVisitedURLsCallback, | 217 &RunOrPostGetMostVisitedURLsCallback, |
| 219 base::MessageLoopProxy::current(), | 218 base::MessageLoopProxy::current(), include_forced_urls, callback)); |
| 220 include_forced_urls, | |
| 221 callback)); | |
| 222 return; | 219 return; |
| 223 } | 220 } |
| 224 if (include_forced_urls) { | 221 if (include_forced_urls) { |
| 225 filtered_urls = thread_safe_cache_->top_sites(); | 222 filtered_urls = thread_safe_cache_->top_sites(); |
| 226 } else { | 223 } else { |
| 227 filtered_urls.assign(thread_safe_cache_->top_sites().begin() + | 224 filtered_urls.assign(thread_safe_cache_->top_sites().begin() + |
| 228 thread_safe_cache_->GetNumForcedURLs(), | 225 thread_safe_cache_->GetNumForcedURLs(), |
| 229 thread_safe_cache_->top_sites().end()); | 226 thread_safe_cache_->top_sites().end()); |
| 230 } | 227 } |
| 231 } | 228 } |
| 232 callback.Run(filtered_urls); | 229 callback.Run(filtered_urls); |
| 233 } | 230 } |
| 234 | 231 |
| 235 bool TopSitesImpl::GetPageThumbnail( | 232 bool TopSitesService::GetPageThumbnail( |
| 236 const GURL& url, | 233 const GURL& url, |
| 237 bool prefix_match, | 234 bool prefix_match, |
| 238 scoped_refptr<base::RefCountedMemory>* bytes) { | 235 scoped_refptr<base::RefCountedMemory>* bytes) { |
| 239 // WARNING: this may be invoked on any thread. | 236 // WARNING: this may be invoked on any thread. |
| 240 // Perform exact match. | 237 // Perform exact match. |
| 241 { | 238 { |
| 242 base::AutoLock lock(lock_); | 239 base::AutoLock lock(lock_); |
| 243 if (thread_safe_cache_->GetPageThumbnail(url, bytes)) | 240 if (thread_safe_cache_->GetPageThumbnail(url, bytes)) |
| 244 return true; | 241 return true; |
| 245 } | 242 } |
| 246 | 243 |
| 247 // Resource bundle is thread safe. | 244 // Resource bundle is thread safe. |
| 248 for (int i = 0; i < kPrepopulatedPagesCount; i++) { | 245 for (int i = 0; i < kPrepopulatedPagesCount; i++) { |
| 249 if (url == prepopulated_page_urls_[i]) { | 246 if (url == prepopulated_page_urls_[i]) { |
| 250 *bytes = ResourceBundle::GetSharedInstance(). | 247 *bytes = |
| 251 LoadDataResourceBytesForScale( | 248 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( |
| 252 kPrepopulatedPages[i].thumbnail_id, | 249 kPrepopulatedPages[i].thumbnail_id, ui::SCALE_FACTOR_100P); |
| 253 ui::SCALE_FACTOR_100P); | |
| 254 return true; | 250 return true; |
| 255 } | 251 } |
| 256 } | 252 } |
| 257 | 253 |
| 258 if (prefix_match) { | 254 if (prefix_match) { |
| 259 // If http or https, search with |url| first, then try the other one. | 255 // If http or https, search with |url| first, then try the other one. |
| 260 std::vector<GURL> url_list; | 256 std::vector<GURL> url_list; |
| 261 url_list.push_back(url); | 257 url_list.push_back(url); |
| 262 if (url.SchemeIsHTTPOrHTTPS()) | 258 if (url.SchemeIsHTTPOrHTTPS()) |
| 263 url_list.push_back(ToggleHTTPAndHTTPS(url)); | 259 url_list.push_back(ToggleHTTPAndHTTPS(url)); |
| 264 | 260 |
| 265 for (std::vector<GURL>::iterator it = url_list.begin(); | 261 for (std::vector<GURL>::iterator it = url_list.begin(); |
| 266 it != url_list.end(); ++it) { | 262 it != url_list.end(); ++it) { |
| 267 base::AutoLock lock(lock_); | 263 base::AutoLock lock(lock_); |
| 268 | 264 |
| 269 GURL canonical_url; | 265 GURL canonical_url; |
| 270 // Test whether any stored URL is a prefix of |url|. | 266 // Test whether any stored URL is a prefix of |url|. |
| 271 canonical_url = thread_safe_cache_->GetGeneralizedCanonicalURL(*it); | 267 canonical_url = thread_safe_cache_->GetGeneralizedCanonicalURL(*it); |
| 272 if (!canonical_url.is_empty() && | 268 if (!canonical_url.is_empty() && |
| 273 thread_safe_cache_->GetPageThumbnail(canonical_url, bytes)) { | 269 thread_safe_cache_->GetPageThumbnail(canonical_url, bytes)) { |
| 274 return true; | 270 return true; |
| 275 } | 271 } |
| 276 } | 272 } |
| 277 } | 273 } |
| 278 | 274 |
| 279 return false; | 275 return false; |
| 280 } | 276 } |
| 281 | 277 |
| 282 bool TopSitesImpl::GetPageThumbnailScore(const GURL& url, | 278 bool TopSitesService::GetPageThumbnailScore(const GURL& url, |
| 283 ThumbnailScore* score) { | 279 ThumbnailScore* score) { |
| 284 // WARNING: this may be invoked on any thread. | 280 // WARNING: this may be invoked on any thread. |
| 285 base::AutoLock lock(lock_); | 281 base::AutoLock lock(lock_); |
| 286 return thread_safe_cache_->GetPageThumbnailScore(url, score); | 282 return thread_safe_cache_->GetPageThumbnailScore(url, score); |
| 287 } | 283 } |
| 288 | 284 |
| 289 bool TopSitesImpl::GetTemporaryPageThumbnailScore(const GURL& url, | 285 bool TopSitesService::GetTemporaryPageThumbnailScore(const GURL& url, |
| 290 ThumbnailScore* score) { | 286 ThumbnailScore* score) { |
| 291 for (TempImages::iterator i = temp_images_.begin(); i != temp_images_.end(); | 287 for (TempImages::iterator i = temp_images_.begin(); i != temp_images_.end(); |
| 292 ++i) { | 288 ++i) { |
| 293 if (i->first == url) { | 289 if (i->first == url) { |
| 294 *score = i->second.thumbnail_score; | 290 *score = i->second.thumbnail_score; |
| 295 return true; | 291 return true; |
| 296 } | 292 } |
| 297 } | 293 } |
| 298 return false; | 294 return false; |
| 299 } | 295 } |
| 300 | 296 |
| 301 | |
| 302 // Returns the index of |url| in |urls|, or -1 if not found. | 297 // Returns the index of |url| in |urls|, or -1 if not found. |
| 303 static int IndexOf(const MostVisitedURLList& urls, const GURL& url) { | 298 static int IndexOf(const MostVisitedURLList& urls, const GURL& url) { |
| 304 for (size_t i = 0; i < urls.size(); i++) { | 299 for (size_t i = 0; i < urls.size(); i++) { |
| 305 if (urls[i].url == url) | 300 if (urls[i].url == url) |
| 306 return i; | 301 return i; |
| 307 } | 302 } |
| 308 return -1; | 303 return -1; |
| 309 } | 304 } |
| 310 | 305 |
| 311 void TopSitesImpl::SyncWithHistory() { | 306 void TopSitesService::SyncWithHistory() { |
| 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 313 if (loaded_ && temp_images_.size()) { | 308 if (loaded_ && temp_images_.size()) { |
| 314 // If we have temporary thumbnails it means there isn't much data, and most | 309 // If we have temporary thumbnails it means there isn't much data, and most |
| 315 // likely the user is first running Chrome. During this time we throttle | 310 // likely the user is first running Chrome. During this time we throttle |
| 316 // updating from history by 30 seconds. If the user creates a new tab page | 311 // updating from history by 30 seconds. If the user creates a new tab page |
| 317 // during this window of time we force updating from history so that the new | 312 // during this window of time we force updating from history so that the new |
| 318 // tab page isn't so far out of date. | 313 // tab page isn't so far out of date. |
| 319 timer_.Stop(); | 314 timer_.Stop(); |
| 320 StartQueryForMostVisited(); | 315 StartQueryForMostVisited(); |
| 321 } | 316 } |
| 322 } | 317 } |
| 323 | 318 |
| 324 bool TopSitesImpl::HasBlacklistedItems() const { | 319 bool TopSitesService::HasBlacklistedItems() const { |
| 325 const base::DictionaryValue* blacklist = | 320 const base::DictionaryValue* blacklist = |
| 326 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); | 321 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); |
| 327 return blacklist && !blacklist->empty(); | 322 return blacklist && !blacklist->empty(); |
| 328 } | 323 } |
| 329 | 324 |
| 330 void TopSitesImpl::AddBlacklistedURL(const GURL& url) { | 325 void TopSitesService::AddBlacklistedURL(const GURL& url) { |
| 331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 332 | 327 |
| 333 base::Value* dummy = base::Value::CreateNullValue(); | 328 base::Value* dummy = base::Value::CreateNullValue(); |
| 334 { | 329 { |
| 335 DictionaryPrefUpdate update(profile_->GetPrefs(), | 330 DictionaryPrefUpdate update(profile_->GetPrefs(), |
| 336 prefs::kNtpMostVisitedURLsBlacklist); | 331 prefs::kNtpMostVisitedURLsBlacklist); |
| 337 base::DictionaryValue* blacklist = update.Get(); | 332 base::DictionaryValue* blacklist = update.Get(); |
| 338 blacklist->SetWithoutPathExpansion(GetURLHash(url), dummy); | 333 blacklist->SetWithoutPathExpansion(GetURLHash(url), dummy); |
| 339 } | 334 } |
| 340 | 335 |
| 341 ResetThreadSafeCache(); | 336 ResetThreadSafeCache(); |
| 342 NotifyTopSitesChanged(); | 337 NotifyTopSitesChanged(); |
| 343 } | 338 } |
| 344 | 339 |
| 345 void TopSitesImpl::RemoveBlacklistedURL(const GURL& url) { | 340 void TopSitesService::RemoveBlacklistedURL(const GURL& url) { |
| 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 347 { | 342 { |
| 348 DictionaryPrefUpdate update(profile_->GetPrefs(), | 343 DictionaryPrefUpdate update(profile_->GetPrefs(), |
| 349 prefs::kNtpMostVisitedURLsBlacklist); | 344 prefs::kNtpMostVisitedURLsBlacklist); |
| 350 base::DictionaryValue* blacklist = update.Get(); | 345 base::DictionaryValue* blacklist = update.Get(); |
| 351 blacklist->RemoveWithoutPathExpansion(GetURLHash(url), NULL); | 346 blacklist->RemoveWithoutPathExpansion(GetURLHash(url), NULL); |
| 352 } | 347 } |
| 353 ResetThreadSafeCache(); | 348 ResetThreadSafeCache(); |
| 354 NotifyTopSitesChanged(); | 349 NotifyTopSitesChanged(); |
| 355 } | 350 } |
| 356 | 351 |
| 357 bool TopSitesImpl::IsBlacklisted(const GURL& url) { | 352 bool TopSitesService::IsBlacklisted(const GURL& url) { |
| 358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 353 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 359 const base::DictionaryValue* blacklist = | 354 const base::DictionaryValue* blacklist = |
| 360 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); | 355 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); |
| 361 return blacklist && blacklist->HasKey(GetURLHash(url)); | 356 return blacklist && blacklist->HasKey(GetURLHash(url)); |
| 362 } | 357 } |
| 363 | 358 |
| 364 void TopSitesImpl::ClearBlacklistedURLs() { | 359 void TopSitesService::ClearBlacklistedURLs() { |
| 365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 366 { | 361 { |
| 367 DictionaryPrefUpdate update(profile_->GetPrefs(), | 362 DictionaryPrefUpdate update(profile_->GetPrefs(), |
| 368 prefs::kNtpMostVisitedURLsBlacklist); | 363 prefs::kNtpMostVisitedURLsBlacklist); |
| 369 base::DictionaryValue* blacklist = update.Get(); | 364 base::DictionaryValue* blacklist = update.Get(); |
| 370 blacklist->Clear(); | 365 blacklist->Clear(); |
| 371 } | 366 } |
| 372 ResetThreadSafeCache(); | 367 ResetThreadSafeCache(); |
| 373 NotifyTopSitesChanged(); | 368 NotifyTopSitesChanged(); |
| 374 } | 369 } |
| 375 | 370 |
| 376 void TopSitesImpl::Shutdown() { | 371 void TopSitesService::Shutdown() { |
| 377 profile_ = NULL; | 372 profile_ = NULL; |
| 378 // Cancel all requests so that the service doesn't callback to us after we've | 373 // Cancel all requests so that the service doesn't callback to us after we've |
| 379 // invoked Shutdown (this could happen if we have a pending request and | 374 // invoked Shutdown (this could happen if we have a pending request and |
| 380 // Shutdown is invoked). | 375 // Shutdown is invoked). |
| 381 cancelable_task_tracker_.TryCancelAll(); | 376 cancelable_task_tracker_.TryCancelAll(); |
| 382 backend_->Shutdown(); | 377 backend_->Shutdown(); |
| 383 } | 378 } |
| 384 | 379 |
| 385 // static | 380 // static |
| 386 void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list, | 381 void TopSitesService::DiffMostVisited(const MostVisitedURLList& old_list, |
| 387 const MostVisitedURLList& new_list, | 382 const MostVisitedURLList& new_list, |
| 388 TopSitesDelta* delta) { | 383 TopSitesDelta* delta) { |
| 389 | |
| 390 // Add all the old URLs for quick lookup. This maps URLs to the corresponding | 384 // Add all the old URLs for quick lookup. This maps URLs to the corresponding |
| 391 // index in the input. | 385 // index in the input. |
| 392 std::map<GURL, size_t> all_old_urls; | 386 std::map<GURL, size_t> all_old_urls; |
| 393 size_t num_old_forced = 0; | 387 size_t num_old_forced = 0; |
| 394 for (size_t i = 0; i < old_list.size(); i++) { | 388 for (size_t i = 0; i < old_list.size(); i++) { |
| 395 if (!old_list[i].last_forced_time.is_null()) | 389 if (!old_list[i].last_forced_time.is_null()) |
| 396 num_old_forced++; | 390 num_old_forced++; |
| 397 DCHECK(old_list[i].last_forced_time.is_null() || i < num_old_forced) | 391 DCHECK(old_list[i].last_forced_time.is_null() || i < num_old_forced) |
| 398 << "Forced URLs must all appear before non-forced URLs."; | 392 << "Forced URLs must all appear before non-forced URLs."; |
| 399 all_old_urls[old_list[i].url] = i; | 393 all_old_urls[old_list[i].url] = i; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 414 << "Forced URLs must all appear before non-forced URLs."; | 408 << "Forced URLs must all appear before non-forced URLs."; |
| 415 std::map<GURL, size_t>::iterator found = all_old_urls.find(new_list[i].url); | 409 std::map<GURL, size_t>::iterator found = all_old_urls.find(new_list[i].url); |
| 416 if (found == all_old_urls.end()) { | 410 if (found == all_old_urls.end()) { |
| 417 MostVisitedURLWithRank added; | 411 MostVisitedURLWithRank added; |
| 418 added.url = new_list[i]; | 412 added.url = new_list[i]; |
| 419 added.rank = rank; | 413 added.rank = rank; |
| 420 delta->added.push_back(added); | 414 delta->added.push_back(added); |
| 421 } else { | 415 } else { |
| 422 DCHECK(found->second != kAlreadyFoundMarker) | 416 DCHECK(found->second != kAlreadyFoundMarker) |
| 423 << "Same URL appears twice in the new list."; | 417 << "Same URL appears twice in the new list."; |
| 424 int old_rank = found->second >= num_old_forced ? | 418 int old_rank = |
| 425 found->second - num_old_forced : -1; | 419 found->second >= num_old_forced ? found->second - num_old_forced : -1; |
| 426 if (old_rank != rank || | 420 if (old_rank != rank || |
| 427 old_list[found->second].last_forced_time != | 421 old_list[found->second].last_forced_time != |
| 428 new_list[i].last_forced_time) { | 422 new_list[i].last_forced_time) { |
| 429 MostVisitedURLWithRank moved; | 423 MostVisitedURLWithRank moved; |
| 430 moved.url = new_list[i]; | 424 moved.url = new_list[i]; |
| 431 moved.rank = rank; | 425 moved.rank = rank; |
| 432 delta->moved.push_back(moved); | 426 delta->moved.push_back(moved); |
| 433 } | 427 } |
| 434 found->second = kAlreadyFoundMarker; | 428 found->second = kAlreadyFoundMarker; |
| 435 } | 429 } |
| 436 } | 430 } |
| 437 | 431 |
| 438 // Any member without the special marker in the all_old_urls list means that | 432 // Any member without the special marker in the all_old_urls list means that |
| 439 // there wasn't a "new" URL that mapped to it, so it was deleted. | 433 // there wasn't a "new" URL that mapped to it, so it was deleted. |
| 440 for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin(); | 434 for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin(); |
| 441 i != all_old_urls.end(); ++i) { | 435 i != all_old_urls.end(); ++i) { |
| 442 if (i->second != kAlreadyFoundMarker) | 436 if (i->second != kAlreadyFoundMarker) |
| 443 delta->deleted.push_back(old_list[i->second]); | 437 delta->deleted.push_back(old_list[i->second]); |
| 444 } | 438 } |
| 445 } | 439 } |
| 446 | 440 |
| 447 base::CancelableTaskTracker::TaskId TopSitesImpl::StartQueryForMostVisited() { | 441 base::CancelableTaskTracker::TaskId |
| 442 TopSitesService::StartQueryForMostVisited() { |
| 448 DCHECK(loaded_); | 443 DCHECK(loaded_); |
| 449 if (!profile_) | 444 if (!profile_) |
| 450 return base::CancelableTaskTracker::kBadTaskId; | 445 return base::CancelableTaskTracker::kBadTaskId; |
| 451 | 446 |
| 452 HistoryService* hs = HistoryServiceFactory::GetForProfile( | 447 HistoryService* hs = |
| 453 profile_, Profile::EXPLICIT_ACCESS); | 448 HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); |
| 454 // |hs| may be null during unit tests. | 449 // |hs| may be null during unit tests. |
| 455 if (hs) { | 450 if (hs) { |
| 456 return hs->QueryMostVisitedURLs( | 451 return hs->QueryMostVisitedURLs( |
| 457 num_results_to_request_from_history(), | 452 num_results_to_request_from_history(), kDaysOfHistory, |
| 458 kDaysOfHistory, | 453 base::Bind(&TopSitesService::OnTopSitesAvailableFromHistory, |
| 459 base::Bind(&TopSitesImpl::OnTopSitesAvailableFromHistory, | |
| 460 base::Unretained(this)), | 454 base::Unretained(this)), |
| 461 &cancelable_task_tracker_); | 455 &cancelable_task_tracker_); |
| 462 } | 456 } |
| 463 return base::CancelableTaskTracker::kBadTaskId; | 457 return base::CancelableTaskTracker::kBadTaskId; |
| 464 } | 458 } |
| 465 | 459 |
| 466 bool TopSitesImpl::IsKnownURL(const GURL& url) { | 460 bool TopSitesService::IsKnownURL(const GURL& url) { |
| 467 return loaded_ && cache_->IsKnownURL(url); | 461 return loaded_ && cache_->IsKnownURL(url); |
| 468 } | 462 } |
| 469 | 463 |
| 470 const std::string& TopSitesImpl::GetCanonicalURLString(const GURL& url) const { | 464 const std::string& TopSitesService::GetCanonicalURLString( |
| 465 const GURL& url) const { |
| 471 return cache_->GetCanonicalURL(url).spec(); | 466 return cache_->GetCanonicalURL(url).spec(); |
| 472 } | 467 } |
| 473 | 468 |
| 474 bool TopSitesImpl::IsNonForcedFull() { | 469 bool TopSitesService::IsNonForcedFull() { |
| 475 return loaded_ && cache_->GetNumNonForcedURLs() >= kNonForcedTopSitesNumber; | 470 return loaded_ && cache_->GetNumNonForcedURLs() >= kNonForcedTopSitesNumber; |
| 476 } | 471 } |
| 477 | 472 |
| 478 bool TopSitesImpl::IsForcedFull() { | 473 bool TopSitesService::IsForcedFull() { |
| 479 return loaded_ && cache_->GetNumForcedURLs() >= kForcedTopSitesNumber; | 474 return loaded_ && cache_->GetNumForcedURLs() >= kForcedTopSitesNumber; |
| 480 } | 475 } |
| 481 | 476 |
| 482 TopSitesImpl::~TopSitesImpl() { | 477 TopSitesService::~TopSitesService() { |
| 483 } | 478 } |
| 484 | 479 |
| 485 bool TopSitesImpl::SetPageThumbnailNoDB( | 480 bool TopSitesService::SetPageThumbnailNoDB( |
| 486 const GURL& url, | 481 const GURL& url, |
| 487 const base::RefCountedMemory* thumbnail_data, | 482 const base::RefCountedMemory* thumbnail_data, |
| 488 const ThumbnailScore& score) { | 483 const ThumbnailScore& score) { |
| 489 // This should only be invoked when we know about the url. | 484 // This should only be invoked when we know about the url. |
| 490 DCHECK(cache_->IsKnownURL(url)); | 485 DCHECK(cache_->IsKnownURL(url)); |
| 491 | 486 |
| 492 const MostVisitedURL& most_visited = | 487 const MostVisitedURL& most_visited = |
| 493 cache_->top_sites()[cache_->GetURLIndex(url)]; | 488 cache_->top_sites()[cache_->GetURLIndex(url)]; |
| 494 Images* image = cache_->GetImage(url); | 489 Images* image = cache_->GetImage(url); |
| 495 | 490 |
| 496 // When comparing the thumbnail scores, we need to take into account the | 491 // When comparing the thumbnail scores, we need to take into account the |
| 497 // redirect hops, which are not generated when the thumbnail is because the | 492 // redirect hops, which are not generated when the thumbnail is because the |
| 498 // redirects weren't known. We fill that in here since we know the redirects. | 493 // redirects weren't known. We fill that in here since we know the redirects. |
| 499 ThumbnailScore new_score_with_redirects(score); | 494 ThumbnailScore new_score_with_redirects(score); |
| 500 new_score_with_redirects.redirect_hops_from_dest = | 495 new_score_with_redirects.redirect_hops_from_dest = |
| 501 GetRedirectDistanceForURL(most_visited, url); | 496 GetRedirectDistanceForURL(most_visited, url); |
| 502 | 497 |
| 503 if (!ShouldReplaceThumbnailWith(image->thumbnail_score, | 498 if (!ShouldReplaceThumbnailWith(image->thumbnail_score, |
| 504 new_score_with_redirects) && | 499 new_score_with_redirects) && |
| 505 image->thumbnail.get()) | 500 image->thumbnail.get()) |
| 506 return false; // The one we already have is better. | 501 return false; // The one we already have is better. |
| 507 | 502 |
| 508 image->thumbnail = const_cast<base::RefCountedMemory*>(thumbnail_data); | 503 image->thumbnail = const_cast<base::RefCountedMemory*>(thumbnail_data); |
| 509 image->thumbnail_score = new_score_with_redirects; | 504 image->thumbnail_score = new_score_with_redirects; |
| 510 | 505 |
| 511 ResetThreadSafeImageCache(); | 506 ResetThreadSafeImageCache(); |
| 512 return true; | 507 return true; |
| 513 } | 508 } |
| 514 | 509 |
| 515 bool TopSitesImpl::SetPageThumbnailEncoded( | 510 bool TopSitesService::SetPageThumbnailEncoded( |
| 516 const GURL& url, | 511 const GURL& url, |
| 517 const base::RefCountedMemory* thumbnail, | 512 const base::RefCountedMemory* thumbnail, |
| 518 const ThumbnailScore& score) { | 513 const ThumbnailScore& score) { |
| 519 if (!SetPageThumbnailNoDB(url, thumbnail, score)) | 514 if (!SetPageThumbnailNoDB(url, thumbnail, score)) |
| 520 return false; | 515 return false; |
| 521 | 516 |
| 522 // Update the database. | 517 // Update the database. |
| 523 if (!cache_->IsKnownURL(url)) | 518 if (!cache_->IsKnownURL(url)) |
| 524 return false; | 519 return false; |
| 525 | 520 |
| 526 size_t index = cache_->GetURLIndex(url); | 521 size_t index = cache_->GetURLIndex(url); |
| 527 int url_rank = index - cache_->GetNumForcedURLs(); | 522 int url_rank = index - cache_->GetNumForcedURLs(); |
| 528 const MostVisitedURL& most_visited = cache_->top_sites()[index]; | 523 const MostVisitedURL& most_visited = cache_->top_sites()[index]; |
| 529 backend_->SetPageThumbnail(most_visited, | 524 backend_->SetPageThumbnail(most_visited, url_rank < 0 ? -1 : url_rank, |
| 530 url_rank < 0 ? -1 : url_rank, | |
| 531 *(cache_->GetImage(most_visited.url))); | 525 *(cache_->GetImage(most_visited.url))); |
| 532 return true; | 526 return true; |
| 533 } | 527 } |
| 534 | 528 |
| 535 // static | 529 // static |
| 536 bool TopSitesImpl::EncodeBitmap(const gfx::Image& bitmap, | 530 bool TopSitesService::EncodeBitmap( |
| 537 scoped_refptr<base::RefCountedBytes>* bytes) { | 531 const gfx::Image& bitmap, |
| 532 scoped_refptr<base::RefCountedBytes>* bytes) { |
| 538 if (bitmap.IsEmpty()) | 533 if (bitmap.IsEmpty()) |
| 539 return false; | 534 return false; |
| 540 *bytes = new base::RefCountedBytes(); | 535 *bytes = new base::RefCountedBytes(); |
| 541 std::vector<unsigned char> data; | 536 std::vector<unsigned char> data; |
| 542 if (!gfx::JPEG1xEncodedDataFromImage(bitmap, kTopSitesImageQuality, &data)) | 537 if (!gfx::JPEG1xEncodedDataFromImage(bitmap, kTopSitesImageQuality, &data)) |
| 543 return false; | 538 return false; |
| 544 | 539 |
| 545 // As we're going to cache this data, make sure the vector is only as big as | 540 // As we're going to cache this data, make sure the vector is only as big as |
| 546 // it needs to be, as JPEGCodec::Encode() over-allocates data.capacity(). | 541 // it needs to be, as JPEGCodec::Encode() over-allocates data.capacity(). |
| 547 // (In a C++0x future, we can just call shrink_to_fit() in Encode()) | 542 // (In a C++0x future, we can just call shrink_to_fit() in Encode()) |
| 548 (*bytes)->data() = data; | 543 (*bytes)->data() = data; |
| 549 return true; | 544 return true; |
| 550 } | 545 } |
| 551 | 546 |
| 552 void TopSitesImpl::RemoveTemporaryThumbnailByURL(const GURL& url) { | 547 void TopSitesService::RemoveTemporaryThumbnailByURL(const GURL& url) { |
| 553 for (TempImages::iterator i = temp_images_.begin(); i != temp_images_.end(); | 548 for (TempImages::iterator i = temp_images_.begin(); i != temp_images_.end(); |
| 554 ++i) { | 549 ++i) { |
| 555 if (i->first == url) { | 550 if (i->first == url) { |
| 556 temp_images_.erase(i); | 551 temp_images_.erase(i); |
| 557 return; | 552 return; |
| 558 } | 553 } |
| 559 } | 554 } |
| 560 } | 555 } |
| 561 | 556 |
| 562 void TopSitesImpl::AddTemporaryThumbnail( | 557 void TopSitesService::AddTemporaryThumbnail( |
| 563 const GURL& url, | 558 const GURL& url, |
| 564 const base::RefCountedMemory* thumbnail, | 559 const base::RefCountedMemory* thumbnail, |
| 565 const ThumbnailScore& score) { | 560 const ThumbnailScore& score) { |
| 566 if (temp_images_.size() == kMaxTempTopImages) | 561 if (temp_images_.size() == kMaxTempTopImages) |
| 567 temp_images_.erase(temp_images_.begin()); | 562 temp_images_.erase(temp_images_.begin()); |
| 568 | 563 |
| 569 TempImage image; | 564 TempImage image; |
| 570 image.first = url; | 565 image.first = url; |
| 571 image.second.thumbnail = const_cast<base::RefCountedMemory*>(thumbnail); | 566 image.second.thumbnail = const_cast<base::RefCountedMemory*>(thumbnail); |
| 572 image.second.thumbnail_score = score; | 567 image.second.thumbnail_score = score; |
| 573 temp_images_.push_back(image); | 568 temp_images_.push_back(image); |
| 574 } | 569 } |
| 575 | 570 |
| 576 void TopSitesImpl::TimerFired() { | 571 void TopSitesService::TimerFired() { |
| 577 StartQueryForMostVisited(); | 572 StartQueryForMostVisited(); |
| 578 } | 573 } |
| 579 | 574 |
| 580 // static | 575 // static |
| 581 int TopSitesImpl::GetRedirectDistanceForURL(const MostVisitedURL& most_visited, | 576 int TopSitesService::GetRedirectDistanceForURL( |
| 582 const GURL& url) { | 577 const MostVisitedURL& most_visited, |
| 578 const GURL& url) { |
| 583 for (size_t i = 0; i < most_visited.redirects.size(); i++) { | 579 for (size_t i = 0; i < most_visited.redirects.size(); i++) { |
| 584 if (most_visited.redirects[i] == url) | 580 if (most_visited.redirects[i] == url) |
| 585 return static_cast<int>(most_visited.redirects.size() - i - 1); | 581 return static_cast<int>(most_visited.redirects.size() - i - 1); |
| 586 } | 582 } |
| 587 NOTREACHED() << "URL should always be found."; | 583 NOTREACHED() << "URL should always be found."; |
| 588 return 0; | 584 return 0; |
| 589 } | 585 } |
| 590 | 586 |
| 591 MostVisitedURLList TopSitesImpl::GetPrepopulatePages() { | 587 MostVisitedURLList TopSitesService::GetPrepopulatePages() { |
| 592 MostVisitedURLList urls; | 588 MostVisitedURLList urls; |
| 593 urls.resize(kPrepopulatedPagesCount); | 589 urls.resize(kPrepopulatedPagesCount); |
| 594 for (int i = 0; i < kPrepopulatedPagesCount; ++i) { | 590 for (int i = 0; i < kPrepopulatedPagesCount; ++i) { |
| 595 MostVisitedURL& url = urls[i]; | 591 MostVisitedURL& url = urls[i]; |
| 596 url.url = GURL(prepopulated_page_urls_[i]); | 592 url.url = GURL(prepopulated_page_urls_[i]); |
| 597 url.redirects.push_back(url.url); | 593 url.redirects.push_back(url.url); |
| 598 url.title = l10n_util::GetStringUTF16(kPrepopulatedPages[i].title_id); | 594 url.title = l10n_util::GetStringUTF16(kPrepopulatedPages[i].title_id); |
| 599 } | 595 } |
| 600 return urls; | 596 return urls; |
| 601 } | 597 } |
| 602 | 598 |
| 603 bool TopSitesImpl::loaded() const { | 599 bool TopSitesService::loaded() const { |
| 604 return loaded_; | 600 return loaded_; |
| 605 } | 601 } |
| 606 | 602 |
| 607 bool TopSitesImpl::AddForcedURL(const GURL& url, const base::Time& time) { | 603 bool TopSitesService::AddForcedURL(const GURL& url, const base::Time& time) { |
| 608 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 604 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 609 size_t num_forced = cache_->GetNumForcedURLs(); | 605 size_t num_forced = cache_->GetNumForcedURLs(); |
| 610 MostVisitedURLList new_list(cache_->top_sites()); | 606 MostVisitedURLList new_list(cache_->top_sites()); |
| 611 MostVisitedURL new_url; | 607 MostVisitedURL new_url; |
| 612 | 608 |
| 613 if (cache_->IsKnownURL(url)) { | 609 if (cache_->IsKnownURL(url)) { |
| 614 size_t index = cache_->GetURLIndex(url); | 610 size_t index = cache_->GetURLIndex(url); |
| 615 // Do nothing if we currently have that URL as non-forced. | 611 // Do nothing if we currently have that URL as non-forced. |
| 616 if (new_list[index].last_forced_time.is_null()) | 612 if (new_list[index].last_forced_time.is_null()) |
| 617 return false; | 613 return false; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 630 // since this is almost always where it needs to go, unless the user's local | 626 // since this is almost always where it needs to go, unless the user's local |
| 631 // clock is fiddled with. | 627 // clock is fiddled with. |
| 632 MostVisitedURLList::iterator mid = new_list.begin() + num_forced; | 628 MostVisitedURLList::iterator mid = new_list.begin() + num_forced; |
| 633 new_list.insert(mid, new_url); | 629 new_list.insert(mid, new_url); |
| 634 mid = new_list.begin() + num_forced; // Mid was invalidated. | 630 mid = new_list.begin() + num_forced; // Mid was invalidated. |
| 635 std::inplace_merge(new_list.begin(), mid, mid + 1, ForcedURLComparator); | 631 std::inplace_merge(new_list.begin(), mid, mid + 1, ForcedURLComparator); |
| 636 SetTopSites(new_list); | 632 SetTopSites(new_list); |
| 637 return true; | 633 return true; |
| 638 } | 634 } |
| 639 | 635 |
| 640 bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls, | 636 bool TopSitesService::AddPrepopulatedPages(MostVisitedURLList* urls, |
| 641 size_t num_forced_urls) { | 637 size_t num_forced_urls) { |
| 642 bool added = false; | 638 bool added = false; |
| 643 MostVisitedURLList prepopulate_urls = GetPrepopulatePages(); | 639 MostVisitedURLList prepopulate_urls = GetPrepopulatePages(); |
| 644 for (size_t i = 0; i < prepopulate_urls.size(); ++i) { | 640 for (size_t i = 0; i < prepopulate_urls.size(); ++i) { |
| 645 if (urls->size() - num_forced_urls < kNonForcedTopSitesNumber && | 641 if (urls->size() - num_forced_urls < kNonForcedTopSitesNumber && |
| 646 IndexOf(*urls, prepopulate_urls[i].url) == -1) { | 642 IndexOf(*urls, prepopulate_urls[i].url) == -1) { |
| 647 urls->push_back(prepopulate_urls[i]); | 643 urls->push_back(prepopulate_urls[i]); |
| 648 added = true; | 644 added = true; |
| 649 } | 645 } |
| 650 } | 646 } |
| 651 return added; | 647 return added; |
| 652 } | 648 } |
| 653 | 649 |
| 654 size_t TopSitesImpl::MergeCachedForcedURLs(MostVisitedURLList* new_list) { | 650 size_t TopSitesService::MergeCachedForcedURLs(MostVisitedURLList* new_list) { |
| 655 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 651 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 656 // Add all the new URLs for quick lookup. Take that opportunity to count the | 652 // Add all the new URLs for quick lookup. Take that opportunity to count the |
| 657 // number of forced URLs in |new_list|. | 653 // number of forced URLs in |new_list|. |
| 658 std::set<GURL> all_new_urls; | 654 std::set<GURL> all_new_urls; |
| 659 size_t num_forced = 0; | 655 size_t num_forced = 0; |
| 660 for (size_t i = 0; i < new_list->size(); ++i) { | 656 for (size_t i = 0; i < new_list->size(); ++i) { |
| 661 for (size_t j = 0; j < (*new_list)[i].redirects.size(); j++) { | 657 for (size_t j = 0; j < (*new_list)[i].redirects.size(); j++) { |
| 662 all_new_urls.insert((*new_list)[i].redirects[j]); | 658 all_new_urls.insert((*new_list)[i].redirects[j]); |
| 663 } | 659 } |
| 664 if (!(*new_list)[i].last_forced_time.is_null()) | 660 if (!(*new_list)[i].last_forced_time.is_null()) |
| 665 ++num_forced; | 661 ++num_forced; |
| 666 } | 662 } |
| 667 | 663 |
| 668 // Keep the forced URLs from |cache_| that are not found in |new_list|. | 664 // Keep the forced URLs from |cache_| that are not found in |new_list|. |
| 669 MostVisitedURLList filtered_forced_urls; | 665 MostVisitedURLList filtered_forced_urls; |
| 670 for (size_t i = 0; i < cache_->GetNumForcedURLs(); ++i) { | 666 for (size_t i = 0; i < cache_->GetNumForcedURLs(); ++i) { |
| 671 if (all_new_urls.find(cache_->top_sites()[i].url) == all_new_urls.end()) | 667 if (all_new_urls.find(cache_->top_sites()[i].url) == all_new_urls.end()) |
| 672 filtered_forced_urls.push_back(cache_->top_sites()[i]); | 668 filtered_forced_urls.push_back(cache_->top_sites()[i]); |
| 673 } | 669 } |
| 674 num_forced += filtered_forced_urls.size(); | 670 num_forced += filtered_forced_urls.size(); |
| 675 | 671 |
| 676 // Prepend forced URLs and sort in order of ascending |last_forced_time|. | 672 // Prepend forced URLs and sort in order of ascending |last_forced_time|. |
| 677 new_list->insert(new_list->begin(), filtered_forced_urls.begin(), | 673 new_list->insert(new_list->begin(), filtered_forced_urls.begin(), |
| 678 filtered_forced_urls.end()); | 674 filtered_forced_urls.end()); |
| 679 std::inplace_merge( | 675 std::inplace_merge(new_list->begin(), |
| 680 new_list->begin(), new_list->begin() + filtered_forced_urls.size(), | 676 new_list->begin() + filtered_forced_urls.size(), |
| 681 new_list->begin() + num_forced, ForcedURLComparator); | 677 new_list->begin() + num_forced, ForcedURLComparator); |
| 682 | 678 |
| 683 // Drop older forced URLs if the list overflows. Since forced URLs are always | 679 // Drop older forced URLs if the list overflows. Since forced URLs are always |
| 684 // sort in increasing order of |last_forced_time|, drop the first ones. | 680 // sort in increasing order of |last_forced_time|, drop the first ones. |
| 685 if (num_forced > kForcedTopSitesNumber) { | 681 if (num_forced > kForcedTopSitesNumber) { |
| 686 new_list->erase(new_list->begin(), | 682 new_list->erase(new_list->begin(), |
| 687 new_list->begin() + (num_forced - kForcedTopSitesNumber)); | 683 new_list->begin() + (num_forced - kForcedTopSitesNumber)); |
| 688 num_forced = kForcedTopSitesNumber; | 684 num_forced = kForcedTopSitesNumber; |
| 689 } | 685 } |
| 690 | 686 |
| 691 return num_forced; | 687 return num_forced; |
| 692 } | 688 } |
| 693 | 689 |
| 694 void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls, | 690 void TopSitesService::ApplyBlacklist(const MostVisitedURLList& urls, |
| 695 MostVisitedURLList* out) { | 691 MostVisitedURLList* out) { |
| 696 // Log the number of times ApplyBlacklist is called so we can compute the | 692 // Log the number of times ApplyBlacklist is called so we can compute the |
| 697 // average number of blacklisted items per user. | 693 // average number of blacklisted items per user. |
| 698 const base::DictionaryValue* blacklist = | 694 const base::DictionaryValue* blacklist = |
| 699 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); | 695 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); |
| 700 UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true); | 696 UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true); |
| 701 UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems", | 697 UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems", |
| 702 (blacklist ? blacklist->size() : 0)); | 698 (blacklist ? blacklist->size() : 0)); |
| 703 size_t num_non_forced_urls = 0; | 699 size_t num_non_forced_urls = 0; |
| 704 size_t num_forced_urls = 0; | 700 size_t num_forced_urls = 0; |
| 705 for (size_t i = 0; i < urls.size(); ++i) { | 701 for (size_t i = 0; i < urls.size(); ++i) { |
| 706 if (!IsBlacklisted(urls[i].url)) { | 702 if (!IsBlacklisted(urls[i].url)) { |
| 707 if (urls[i].last_forced_time.is_null()) { | 703 if (urls[i].last_forced_time.is_null()) { |
| 708 // Non-forced URL. | 704 // Non-forced URL. |
| 709 if (num_non_forced_urls >= kNonForcedTopSitesNumber) | 705 if (num_non_forced_urls >= kNonForcedTopSitesNumber) |
| 710 continue; | 706 continue; |
| 711 num_non_forced_urls++; | 707 num_non_forced_urls++; |
| 712 } else { | 708 } else { |
| 713 // Forced URL. | 709 // Forced URL. |
| 714 if (num_forced_urls >= kForcedTopSitesNumber) | 710 if (num_forced_urls >= kForcedTopSitesNumber) |
| 715 continue; | 711 continue; |
| 716 num_forced_urls++; | 712 num_forced_urls++; |
| 717 } | 713 } |
| 718 out->push_back(urls[i]); | 714 out->push_back(urls[i]); |
| 719 } | 715 } |
| 720 } | 716 } |
| 721 } | 717 } |
| 722 | 718 |
| 723 std::string TopSitesImpl::GetURLHash(const GURL& url) { | 719 std::string TopSitesService::GetURLHash(const GURL& url) { |
| 724 // We don't use canonical URLs here to be able to blacklist only one of | 720 // 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'. | 721 // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. |
| 726 return base::MD5String(url.spec()); | 722 return base::MD5String(url.spec()); |
| 727 } | 723 } |
| 728 | 724 |
| 729 base::TimeDelta TopSitesImpl::GetUpdateDelay() { | 725 base::TimeDelta TopSitesService::GetUpdateDelay() { |
| 730 if (cache_->top_sites().size() <= kPrepopulatedPagesCount) | 726 if (cache_->top_sites().size() <= kPrepopulatedPagesCount) |
| 731 return base::TimeDelta::FromSeconds(30); | 727 return base::TimeDelta::FromSeconds(30); |
| 732 | 728 |
| 733 int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes; | 729 int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes; |
| 734 int64 minutes = kMaxUpdateIntervalMinutes - | 730 int64 minutes = kMaxUpdateIntervalMinutes - |
| 735 last_num_urls_changed_ * range / cache_->top_sites().size(); | 731 last_num_urls_changed_ * range / cache_->top_sites().size(); |
| 736 return base::TimeDelta::FromMinutes(minutes); | 732 return base::TimeDelta::FromMinutes(minutes); |
| 737 } | 733 } |
| 738 | 734 |
| 739 void TopSitesImpl::Observe(int type, | 735 void TopSitesService::Observe(int type, |
| 740 const content::NotificationSource& source, | 736 const content::NotificationSource& source, |
| 741 const content::NotificationDetails& details) { | 737 const content::NotificationDetails& details) { |
| 742 if (!loaded_) | 738 if (!loaded_) |
| 743 return; | 739 return; |
| 744 | 740 |
| 745 if (type == chrome::NOTIFICATION_HISTORY_URLS_DELETED) { | 741 if (type == chrome::NOTIFICATION_HISTORY_URLS_DELETED) { |
| 746 content::Details<history::URLsDeletedDetails> deleted_details(details); | 742 content::Details<history::URLsDeletedDetails> deleted_details(details); |
| 747 if (deleted_details->all_history) { | 743 if (deleted_details->all_history) { |
| 748 SetTopSites(MostVisitedURLList()); | 744 SetTopSites(MostVisitedURLList()); |
| 749 backend_->ResetDatabase(); | 745 backend_->ResetDatabase(); |
| 750 } else { | 746 } else { |
| 751 std::set<size_t> indices_to_delete; // Indices into top_sites_. | 747 std::set<size_t> indices_to_delete; // Indices into top_sites_. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 779 const GURL& url = load_details->entry->GetURL(); | 775 const GURL& url = load_details->entry->GetURL(); |
| 780 if (!cache_->IsKnownURL(url) && HistoryService::CanAddURL(url)) { | 776 if (!cache_->IsKnownURL(url) && HistoryService::CanAddURL(url)) { |
| 781 // To avoid slamming history we throttle requests when the url updates. | 777 // To avoid slamming history we throttle requests when the url updates. |
| 782 // To do otherwise negatively impacts perf tests. | 778 // To do otherwise negatively impacts perf tests. |
| 783 RestartQueryForTopSitesTimer(GetUpdateDelay()); | 779 RestartQueryForTopSitesTimer(GetUpdateDelay()); |
| 784 } | 780 } |
| 785 } | 781 } |
| 786 } | 782 } |
| 787 } | 783 } |
| 788 | 784 |
| 789 void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites) { | 785 void TopSitesService::SetTopSites(const MostVisitedURLList& new_top_sites) { |
| 790 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 786 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 791 | 787 |
| 792 MostVisitedURLList top_sites(new_top_sites); | 788 MostVisitedURLList top_sites(new_top_sites); |
| 793 size_t num_forced_urls = MergeCachedForcedURLs(&top_sites); | 789 size_t num_forced_urls = MergeCachedForcedURLs(&top_sites); |
| 794 AddPrepopulatedPages(&top_sites, num_forced_urls); | 790 AddPrepopulatedPages(&top_sites, num_forced_urls); |
| 795 | 791 |
| 796 TopSitesDelta delta; | 792 TopSitesDelta delta; |
| 797 DiffMostVisited(cache_->top_sites(), top_sites, &delta); | 793 DiffMostVisited(cache_->top_sites(), top_sites, &delta); |
| 798 if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty()) { | 794 if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty()) { |
| 799 backend_->UpdateTopSites(delta); | 795 backend_->UpdateTopSites(delta); |
| 800 } | 796 } |
| 801 | 797 |
| 802 last_num_urls_changed_ = delta.added.size() + delta.moved.size(); | 798 last_num_urls_changed_ = delta.added.size() + delta.moved.size(); |
| 803 | 799 |
| 804 // We always do the following steps (setting top sites in cache, and resetting | 800 // We always do the following steps (setting top sites in cache, and resetting |
| 805 // thread safe cache ...) as this method is invoked during startup at which | 801 // thread safe cache ...) as this method is invoked during startup at which |
| 806 // point the caches haven't been updated yet. | 802 // point the caches haven't been updated yet. |
| 807 cache_->SetTopSites(top_sites); | 803 cache_->SetTopSites(top_sites); |
| 808 | 804 |
| 809 // See if we have any tmp thumbnails for the new sites. | 805 // See if we have any tmp thumbnails for the new sites. |
| 810 if (!temp_images_.empty()) { | 806 if (!temp_images_.empty()) { |
| 811 for (size_t i = 0; i < top_sites.size(); ++i) { | 807 for (size_t i = 0; i < top_sites.size(); ++i) { |
| 812 const MostVisitedURL& mv = top_sites[i]; | 808 const MostVisitedURL& mv = top_sites[i]; |
| 813 GURL canonical_url = cache_->GetCanonicalURL(mv.url); | 809 GURL canonical_url = cache_->GetCanonicalURL(mv.url); |
| 814 // At the time we get the thumbnail redirects aren't known, so we have to | 810 // At the time we get the thumbnail redirects aren't known, so we have to |
| 815 // iterate through all the images. | 811 // iterate through all the images. |
| 816 for (TempImages::iterator it = temp_images_.begin(); | 812 for (TempImages::iterator it = temp_images_.begin(); |
| 817 it != temp_images_.end(); ++it) { | 813 it != temp_images_.end(); ++it) { |
| 818 if (canonical_url == cache_->GetCanonicalURL(it->first)) { | 814 if (canonical_url == cache_->GetCanonicalURL(it->first)) { |
| 819 SetPageThumbnailEncoded( | 815 SetPageThumbnailEncoded(mv.url, it->second.thumbnail.get(), |
| 820 mv.url, it->second.thumbnail.get(), it->second.thumbnail_score); | 816 it->second.thumbnail_score); |
| 821 temp_images_.erase(it); | 817 temp_images_.erase(it); |
| 822 break; | 818 break; |
| 823 } | 819 } |
| 824 } | 820 } |
| 825 } | 821 } |
| 826 } | 822 } |
| 827 | 823 |
| 828 if (top_sites.size() - num_forced_urls >= kNonForcedTopSitesNumber) | 824 if (top_sites.size() - num_forced_urls >= kNonForcedTopSitesNumber) |
| 829 temp_images_.clear(); | 825 temp_images_.clear(); |
| 830 | 826 |
| 831 ResetThreadSafeCache(); | 827 ResetThreadSafeCache(); |
| 832 ResetThreadSafeImageCache(); | 828 ResetThreadSafeImageCache(); |
| 833 NotifyTopSitesChanged(); | 829 NotifyTopSitesChanged(); |
| 834 | 830 |
| 835 // Restart the timer that queries history for top sites. This is done to | 831 // Restart the timer that queries history for top sites. This is done to |
| 836 // ensure we stay in sync with history. | 832 // ensure we stay in sync with history. |
| 837 RestartQueryForTopSitesTimer(GetUpdateDelay()); | 833 RestartQueryForTopSitesTimer(GetUpdateDelay()); |
| 838 } | 834 } |
| 839 | 835 |
| 840 int TopSitesImpl::num_results_to_request_from_history() const { | 836 int TopSitesService::num_results_to_request_from_history() const { |
| 841 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 837 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 842 | 838 |
| 843 const base::DictionaryValue* blacklist = | 839 const base::DictionaryValue* blacklist = |
| 844 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); | 840 profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); |
| 845 return kNonForcedTopSitesNumber + (blacklist ? blacklist->size() : 0); | 841 return kNonForcedTopSitesNumber + (blacklist ? blacklist->size() : 0); |
| 846 } | 842 } |
| 847 | 843 |
| 848 void TopSitesImpl::MoveStateToLoaded() { | 844 void TopSitesService::MoveStateToLoaded() { |
| 849 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 845 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 850 | 846 |
| 851 MostVisitedURLList filtered_urls_all; | 847 MostVisitedURLList filtered_urls_all; |
| 852 MostVisitedURLList filtered_urls_nonforced; | 848 MostVisitedURLList filtered_urls_nonforced; |
| 853 PendingCallbacks pending_callbacks; | 849 PendingCallbacks pending_callbacks; |
| 854 { | 850 { |
| 855 base::AutoLock lock(lock_); | 851 base::AutoLock lock(lock_); |
| 856 | 852 |
| 857 if (loaded_) | 853 if (loaded_) |
| 858 return; // Don't do anything if we're already loaded. | 854 return; // Don't do anything if we're already loaded. |
| 859 loaded_ = true; | 855 loaded_ = true; |
| 860 | 856 |
| 861 // Now that we're loaded we can service the queued up callbacks. Copy them | 857 // Now that we're loaded we can service the queued up callbacks. Copy them |
| 862 // here and service them outside the lock. | 858 // here and service them outside the lock. |
| 863 if (!pending_callbacks_.empty()) { | 859 if (!pending_callbacks_.empty()) { |
| 864 // We always filter out forced URLs because callers of GetMostVisitedURLs | 860 // We always filter out forced URLs because callers of GetMostVisitedURLs |
| 865 // are not interested in them. | 861 // are not interested in them. |
| 866 filtered_urls_all = thread_safe_cache_->top_sites(); | 862 filtered_urls_all = thread_safe_cache_->top_sites(); |
| 867 filtered_urls_nonforced.assign(thread_safe_cache_->top_sites().begin() + | 863 filtered_urls_nonforced.assign(thread_safe_cache_->top_sites().begin() + |
| 868 thread_safe_cache_->GetNumForcedURLs(), | 864 thread_safe_cache_->GetNumForcedURLs(), |
| 869 thread_safe_cache_->top_sites().end()); | 865 thread_safe_cache_->top_sites().end()); |
| 870 pending_callbacks.swap(pending_callbacks_); | 866 pending_callbacks.swap(pending_callbacks_); |
| 871 } | 867 } |
| 872 } | 868 } |
| 873 | 869 |
| 874 for (size_t i = 0; i < pending_callbacks.size(); i++) | 870 for (size_t i = 0; i < pending_callbacks.size(); i++) |
| 875 pending_callbacks[i].Run(filtered_urls_all, filtered_urls_nonforced); | 871 pending_callbacks[i].Run(filtered_urls_all, filtered_urls_nonforced); |
| 876 | 872 |
| 877 NotifyTopSitesLoaded(); | 873 NotifyTopSitesLoaded(); |
| 878 } | 874 } |
| 879 | 875 |
| 880 void TopSitesImpl::ResetThreadSafeCache() { | 876 void TopSitesService::ResetThreadSafeCache() { |
| 881 base::AutoLock lock(lock_); | 877 base::AutoLock lock(lock_); |
| 882 MostVisitedURLList cached; | 878 MostVisitedURLList cached; |
| 883 ApplyBlacklist(cache_->top_sites(), &cached); | 879 ApplyBlacklist(cache_->top_sites(), &cached); |
| 884 thread_safe_cache_->SetTopSites(cached); | 880 thread_safe_cache_->SetTopSites(cached); |
| 885 } | 881 } |
| 886 | 882 |
| 887 void TopSitesImpl::ResetThreadSafeImageCache() { | 883 void TopSitesService::ResetThreadSafeImageCache() { |
| 888 base::AutoLock lock(lock_); | 884 base::AutoLock lock(lock_); |
| 889 thread_safe_cache_->SetThumbnails(cache_->images()); | 885 thread_safe_cache_->SetThumbnails(cache_->images()); |
| 890 } | 886 } |
| 891 | 887 |
| 892 void TopSitesImpl::RestartQueryForTopSitesTimer(base::TimeDelta delta) { | 888 void TopSitesService::RestartQueryForTopSitesTimer(base::TimeDelta delta) { |
| 893 if (timer_.IsRunning() && ((timer_start_time_ + timer_.GetCurrentDelay()) < | 889 if (timer_.IsRunning() && ((timer_start_time_ + timer_.GetCurrentDelay()) < |
| 894 (base::TimeTicks::Now() + delta))) { | 890 (base::TimeTicks::Now() + delta))) { |
| 895 return; | 891 return; |
| 896 } | 892 } |
| 897 | 893 |
| 898 timer_start_time_ = base::TimeTicks::Now(); | 894 timer_start_time_ = base::TimeTicks::Now(); |
| 899 timer_.Stop(); | 895 timer_.Stop(); |
| 900 timer_.Start(FROM_HERE, delta, this, &TopSitesImpl::TimerFired); | 896 timer_.Start(FROM_HERE, delta, this, &TopSitesService::TimerFired); |
| 901 } | 897 } |
| 902 | 898 |
| 903 void TopSitesImpl::OnGotMostVisitedThumbnails( | 899 void TopSitesService::OnGotMostVisitedThumbnails( |
| 904 const scoped_refptr<MostVisitedThumbnails>& thumbnails) { | 900 const scoped_refptr<MostVisitedThumbnails>& thumbnails) { |
| 905 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 901 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 906 | 902 |
| 907 // Set the top sites directly in the cache so that SetTopSites diffs | 903 // Set the top sites directly in the cache so that SetTopSites diffs |
| 908 // correctly. | 904 // correctly. |
| 909 cache_->SetTopSites(thumbnails->most_visited); | 905 cache_->SetTopSites(thumbnails->most_visited); |
| 910 SetTopSites(thumbnails->most_visited); | 906 SetTopSites(thumbnails->most_visited); |
| 911 cache_->SetThumbnails(thumbnails->url_to_images_map); | 907 cache_->SetThumbnails(thumbnails->url_to_images_map); |
| 912 | 908 |
| 913 ResetThreadSafeImageCache(); | 909 ResetThreadSafeImageCache(); |
| 914 | 910 |
| 915 MoveStateToLoaded(); | 911 MoveStateToLoaded(); |
| 916 | 912 |
| 917 // Start a timer that refreshes top sites from history. | 913 // Start a timer that refreshes top sites from history. |
| 918 RestartQueryForTopSitesTimer( | 914 RestartQueryForTopSitesTimer( |
| 919 base::TimeDelta::FromSeconds(kUpdateIntervalSecs)); | 915 base::TimeDelta::FromSeconds(kUpdateIntervalSecs)); |
| 920 } | 916 } |
| 921 | 917 |
| 922 void TopSitesImpl::OnTopSitesAvailableFromHistory( | 918 void TopSitesService::OnTopSitesAvailableFromHistory( |
| 923 const MostVisitedURLList* pages) { | 919 const MostVisitedURLList* pages) { |
| 924 DCHECK(pages); | 920 DCHECK(pages); |
| 925 SetTopSites(*pages); | 921 SetTopSites(*pages); |
| 926 } | 922 } |
| 927 | 923 |
| 928 } // namespace history | 924 } // namespace history |
| OLD | NEW |