| 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" | |
| 12 #include "components/history/core/browser/history_service.h" | 11 #include "components/history/core/browser/history_service.h" |
| 13 #include "components/history/core/browser/url_database.h" | 12 #include "components/history/core/browser/url_database.h" |
| 14 #include "content/public/browser/browser_thread.h" | |
| 15 | 13 |
| 16 using in_memory_url_index::InMemoryURLIndexCacheItem; | 14 using in_memory_url_index::InMemoryURLIndexCacheItem; |
| 17 | 15 |
| 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 | |
| 25 // Initializes a whitelist of URL schemes. | 16 // Initializes a whitelist of URL schemes. |
| 26 void InitializeSchemeWhitelist(std::set<std::string>* whitelist) { | 17 void InitializeSchemeWhitelist( |
| 18 std::set<std::string>* whitelist, |
| 19 const std::set<std::string>& client_schemes_to_whitelist) { |
| 27 DCHECK(whitelist); | 20 DCHECK(whitelist); |
| 28 if (!whitelist->empty()) | 21 if (!whitelist->empty()) |
| 29 return; // Nothing to do, already initialized. | 22 return; // Nothing to do, already initialized. |
| 23 |
| 24 whitelist->insert(client_schemes_to_whitelist.begin(), |
| 25 client_schemes_to_whitelist.end()); |
| 26 |
| 30 whitelist->insert(std::string(url::kAboutScheme)); | 27 whitelist->insert(std::string(url::kAboutScheme)); |
| 31 whitelist->insert(std::string(content::kChromeUIScheme)); | |
| 32 whitelist->insert(std::string(url::kFileScheme)); | 28 whitelist->insert(std::string(url::kFileScheme)); |
| 33 whitelist->insert(std::string(url::kFtpScheme)); | 29 whitelist->insert(std::string(url::kFtpScheme)); |
| 34 whitelist->insert(std::string(url::kHttpScheme)); | 30 whitelist->insert(std::string(url::kHttpScheme)); |
| 35 whitelist->insert(std::string(url::kHttpsScheme)); | 31 whitelist->insert(std::string(url::kHttpsScheme)); |
| 36 whitelist->insert(std::string(url::kMailToScheme)); | 32 whitelist->insert(std::string(url::kMailToScheme)); |
| 37 } | 33 } |
| 38 | 34 |
| 39 // Restore/SaveCacheObserver --------------------------------------------------- | 35 // Restore/SaveCacheObserver --------------------------------------------------- |
| 40 | 36 |
| 41 InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() { | 37 InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 72 DoneRunOnMainThread() { | 68 DoneRunOnMainThread() { |
| 73 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_); | 69 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_); |
| 74 } | 70 } |
| 75 | 71 |
| 76 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: | 72 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: |
| 77 ~RebuildPrivateDataFromHistoryDBTask() { | 73 ~RebuildPrivateDataFromHistoryDBTask() { |
| 78 } | 74 } |
| 79 | 75 |
| 80 // InMemoryURLIndex ------------------------------------------------------------ | 76 // InMemoryURLIndex ------------------------------------------------------------ |
| 81 | 77 |
| 82 InMemoryURLIndex::InMemoryURLIndex(bookmarks::BookmarkModel* bookmark_model, | 78 InMemoryURLIndex::InMemoryURLIndex( |
| 83 history::HistoryService* history_service, | 79 bookmarks::BookmarkModel* bookmark_model, |
| 84 const base::FilePath& history_dir, | 80 history::HistoryService* history_service, |
| 85 const std::string& languages) | 81 base::SequencedWorkerPool* worker_pool, |
| 82 const base::FilePath& history_dir, |
| 83 const std::string& languages, |
| 84 const std::set<std::string>& client_schemes_to_whitelist) |
| 86 : bookmark_model_(bookmark_model), | 85 : bookmark_model_(bookmark_model), |
| 87 history_service_(history_service), | 86 history_service_(history_service), |
| 88 history_dir_(history_dir), | 87 history_dir_(history_dir), |
| 89 languages_(languages), | 88 languages_(languages), |
| 90 private_data_(new URLIndexPrivateData), | 89 private_data_(new URLIndexPrivateData), |
| 91 restore_cache_observer_(NULL), | 90 restore_cache_observer_(NULL), |
| 92 save_cache_observer_(NULL), | 91 save_cache_observer_(NULL), |
| 93 task_runner_( | 92 task_runner_( |
| 94 content::BrowserThread::GetBlockingPool()->GetSequencedTaskRunner( | 93 worker_pool->GetSequencedTaskRunner(worker_pool->GetSequenceToken())), |
| 95 content::BrowserThread::GetBlockingPool()->GetSequenceToken())), | |
| 96 shutdown_(false), | 94 shutdown_(false), |
| 97 restored_(false), | 95 restored_(false), |
| 98 needs_to_be_cached_(false), | 96 needs_to_be_cached_(false), |
| 99 listen_to_history_service_loaded_(false) { | 97 listen_to_history_service_loaded_(false) { |
| 100 InitializeSchemeWhitelist(&scheme_whitelist_); | 98 InitializeSchemeWhitelist(&scheme_whitelist_, client_schemes_to_whitelist); |
| 101 // TODO(mrossetti): Register for language change notifications. | 99 // TODO(mrossetti): Register for language change notifications. |
| 102 if (history_service_) | 100 if (history_service_) |
| 103 history_service_->AddObserver(this); | 101 history_service_->AddObserver(this); |
| 104 } | 102 } |
| 105 | 103 |
| 106 InMemoryURLIndex::~InMemoryURLIndex() { | 104 InMemoryURLIndex::~InMemoryURLIndex() { |
| 107 // If there was a history directory (which there won't be for some unit tests) | 105 // If there was a history directory (which there won't be for some unit tests) |
| 108 // then insure that the cache has already been saved. | 106 // then insure that the cache has already been saved. |
| 109 DCHECK(history_dir_.empty() || !needs_to_be_cached_); | 107 DCHECK(history_dir_.empty() || !needs_to_be_cached_); |
| 110 DCHECK(!history_service_); | 108 DCHECK(!history_service_); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 // writing a new cache (after deleting the URLs from the in-memory structure) | 186 // writing a new cache (after deleting the URLs from the in-memory structure) |
| 189 // because deleting the cache forces it to be rebuilt from history upon | 187 // because deleting the cache forces it to be rebuilt from history upon |
| 190 // startup. If we instead write a new, updated cache then at the time of next | 188 // startup. If we instead write a new, updated cache then at the time of next |
| 191 // startup (after an unclean shutdown) we will not rebuild the in-memory data | 189 // startup (after an unclean shutdown) we will not rebuild the in-memory data |
| 192 // structures from history but rather use the cache. This solution is | 190 // structures from history but rather use the cache. This solution is |
| 193 // mediocre because this cache may not have the most-recently-visited URLs | 191 // mediocre because this cache may not have the most-recently-visited URLs |
| 194 // in it (URLs visited after user deleted some URLs from history), which | 192 // in it (URLs visited after user deleted some URLs from history), which |
| 195 // would be odd and confusing. It's better to force a rebuild. | 193 // would be odd and confusing. It's better to force a rebuild. |
| 196 base::FilePath path; | 194 base::FilePath path; |
| 197 if (needs_to_be_cached_ && GetCacheFilePath(&path)) | 195 if (needs_to_be_cached_ && GetCacheFilePath(&path)) |
| 198 task_runner_->PostTask(FROM_HERE, base::Bind(DeleteCacheFile, path)); | 196 task_runner_->PostTask( |
| 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_CURRENTLY_ON(content::BrowserThread::UI); | 211 DCHECK(thread_checker_.CalledOnValidThread()); |
| 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(FROM_HERE, base::Bind(DeleteCacheFile, path)); | 244 task_runner_->PostTask( |
| 245 FROM_HERE, |
| 246 base::Bind(base::IgnoreResult(base::DeleteFile), path, false)); |
| 245 if (history_service_->backend_loaded()) { | 247 if (history_service_->backend_loaded()) { |
| 246 ScheduleRebuildFromHistory(); | 248 ScheduleRebuildFromHistory(); |
| 247 } else { | 249 } else { |
| 248 listen_to_history_service_loaded_ = true; | 250 listen_to_history_service_loaded_ = true; |
| 249 } | 251 } |
| 250 } | 252 } |
| 251 } | 253 } |
| 252 | 254 |
| 253 // Cleanup --------------------------------------------------------------------- | 255 // Cleanup --------------------------------------------------------------------- |
| 254 | 256 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 279 history_service_->ScheduleDBTask( | 281 history_service_->ScheduleDBTask( |
| 280 scoped_ptr<history::HistoryDBTask>( | 282 scoped_ptr<history::HistoryDBTask>( |
| 281 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask( | 283 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask( |
| 282 this, languages_, scheme_whitelist_)), | 284 this, languages_, scheme_whitelist_)), |
| 283 &cache_reader_tracker_); | 285 &cache_reader_tracker_); |
| 284 } | 286 } |
| 285 | 287 |
| 286 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB( | 288 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB( |
| 287 bool succeeded, | 289 bool succeeded, |
| 288 scoped_refptr<URLIndexPrivateData> private_data) { | 290 scoped_refptr<URLIndexPrivateData> private_data) { |
| 289 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 291 DCHECK(thread_checker_.CalledOnValidThread()); |
| 290 if (succeeded) { | 292 if (succeeded) { |
| 291 private_data_tracker_.TryCancelAll(); | 293 private_data_tracker_.TryCancelAll(); |
| 292 private_data_ = private_data; | 294 private_data_ = private_data; |
| 293 PostSaveToCacheFileTask(); // Cache the newly rebuilt index. | 295 PostSaveToCacheFileTask(); // Cache the newly rebuilt index. |
| 294 } else { | 296 } else { |
| 295 private_data_->Clear(); // Dump the old private data. | 297 private_data_->Clear(); // Dump the old private data. |
| 296 // There is no need to do anything with the cache file as it was deleted | 298 // There is no need to do anything with the cache file as it was deleted |
| 297 // when the rebuild from the history operation was kicked off. | 299 // when the rebuild from the history operation was kicked off. |
| 298 } | 300 } |
| 299 restored_ = true; | 301 restored_ = true; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 323 scoped_refptr<URLIndexPrivateData> private_data_copy = | 325 scoped_refptr<URLIndexPrivateData> private_data_copy = |
| 324 private_data_->Duplicate(); | 326 private_data_->Duplicate(); |
| 325 base::PostTaskAndReplyWithResult( | 327 base::PostTaskAndReplyWithResult( |
| 326 task_runner_.get(), | 328 task_runner_.get(), |
| 327 FROM_HERE, | 329 FROM_HERE, |
| 328 base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask, | 330 base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask, |
| 329 private_data_copy, path), | 331 private_data_copy, path), |
| 330 base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr())); | 332 base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr())); |
| 331 } else { | 333 } else { |
| 332 // If there is no data in our index then delete any existing cache file. | 334 // If there is no data in our index then delete any existing cache file. |
| 333 task_runner_->PostTask(FROM_HERE, base::Bind(DeleteCacheFile, path)); | 335 task_runner_->PostTask( |
| 336 FROM_HERE, |
| 337 base::Bind(base::IgnoreResult(base::DeleteFile), path, false)); |
| 334 } | 338 } |
| 335 } | 339 } |
| 336 | 340 |
| 337 void InMemoryURLIndex::OnCacheSaveDone(bool succeeded) { | 341 void InMemoryURLIndex::OnCacheSaveDone(bool succeeded) { |
| 338 if (save_cache_observer_) | 342 if (save_cache_observer_) |
| 339 save_cache_observer_->OnCacheSaveFinished(succeeded); | 343 save_cache_observer_->OnCacheSaveFinished(succeeded); |
| 340 } | 344 } |
| OLD | NEW |