| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/autocomplete/in_memory_url_index.h" | 5 #include "chrome/browser/autocomplete/in_memory_url_index.h" |
| 6 | 6 |
| 7 #include "base/files/file_util.h" | 7 #include "base/files/file_util.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
| 10 #include "chrome/browser/autocomplete/url_index_private_data.h" | 10 #include "chrome/browser/autocomplete/url_index_private_data.h" |
| 11 #include "chrome/common/url_constants.h" |
| 11 #include "components/history/core/browser/history_service.h" | 12 #include "components/history/core/browser/history_service.h" |
| 12 #include "components/history/core/browser/url_database.h" | 13 #include "components/history/core/browser/url_database.h" |
| 14 #include "content/public/browser/browser_thread.h" |
| 13 | 15 |
| 14 using in_memory_url_index::InMemoryURLIndexCacheItem; | 16 using in_memory_url_index::InMemoryURLIndexCacheItem; |
| 15 | 17 |
| 18 // Called by DoSaveToCacheFile to delete any old cache file at |path| when |
| 19 // there is no private data to save. Runs on the blocking pool. |
| 20 void DeleteCacheFile(const base::FilePath& path) { |
| 21 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 22 base::DeleteFile(path, false); |
| 23 } |
| 24 |
| 16 // Initializes a whitelist of URL schemes. | 25 // Initializes a whitelist of URL schemes. |
| 17 void InitializeSchemeWhitelist( | 26 void InitializeSchemeWhitelist(std::set<std::string>* whitelist) { |
| 18 SchemeSet* whitelist, | |
| 19 const SchemeSet& client_schemes_to_whitelist) { | |
| 20 DCHECK(whitelist); | 27 DCHECK(whitelist); |
| 21 if (!whitelist->empty()) | 28 if (!whitelist->empty()) |
| 22 return; // Nothing to do, already initialized. | 29 return; // Nothing to do, already initialized. |
| 23 | |
| 24 whitelist->insert(client_schemes_to_whitelist.begin(), | |
| 25 client_schemes_to_whitelist.end()); | |
| 26 | |
| 27 whitelist->insert(std::string(url::kAboutScheme)); | 30 whitelist->insert(std::string(url::kAboutScheme)); |
| 31 whitelist->insert(std::string(content::kChromeUIScheme)); |
| 28 whitelist->insert(std::string(url::kFileScheme)); | 32 whitelist->insert(std::string(url::kFileScheme)); |
| 29 whitelist->insert(std::string(url::kFtpScheme)); | 33 whitelist->insert(std::string(url::kFtpScheme)); |
| 30 whitelist->insert(std::string(url::kHttpScheme)); | 34 whitelist->insert(std::string(url::kHttpScheme)); |
| 31 whitelist->insert(std::string(url::kHttpsScheme)); | 35 whitelist->insert(std::string(url::kHttpsScheme)); |
| 32 whitelist->insert(std::string(url::kMailToScheme)); | 36 whitelist->insert(std::string(url::kMailToScheme)); |
| 33 } | 37 } |
| 34 | 38 |
| 35 // Restore/SaveCacheObserver --------------------------------------------------- | 39 // Restore/SaveCacheObserver --------------------------------------------------- |
| 36 | 40 |
| 37 InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() { | 41 InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() { |
| 38 } | 42 } |
| 39 | 43 |
| 40 InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() { | 44 InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() { |
| 41 } | 45 } |
| 42 | 46 |
| 43 // RebuildPrivateDataFromHistoryDBTask ----------------------------------------- | 47 // RebuildPrivateDataFromHistoryDBTask ----------------------------------------- |
| 44 | 48 |
| 45 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: | 49 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: |
| 46 RebuildPrivateDataFromHistoryDBTask( | 50 RebuildPrivateDataFromHistoryDBTask( |
| 47 InMemoryURLIndex* index, | 51 InMemoryURLIndex* index, |
| 48 const std::string& languages, | 52 const std::string& languages, |
| 49 const SchemeSet& scheme_whitelist) | 53 const std::set<std::string>& scheme_whitelist) |
| 50 : index_(index), | 54 : index_(index), |
| 51 languages_(languages), | 55 languages_(languages), |
| 52 scheme_whitelist_(scheme_whitelist), | 56 scheme_whitelist_(scheme_whitelist), |
| 53 succeeded_(false) { | 57 succeeded_(false) { |
| 54 } | 58 } |
| 55 | 59 |
| 56 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread( | 60 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread( |
| 57 history::HistoryBackend* backend, | 61 history::HistoryBackend* backend, |
| 58 history::HistoryDatabase* db) { | 62 history::HistoryDatabase* db) { |
| 59 data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_, | 63 data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_, |
| 60 scheme_whitelist_); | 64 scheme_whitelist_); |
| 61 succeeded_ = data_.get() && !data_->Empty(); | 65 succeeded_ = data_.get() && !data_->Empty(); |
| 62 if (!succeeded_ && data_.get()) | 66 if (!succeeded_ && data_.get()) |
| 63 data_->Clear(); | 67 data_->Clear(); |
| 64 return true; | 68 return true; |
| 65 } | 69 } |
| 66 | 70 |
| 67 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: | 71 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: |
| 68 DoneRunOnMainThread() { | 72 DoneRunOnMainThread() { |
| 69 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_); | 73 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_); |
| 70 } | 74 } |
| 71 | 75 |
| 72 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: | 76 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: |
| 73 ~RebuildPrivateDataFromHistoryDBTask() { | 77 ~RebuildPrivateDataFromHistoryDBTask() { |
| 74 } | 78 } |
| 75 | 79 |
| 76 // InMemoryURLIndex ------------------------------------------------------------ | 80 // InMemoryURLIndex ------------------------------------------------------------ |
| 77 | 81 |
| 78 InMemoryURLIndex::InMemoryURLIndex( | 82 InMemoryURLIndex::InMemoryURLIndex(bookmarks::BookmarkModel* bookmark_model, |
| 79 bookmarks::BookmarkModel* bookmark_model, | 83 history::HistoryService* history_service, |
| 80 history::HistoryService* history_service, | 84 const base::FilePath& history_dir, |
| 81 base::SequencedWorkerPool* worker_pool, | 85 const std::string& languages) |
| 82 const base::FilePath& history_dir, | |
| 83 const std::string& languages, | |
| 84 const SchemeSet& client_schemes_to_whitelist) | |
| 85 : bookmark_model_(bookmark_model), | 86 : bookmark_model_(bookmark_model), |
| 86 history_service_(history_service), | 87 history_service_(history_service), |
| 87 history_dir_(history_dir), | 88 history_dir_(history_dir), |
| 88 languages_(languages), | 89 languages_(languages), |
| 89 private_data_(new URLIndexPrivateData), | 90 private_data_(new URLIndexPrivateData), |
| 90 restore_cache_observer_(NULL), | 91 restore_cache_observer_(NULL), |
| 91 save_cache_observer_(NULL), | 92 save_cache_observer_(NULL), |
| 92 task_runner_( | 93 task_runner_( |
| 93 worker_pool->GetSequencedTaskRunner(worker_pool->GetSequenceToken())), | 94 content::BrowserThread::GetBlockingPool()->GetSequencedTaskRunner( |
| 95 content::BrowserThread::GetBlockingPool()->GetSequenceToken())), |
| 94 shutdown_(false), | 96 shutdown_(false), |
| 95 restored_(false), | 97 restored_(false), |
| 96 needs_to_be_cached_(false), | 98 needs_to_be_cached_(false), |
| 97 listen_to_history_service_loaded_(false) { | 99 listen_to_history_service_loaded_(false) { |
| 98 InitializeSchemeWhitelist(&scheme_whitelist_, client_schemes_to_whitelist); | 100 InitializeSchemeWhitelist(&scheme_whitelist_); |
| 99 // TODO(mrossetti): Register for language change notifications. | 101 // TODO(mrossetti): Register for language change notifications. |
| 100 if (history_service_) | 102 if (history_service_) |
| 101 history_service_->AddObserver(this); | 103 history_service_->AddObserver(this); |
| 102 } | 104 } |
| 103 | 105 |
| 104 InMemoryURLIndex::~InMemoryURLIndex() { | 106 InMemoryURLIndex::~InMemoryURLIndex() { |
| 105 // If there was a history directory (which there won't be for some unit tests) | 107 // If there was a history directory (which there won't be for some unit tests) |
| 106 // then insure that the cache has already been saved. | 108 // then insure that the cache has already been saved. |
| 107 DCHECK(history_dir_.empty() || !needs_to_be_cached_); | 109 DCHECK(history_dir_.empty() || !needs_to_be_cached_); |
| 108 DCHECK(!history_service_); | 110 DCHECK(!history_service_); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 // writing a new cache (after deleting the URLs from the in-memory structure) | 188 // writing a new cache (after deleting the URLs from the in-memory structure) |
| 187 // because deleting the cache forces it to be rebuilt from history upon | 189 // because deleting the cache forces it to be rebuilt from history upon |
| 188 // startup. If we instead write a new, updated cache then at the time of next | 190 // startup. If we instead write a new, updated cache then at the time of next |
| 189 // startup (after an unclean shutdown) we will not rebuild the in-memory data | 191 // startup (after an unclean shutdown) we will not rebuild the in-memory data |
| 190 // structures from history but rather use the cache. This solution is | 192 // structures from history but rather use the cache. This solution is |
| 191 // mediocre because this cache may not have the most-recently-visited URLs | 193 // mediocre because this cache may not have the most-recently-visited URLs |
| 192 // in it (URLs visited after user deleted some URLs from history), which | 194 // in it (URLs visited after user deleted some URLs from history), which |
| 193 // would be odd and confusing. It's better to force a rebuild. | 195 // would be odd and confusing. It's better to force a rebuild. |
| 194 base::FilePath path; | 196 base::FilePath path; |
| 195 if (needs_to_be_cached_ && GetCacheFilePath(&path)) | 197 if (needs_to_be_cached_ && GetCacheFilePath(&path)) |
| 196 task_runner_->PostTask( | 198 task_runner_->PostTask(FROM_HERE, base::Bind(DeleteCacheFile, path)); |
| 197 FROM_HERE, | |
| 198 base::Bind(base::IgnoreResult(base::DeleteFile), path, false)); | |
| 199 } | 199 } |
| 200 | 200 |
| 201 void InMemoryURLIndex::OnHistoryServiceLoaded( | 201 void InMemoryURLIndex::OnHistoryServiceLoaded( |
| 202 history::HistoryService* history_service) { | 202 history::HistoryService* history_service) { |
| 203 if (listen_to_history_service_loaded_) | 203 if (listen_to_history_service_loaded_) |
| 204 ScheduleRebuildFromHistory(); | 204 ScheduleRebuildFromHistory(); |
| 205 listen_to_history_service_loaded_ = false; | 205 listen_to_history_service_loaded_ = false; |
| 206 } | 206 } |
| 207 | 207 |
| 208 // Restoring from Cache -------------------------------------------------------- | 208 // Restoring from Cache -------------------------------------------------------- |
| 209 | 209 |
| 210 void InMemoryURLIndex::PostRestoreFromCacheFileTask() { | 210 void InMemoryURLIndex::PostRestoreFromCacheFileTask() { |
| 211 DCHECK(thread_checker_.CalledOnValidThread()); | 211 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 212 TRACE_EVENT0("browser", "InMemoryURLIndex::PostRestoreFromCacheFileTask"); | 212 TRACE_EVENT0("browser", "InMemoryURLIndex::PostRestoreFromCacheFileTask"); |
| 213 | 213 |
| 214 base::FilePath path; | 214 base::FilePath path; |
| 215 if (!GetCacheFilePath(&path) || shutdown_) { | 215 if (!GetCacheFilePath(&path) || shutdown_) { |
| 216 restored_ = true; | 216 restored_ = true; |
| 217 if (restore_cache_observer_) | 217 if (restore_cache_observer_) |
| 218 restore_cache_observer_->OnCacheRestoreFinished(false); | 218 restore_cache_observer_->OnCacheRestoreFinished(false); |
| 219 return; | 219 return; |
| 220 } | 220 } |
| 221 | 221 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 234 restored_ = true; | 234 restored_ = true; |
| 235 if (restore_cache_observer_) | 235 if (restore_cache_observer_) |
| 236 restore_cache_observer_->OnCacheRestoreFinished(true); | 236 restore_cache_observer_->OnCacheRestoreFinished(true); |
| 237 } else if (history_service_) { | 237 } else if (history_service_) { |
| 238 // When unable to restore from the cache file delete the cache file, if | 238 // When unable to restore from the cache file delete the cache file, if |
| 239 // it exists, and then rebuild from the history database if it's available, | 239 // it exists, and then rebuild from the history database if it's available, |
| 240 // otherwise wait until the history database loaded and then rebuild. | 240 // otherwise wait until the history database loaded and then rebuild. |
| 241 base::FilePath path; | 241 base::FilePath path; |
| 242 if (!GetCacheFilePath(&path) || shutdown_) | 242 if (!GetCacheFilePath(&path) || shutdown_) |
| 243 return; | 243 return; |
| 244 task_runner_->PostTask( | 244 task_runner_->PostTask(FROM_HERE, base::Bind(DeleteCacheFile, path)); |
| 245 FROM_HERE, | |
| 246 base::Bind(base::IgnoreResult(base::DeleteFile), path, false)); | |
| 247 if (history_service_->backend_loaded()) { | 245 if (history_service_->backend_loaded()) { |
| 248 ScheduleRebuildFromHistory(); | 246 ScheduleRebuildFromHistory(); |
| 249 } else { | 247 } else { |
| 250 listen_to_history_service_loaded_ = true; | 248 listen_to_history_service_loaded_ = true; |
| 251 } | 249 } |
| 252 } | 250 } |
| 253 } | 251 } |
| 254 | 252 |
| 255 // Cleanup --------------------------------------------------------------------- | 253 // Cleanup --------------------------------------------------------------------- |
| 256 | 254 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 281 history_service_->ScheduleDBTask( | 279 history_service_->ScheduleDBTask( |
| 282 scoped_ptr<history::HistoryDBTask>( | 280 scoped_ptr<history::HistoryDBTask>( |
| 283 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask( | 281 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask( |
| 284 this, languages_, scheme_whitelist_)), | 282 this, languages_, scheme_whitelist_)), |
| 285 &cache_reader_tracker_); | 283 &cache_reader_tracker_); |
| 286 } | 284 } |
| 287 | 285 |
| 288 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB( | 286 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB( |
| 289 bool succeeded, | 287 bool succeeded, |
| 290 scoped_refptr<URLIndexPrivateData> private_data) { | 288 scoped_refptr<URLIndexPrivateData> private_data) { |
| 291 DCHECK(thread_checker_.CalledOnValidThread()); | 289 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 292 if (succeeded) { | 290 if (succeeded) { |
| 293 private_data_tracker_.TryCancelAll(); | 291 private_data_tracker_.TryCancelAll(); |
| 294 private_data_ = private_data; | 292 private_data_ = private_data; |
| 295 PostSaveToCacheFileTask(); // Cache the newly rebuilt index. | 293 PostSaveToCacheFileTask(); // Cache the newly rebuilt index. |
| 296 } else { | 294 } else { |
| 297 private_data_->Clear(); // Dump the old private data. | 295 private_data_->Clear(); // Dump the old private data. |
| 298 // There is no need to do anything with the cache file as it was deleted | 296 // There is no need to do anything with the cache file as it was deleted |
| 299 // when the rebuild from the history operation was kicked off. | 297 // when the rebuild from the history operation was kicked off. |
| 300 } | 298 } |
| 301 restored_ = true; | 299 restored_ = true; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 325 scoped_refptr<URLIndexPrivateData> private_data_copy = | 323 scoped_refptr<URLIndexPrivateData> private_data_copy = |
| 326 private_data_->Duplicate(); | 324 private_data_->Duplicate(); |
| 327 base::PostTaskAndReplyWithResult( | 325 base::PostTaskAndReplyWithResult( |
| 328 task_runner_.get(), | 326 task_runner_.get(), |
| 329 FROM_HERE, | 327 FROM_HERE, |
| 330 base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask, | 328 base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask, |
| 331 private_data_copy, path), | 329 private_data_copy, path), |
| 332 base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr())); | 330 base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr())); |
| 333 } else { | 331 } else { |
| 334 // If there is no data in our index then delete any existing cache file. | 332 // If there is no data in our index then delete any existing cache file. |
| 335 task_runner_->PostTask( | 333 task_runner_->PostTask(FROM_HERE, base::Bind(DeleteCacheFile, path)); |
| 336 FROM_HERE, | |
| 337 base::Bind(base::IgnoreResult(base::DeleteFile), path, false)); | |
| 338 } | 334 } |
| 339 } | 335 } |
| 340 | 336 |
| 341 void InMemoryURLIndex::OnCacheSaveDone(bool succeeded) { | 337 void InMemoryURLIndex::OnCacheSaveDone(bool succeeded) { |
| 342 if (save_cache_observer_) | 338 if (save_cache_observer_) |
| 343 save_cache_observer_->OnCacheSaveFinished(succeeded); | 339 save_cache_observer_->OnCacheSaveFinished(succeeded); |
| 344 } | 340 } |
| OLD | NEW |