| 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 |