OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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.h" | 5 #include "chrome/browser/history/top_sites.h" |
6 | 6 |
| 7 #include <algorithm> |
| 8 |
| 9 #include "base/file_util.h" |
7 #include "base/logging.h" | 10 #include "base/logging.h" |
8 #include "chrome/browser/profile.h" | 11 #include "chrome/browser/profile.h" |
9 #include "chrome/browser/history/top_sites_database.h" | 12 #include "chrome/browser/history/top_sites_database.h" |
| 13 #include "chrome/browser/history/history_notifications.h" |
10 #include "chrome/browser/history/page_usage_data.h" | 14 #include "chrome/browser/history/page_usage_data.h" |
11 #include "gfx/codec/jpeg_codec.h" | 15 #include "gfx/codec/jpeg_codec.h" |
12 #include "third_party/skia/include/core/SkBitmap.h" | 16 #include "third_party/skia/include/core/SkBitmap.h" |
13 | 17 |
14 namespace history { | 18 namespace history { |
15 | 19 |
16 // How many top sites to store in the cache. | 20 // How many top sites to store in the cache. |
17 static const int kTopSitesNumber = 20; | 21 static const int kTopSitesNumber = 20; |
18 static const int kDaysOfHistory = 90; | 22 static const int kDaysOfHistory = 90; |
19 static const int64 kUpdateIntervalSecs = 15; // TODO(Nik): come up | 23 static const int64 kUpdateIntervalSecs = 15; // Time from startup to DB query. |
20 // with an algorithm for timing. | 24 // Intervals between requests to HistoryService. |
| 25 static const int64 kMinUpdateIntervalMinutes = 1; |
| 26 static const int64 kMaxUpdateIntervalMinutes = 60; |
| 27 |
21 | 28 |
22 TopSites::TopSites(Profile* profile) : profile_(profile), | 29 TopSites::TopSites(Profile* profile) : profile_(profile), |
23 mock_history_service_(NULL) { | 30 mock_history_service_(NULL), |
| 31 last_num_urls_changed_(0) { |
| 32 registrar_.Add(this, NotificationType::HISTORY_URLS_DELETED, |
| 33 Source<Profile>(profile_)); |
24 } | 34 } |
25 | 35 |
26 TopSites::~TopSites() { | 36 TopSites::~TopSites() { |
| 37 timer_.Stop(); |
27 } | 38 } |
28 | 39 |
29 void TopSites::Init() { | 40 void TopSites::Init(const FilePath& db_name) { |
30 if (db_.get()) | 41 db_path_ = db_name; |
31 ReadDatabase(); | 42 db_.reset(new TopSitesDatabaseImpl()); |
| 43 if (!db_->Init(db_name)) |
| 44 return; |
| 45 |
| 46 ReadDatabase(); |
32 | 47 |
33 // Start the one-shot timer. | 48 // Start the one-shot timer. |
34 timer_.Start(base::TimeDelta::FromSeconds(kUpdateIntervalSecs), this, | 49 timer_.Start(base::TimeDelta::FromSeconds(kUpdateIntervalSecs), this, |
35 &TopSites::StartQueryForMostVisited); | 50 &TopSites::StartQueryForMostVisited); |
36 } | 51 } |
37 | 52 |
38 void TopSites::ReadDatabase() { | 53 void TopSites::ReadDatabase() { |
39 DCHECK(db_.get()); | 54 DCHECK(db_.get()); |
40 { | 55 { |
41 AutoLock lock(lock_); | 56 AutoLock lock(lock_); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 void TopSites::UpdateMostVisited(MostVisitedURLList* most_visited) { | 148 void TopSites::UpdateMostVisited(MostVisitedURLList* most_visited) { |
134 lock_.AssertAcquired(); | 149 lock_.AssertAcquired(); |
135 // TODO(brettw) filter for blacklist! | 150 // TODO(brettw) filter for blacklist! |
136 | 151 |
137 if (!top_sites_.empty()) { | 152 if (!top_sites_.empty()) { |
138 std::vector<size_t> added; // Indices into most_visited. | 153 std::vector<size_t> added; // Indices into most_visited. |
139 std::vector<size_t> deleted; // Indices into top_sites_. | 154 std::vector<size_t> deleted; // Indices into top_sites_. |
140 std::vector<size_t> moved; // Indices into most_visited. | 155 std::vector<size_t> moved; // Indices into most_visited. |
141 DiffMostVisited(top_sites_, *most_visited, &added, &deleted, &moved); | 156 DiffMostVisited(top_sites_, *most_visited, &added, &deleted, &moved); |
142 | 157 |
| 158 // #added == #deleted; #added + #moved = total. |
| 159 last_num_urls_changed_ = added.size() + moved.size(); |
| 160 |
143 // Process the diff: delete from images and disk, add to disk. | 161 // Process the diff: delete from images and disk, add to disk. |
144 // Delete all the thumbnails associated with URLs that were deleted. | 162 // Delete all the thumbnails associated with URLs that were deleted. |
145 for (size_t i = 0; i < deleted.size(); i++) { | 163 for (size_t i = 0; i < deleted.size(); i++) { |
146 MostVisitedURL deleted_url = top_sites_[deleted[i]]; | 164 MostVisitedURL deleted_url = top_sites_[deleted[i]]; |
147 std::map<GURL, Images>::iterator found = | 165 std::map<GURL, Images>::iterator found = |
148 top_images_.find(deleted_url.url); | 166 top_images_.find(deleted_url.url); |
149 if (found != top_images_.end()) | 167 if (found != top_images_.end()) |
150 top_images_.erase(found); | 168 top_images_.erase(found); |
151 | 169 |
152 // Delete from disk. | 170 // Delete from disk. |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin(); | 273 for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin(); |
256 i != all_old_urls.end(); ++i) { | 274 i != all_old_urls.end(); ++i) { |
257 if (i->second != kAlreadyFoundMarker) | 275 if (i->second != kAlreadyFoundMarker) |
258 deleted_urls->push_back(i->second); | 276 deleted_urls->push_back(i->second); |
259 } | 277 } |
260 } | 278 } |
261 | 279 |
262 void TopSites::StartQueryForMostVisited() { | 280 void TopSites::StartQueryForMostVisited() { |
263 if (mock_history_service_) { | 281 if (mock_history_service_) { |
264 // Testing with a mockup. | 282 // Testing with a mockup. |
265 // QuerySegmentUsageSince is not virtual, so we have to duplicate the code. | 283 // QueryMostVisitedURLs is not virtual, so we have to duplicate the code. |
266 mock_history_service_->QueryMostVisitedURLs( | 284 mock_history_service_->QueryMostVisitedURLs( |
267 kTopSitesNumber, | 285 kTopSitesNumber, |
268 kDaysOfHistory, | 286 kDaysOfHistory, |
269 &cancelable_consumer_, | 287 &cancelable_consumer_, |
270 NewCallback(this, &TopSites::OnTopSitesAvailable)); | 288 NewCallback(this, &TopSites::OnTopSitesAvailable)); |
271 } else { | 289 } else { |
272 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | 290 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); |
273 // |hs| may be null during unit tests. | 291 // |hs| may be null during unit tests. |
274 if (hs) { | 292 if (hs) { |
275 hs->QueryMostVisitedURLs( | 293 hs->QueryMostVisitedURLs( |
276 kTopSitesNumber, | 294 kTopSitesNumber, |
277 kDaysOfHistory, | 295 kDaysOfHistory, |
278 &cancelable_consumer_, | 296 &cancelable_consumer_, |
279 NewCallback(this, &TopSites::OnTopSitesAvailable)); | 297 NewCallback(this, &TopSites::OnTopSitesAvailable)); |
280 } else { | 298 } else { |
281 LOG(INFO) << "History Service not available."; | 299 LOG(INFO) << "History Service not available."; |
282 } | 300 } |
283 } | 301 } |
| 302 |
| 303 timer_.Stop(); |
| 304 timer_.Start(GetUpdateDelay(), this, |
| 305 &TopSites::StartQueryForMostVisited); |
| 306 } |
| 307 |
| 308 base::TimeDelta TopSites::GetUpdateDelay() { |
| 309 int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes; |
| 310 int64 minutes = kMaxUpdateIntervalMinutes - |
| 311 last_num_urls_changed_ * range / kTopSitesNumber; |
| 312 return base::TimeDelta::FromMinutes(minutes); |
284 } | 313 } |
285 | 314 |
286 void TopSites::OnTopSitesAvailable( | 315 void TopSites::OnTopSitesAvailable( |
287 CancelableRequestProvider::Handle handle, | 316 CancelableRequestProvider::Handle handle, |
288 MostVisitedURLList pages) { | 317 MostVisitedURLList pages) { |
289 AutoLock lock(lock_); | 318 AutoLock lock(lock_); |
290 UpdateMostVisited(&pages); | 319 UpdateMostVisited(&pages); |
291 } | 320 } |
292 | 321 |
293 void TopSites::SetMockHistoryService(MockHistoryService* mhs) { | 322 void TopSites::SetMockHistoryService(MockHistoryService* mhs) { |
294 mock_history_service_ = mhs; | 323 mock_history_service_ = mhs; |
295 } | 324 } |
296 | 325 |
| 326 void TopSites::Observe(NotificationType type, |
| 327 const NotificationSource& source, |
| 328 const NotificationDetails& details) { |
| 329 if (type != NotificationType::HISTORY_URLS_DELETED) { |
| 330 NOTREACHED(); |
| 331 return; |
| 332 } |
| 333 |
| 334 Details<history::URLsDeletedDetails> deleted_details(details); |
| 335 if (deleted_details->all_history) { |
| 336 db_.reset(new TopSitesDatabaseImpl()); |
| 337 // TODO(nshkrob): delete file in background (FILE) thread. |
| 338 file_util::Delete(db_path_, false); |
| 339 if (!db_->Init(db_path_)) { |
| 340 NOTREACHED() << "Failed to initialize database."; |
| 341 return; |
| 342 } |
| 343 } |
| 344 StartQueryForMostVisited(); |
| 345 } |
| 346 |
297 } // namespace history | 347 } // namespace history |
OLD | NEW |