| 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     SchemeSet* whitelist, | 
 |   19     const SchemeSet& 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() { | 
|   42 } |   38 } | 
|   43  |   39  | 
|   44 InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() { |   40 InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() { | 
|   45 } |   41 } | 
|   46  |   42  | 
|   47 // RebuildPrivateDataFromHistoryDBTask ----------------------------------------- |   43 // RebuildPrivateDataFromHistoryDBTask ----------------------------------------- | 
|   48  |   44  | 
|   49 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: |   45 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: | 
|   50     RebuildPrivateDataFromHistoryDBTask( |   46     RebuildPrivateDataFromHistoryDBTask( | 
|   51         InMemoryURLIndex* index, |   47         InMemoryURLIndex* index, | 
|   52         const std::string& languages, |   48         const std::string& languages, | 
|   53         const std::set<std::string>& scheme_whitelist) |   49         const SchemeSet& scheme_whitelist) | 
|   54     : index_(index), |   50     : index_(index), | 
|   55       languages_(languages), |   51       languages_(languages), | 
|   56       scheme_whitelist_(scheme_whitelist), |   52       scheme_whitelist_(scheme_whitelist), | 
|   57       succeeded_(false) { |   53       succeeded_(false) { | 
|   58 } |   54 } | 
|   59  |   55  | 
|   60 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread( |   56 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread( | 
|   61     history::HistoryBackend* backend, |   57     history::HistoryBackend* backend, | 
|   62     history::HistoryDatabase* db) { |   58     history::HistoryDatabase* db) { | 
|   63   data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_, |   59   data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_, | 
|   64                                                   scheme_whitelist_); |   60                                                   scheme_whitelist_); | 
|   65   succeeded_ = data_.get() && !data_->Empty(); |   61   succeeded_ = data_.get() && !data_->Empty(); | 
|   66   if (!succeeded_ && data_.get()) |   62   if (!succeeded_ && data_.get()) | 
|   67     data_->Clear(); |   63     data_->Clear(); | 
|   68   return true; |   64   return true; | 
|   69 } |   65 } | 
|   70  |   66  | 
|   71 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: |   67 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: | 
|   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 SchemeSet& 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 |