Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / components / omnibox / browser / in_memory_url_index.cc
blob992001303b164c7fb2b9326695a425855e794d01
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
3 // found in the LICENSE file.
5 #include "components/omnibox/browser/in_memory_url_index.h"
7 #include "base/files/file_util.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/trace_event/trace_event.h"
10 #include "components/history/core/browser/history_service.h"
11 #include "components/history/core/browser/url_database.h"
12 #include "components/omnibox/browser/url_index_private_data.h"
14 using in_memory_url_index::InMemoryURLIndexCacheItem;
16 // Initializes a whitelist of URL schemes.
17 void InitializeSchemeWhitelist(
18 SchemeSet* whitelist,
19 const SchemeSet& client_schemes_to_whitelist) {
20 DCHECK(whitelist);
21 if (!whitelist->empty())
22 return; // Nothing to do, already initialized.
24 whitelist->insert(client_schemes_to_whitelist.begin(),
25 client_schemes_to_whitelist.end());
27 whitelist->insert(std::string(url::kAboutScheme));
28 whitelist->insert(std::string(url::kFileScheme));
29 whitelist->insert(std::string(url::kFtpScheme));
30 whitelist->insert(std::string(url::kHttpScheme));
31 whitelist->insert(std::string(url::kHttpsScheme));
32 whitelist->insert(std::string(url::kMailToScheme));
35 // Restore/SaveCacheObserver ---------------------------------------------------
37 InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() {
40 InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() {
43 // RebuildPrivateDataFromHistoryDBTask -----------------------------------------
45 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
46 RebuildPrivateDataFromHistoryDBTask(
47 InMemoryURLIndex* index,
48 const std::string& languages,
49 const SchemeSet& scheme_whitelist)
50 : index_(index),
51 languages_(languages),
52 scheme_whitelist_(scheme_whitelist),
53 succeeded_(false) {
56 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread(
57 history::HistoryBackend* backend,
58 history::HistoryDatabase* db) {
59 data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_,
60 scheme_whitelist_);
61 succeeded_ = data_.get() && !data_->Empty();
62 if (!succeeded_ && data_.get())
63 data_->Clear();
64 return true;
67 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
68 DoneRunOnMainThread() {
69 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_);
72 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
73 ~RebuildPrivateDataFromHistoryDBTask() {
76 // InMemoryURLIndex ------------------------------------------------------------
78 InMemoryURLIndex::InMemoryURLIndex(
79 bookmarks::BookmarkModel* bookmark_model,
80 history::HistoryService* history_service,
81 base::SequencedWorkerPool* worker_pool,
82 const base::FilePath& history_dir,
83 const std::string& languages,
84 const SchemeSet& client_schemes_to_whitelist)
85 : bookmark_model_(bookmark_model),
86 history_service_(history_service),
87 history_dir_(history_dir),
88 languages_(languages),
89 private_data_(new URLIndexPrivateData),
90 restore_cache_observer_(NULL),
91 save_cache_observer_(NULL),
92 task_runner_(
93 worker_pool->GetSequencedTaskRunner(worker_pool->GetSequenceToken())),
94 shutdown_(false),
95 restored_(false),
96 needs_to_be_cached_(false),
97 listen_to_history_service_loaded_(false) {
98 InitializeSchemeWhitelist(&scheme_whitelist_, client_schemes_to_whitelist);
99 // TODO(mrossetti): Register for language change notifications.
100 if (history_service_)
101 history_service_->AddObserver(this);
104 InMemoryURLIndex::~InMemoryURLIndex() {
105 // 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.
107 DCHECK(history_dir_.empty() || !needs_to_be_cached_);
108 DCHECK(!history_service_);
109 DCHECK(shutdown_);
112 void InMemoryURLIndex::Init() {
113 PostRestoreFromCacheFileTask();
116 void InMemoryURLIndex::ClearPrivateData() {
117 private_data_->Clear();
120 bool InMemoryURLIndex::GetCacheFilePath(base::FilePath* file_path) {
121 if (history_dir_.empty())
122 return false;
123 *file_path = history_dir_.Append(FILE_PATH_LITERAL("History Provider Cache"));
124 return true;
127 // Querying --------------------------------------------------------------------
129 ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms(
130 const base::string16& term_string,
131 size_t cursor_position,
132 size_t max_matches) {
133 return private_data_->HistoryItemsForTerms(
134 term_string, cursor_position, max_matches, languages_, bookmark_model_);
137 // Updating --------------------------------------------------------------------
139 void InMemoryURLIndex::DeleteURL(const GURL& url) {
140 private_data_->DeleteURL(url);
143 void InMemoryURLIndex::OnURLVisited(history::HistoryService* history_service,
144 ui::PageTransition transition,
145 const history::URLRow& row,
146 const history::RedirectList& redirects,
147 base::Time visit_time) {
148 DCHECK_EQ(history_service_, history_service);
149 needs_to_be_cached_ |= private_data_->UpdateURL(history_service_,
150 row,
151 languages_,
152 scheme_whitelist_,
153 &private_data_tracker_);
156 void InMemoryURLIndex::OnURLsModified(history::HistoryService* history_service,
157 const history::URLRows& changed_urls) {
158 DCHECK_EQ(history_service_, history_service);
159 for (const auto& row : changed_urls) {
160 needs_to_be_cached_ |= private_data_->UpdateURL(history_service_,
161 row,
162 languages_,
163 scheme_whitelist_,
164 &private_data_tracker_);
168 void InMemoryURLIndex::OnURLsDeleted(history::HistoryService* history_service,
169 bool all_history,
170 bool expired,
171 const history::URLRows& deleted_rows,
172 const std::set<GURL>& favicon_urls) {
173 if (all_history) {
174 ClearPrivateData();
175 needs_to_be_cached_ = true;
176 } else {
177 for (const auto& row : deleted_rows)
178 needs_to_be_cached_ |= private_data_->DeleteURL(row.url());
180 // If we made changes, destroy the previous cache. Otherwise, if we go
181 // through an unclean shutdown (and therefore fail to write a new cache file),
182 // when Chrome restarts and we restore from the previous cache, we'll end up
183 // searching over URLs that may be deleted. This would be wrong, and
184 // surprising to the user who bothered to delete some URLs from his/her
185 // history. In this situation, deleting the cache is a better solution than
186 // 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
188 // 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
190 // structures from history but rather use the cache. This solution is
191 // 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
193 // would be odd and confusing. It's better to force a rebuild.
194 base::FilePath path;
195 if (needs_to_be_cached_ && GetCacheFilePath(&path))
196 task_runner_->PostTask(
197 FROM_HERE,
198 base::Bind(base::IgnoreResult(base::DeleteFile), path, false));
201 void InMemoryURLIndex::OnHistoryServiceLoaded(
202 history::HistoryService* history_service) {
203 if (listen_to_history_service_loaded_)
204 ScheduleRebuildFromHistory();
205 listen_to_history_service_loaded_ = false;
208 // Restoring from Cache --------------------------------------------------------
210 void InMemoryURLIndex::PostRestoreFromCacheFileTask() {
211 DCHECK(thread_checker_.CalledOnValidThread());
212 TRACE_EVENT0("browser", "InMemoryURLIndex::PostRestoreFromCacheFileTask");
214 base::FilePath path;
215 if (!GetCacheFilePath(&path) || shutdown_) {
216 restored_ = true;
217 if (restore_cache_observer_)
218 restore_cache_observer_->OnCacheRestoreFinished(false);
219 return;
222 base::PostTaskAndReplyWithResult(
223 task_runner_.get(),
224 FROM_HERE,
225 base::Bind(&URLIndexPrivateData::RestoreFromFile, path, languages_),
226 base::Bind(&InMemoryURLIndex::OnCacheLoadDone, AsWeakPtr()));
229 void InMemoryURLIndex::OnCacheLoadDone(
230 scoped_refptr<URLIndexPrivateData> private_data) {
231 if (private_data.get() && !private_data->Empty()) {
232 private_data_tracker_.TryCancelAll();
233 private_data_ = private_data;
234 restored_ = true;
235 if (restore_cache_observer_)
236 restore_cache_observer_->OnCacheRestoreFinished(true);
237 } else if (history_service_) {
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,
240 // otherwise wait until the history database loaded and then rebuild.
241 base::FilePath path;
242 if (!GetCacheFilePath(&path) || shutdown_)
243 return;
244 task_runner_->PostTask(
245 FROM_HERE,
246 base::Bind(base::IgnoreResult(base::DeleteFile), path, false));
247 if (history_service_->backend_loaded()) {
248 ScheduleRebuildFromHistory();
249 } else {
250 listen_to_history_service_loaded_ = true;
255 // Cleanup ---------------------------------------------------------------------
257 void InMemoryURLIndex::Shutdown() {
258 if (history_service_) {
259 history_service_->RemoveObserver(this);
260 history_service_ = nullptr;
262 cache_reader_tracker_.TryCancelAll();
263 shutdown_ = true;
264 base::FilePath path;
265 if (!GetCacheFilePath(&path))
266 return;
267 private_data_tracker_.TryCancelAll();
268 task_runner_->PostTask(
269 FROM_HERE,
270 base::Bind(
271 base::IgnoreResult(
272 &URLIndexPrivateData::WritePrivateDataToCacheFileTask),
273 private_data_, path));
274 needs_to_be_cached_ = false;
277 // Restoring from the History DB -----------------------------------------------
279 void InMemoryURLIndex::ScheduleRebuildFromHistory() {
280 DCHECK(history_service_);
281 history_service_->ScheduleDBTask(
282 scoped_ptr<history::HistoryDBTask>(
283 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(
284 this, languages_, scheme_whitelist_)),
285 &cache_reader_tracker_);
288 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB(
289 bool succeeded,
290 scoped_refptr<URLIndexPrivateData> private_data) {
291 DCHECK(thread_checker_.CalledOnValidThread());
292 if (succeeded) {
293 private_data_tracker_.TryCancelAll();
294 private_data_ = private_data;
295 PostSaveToCacheFileTask(); // Cache the newly rebuilt index.
296 } else {
297 private_data_->Clear(); // Dump the old private data.
298 // 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.
301 restored_ = true;
302 if (restore_cache_observer_)
303 restore_cache_observer_->OnCacheRestoreFinished(succeeded);
306 void InMemoryURLIndex::RebuildFromHistory(
307 history::HistoryDatabase* history_db) {
308 private_data_tracker_.TryCancelAll();
309 private_data_ = URLIndexPrivateData::RebuildFromHistory(history_db,
310 languages_,
311 scheme_whitelist_);
314 // Saving to Cache -------------------------------------------------------------
316 void InMemoryURLIndex::PostSaveToCacheFileTask() {
317 base::FilePath path;
318 if (!GetCacheFilePath(&path))
319 return;
320 // If there is anything in our private data then make a copy of it and tell
321 // it to save itself to a file.
322 if (private_data_.get() && !private_data_->Empty()) {
323 // Note that ownership of the copy of our private data is passed to the
324 // completion closure below.
325 scoped_refptr<URLIndexPrivateData> private_data_copy =
326 private_data_->Duplicate();
327 base::PostTaskAndReplyWithResult(
328 task_runner_.get(),
329 FROM_HERE,
330 base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask,
331 private_data_copy, path),
332 base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr()));
333 } else {
334 // If there is no data in our index then delete any existing cache file.
335 task_runner_->PostTask(
336 FROM_HERE,
337 base::Bind(base::IgnoreResult(base::DeleteFile), path, false));
341 void InMemoryURLIndex::OnCacheSaveDone(bool succeeded) {
342 if (save_cache_observer_)
343 save_cache_observer_->OnCacheSaveFinished(succeeded);