Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(701)

Side by Side Diff: chrome/browser/history/top_sites_service.cc

Issue 815983002: Topsites become keyedService based. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698