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 |