Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: chrome/browser/history/in_memory_url_index.cc

Issue 963823003: Move InMemoryURLIndex into chrome/browser/autocomplete (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@shortcut-database
Patch Set: Fixing win_chromium_x64_rel_ng build Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/history/in_memory_url_index.h"
6
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 "chrome/browser/history/history_service.h"
11 #include "chrome/browser/history/url_index_private_data.h"
12 #include "chrome/common/url_constants.h"
13 #include "components/history/core/browser/url_database.h"
14 #include "content/public/browser/browser_thread.h"
15
16 using in_memory_url_index::InMemoryURLIndexCacheItem;
17
18 namespace history {
19
20 // Called by DoSaveToCacheFile to delete any old cache file at |path| when
21 // there is no private data to save. Runs on the FILE thread.
22 void DeleteCacheFile(const base::FilePath& path) {
23 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
24 base::DeleteFile(path, false);
25 }
26
27 // Initializes a whitelist of URL schemes.
28 void InitializeSchemeWhitelist(std::set<std::string>* whitelist) {
29 DCHECK(whitelist);
30 if (!whitelist->empty())
31 return; // Nothing to do, already initialized.
32 whitelist->insert(std::string(url::kAboutScheme));
33 whitelist->insert(std::string(content::kChromeUIScheme));
34 whitelist->insert(std::string(url::kFileScheme));
35 whitelist->insert(std::string(url::kFtpScheme));
36 whitelist->insert(std::string(url::kHttpScheme));
37 whitelist->insert(std::string(url::kHttpsScheme));
38 whitelist->insert(std::string(url::kMailToScheme));
39 }
40
41 // Restore/SaveCacheObserver ---------------------------------------------------
42
43 InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() {}
44
45 InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() {}
46
47 // RebuildPrivateDataFromHistoryDBTask -----------------------------------------
48
49 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
50 RebuildPrivateDataFromHistoryDBTask(
51 InMemoryURLIndex* index,
52 const std::string& languages,
53 const std::set<std::string>& scheme_whitelist)
54 : index_(index),
55 languages_(languages),
56 scheme_whitelist_(scheme_whitelist),
57 succeeded_(false) {
58 }
59
60 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread(
61 HistoryBackend* backend,
62 HistoryDatabase* db) {
63 data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_,
64 scheme_whitelist_);
65 succeeded_ = data_.get() && !data_->Empty();
66 if (!succeeded_ && data_.get())
67 data_->Clear();
68 return true;
69 }
70
71 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
72 DoneRunOnMainThread() {
73 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_);
74 }
75
76 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
77 ~RebuildPrivateDataFromHistoryDBTask() {
78 }
79
80 // InMemoryURLIndex ------------------------------------------------------------
81
82 InMemoryURLIndex::InMemoryURLIndex(HistoryService* history_service,
83 const base::FilePath& history_dir,
84 const std::string& languages)
85 : history_service_(history_service),
86 history_dir_(history_dir),
87 languages_(languages),
88 private_data_(new URLIndexPrivateData),
89 restore_cache_observer_(NULL),
90 save_cache_observer_(NULL),
91 shutdown_(false),
92 restored_(false),
93 needs_to_be_cached_(false),
94 listen_to_history_service_loaded_(false) {
95 InitializeSchemeWhitelist(&scheme_whitelist_);
96 // TODO(mrossetti): Register for language change notifications.
97 if (history_service_)
98 history_service_->AddObserver(this);
99 }
100
101 InMemoryURLIndex::~InMemoryURLIndex() {
102 // If there was a history directory (which there won't be for some unit tests)
103 // then insure that the cache has already been saved.
104 DCHECK(history_dir_.empty() || !needs_to_be_cached_);
105 DCHECK(!history_service_);
106 DCHECK(shutdown_);
107 }
108
109 void InMemoryURLIndex::Init() {
110 PostRestoreFromCacheFileTask();
111 }
112
113 void InMemoryURLIndex::ShutDown() {
114 if (history_service_) {
115 history_service_->RemoveObserver(this);
116 history_service_ = nullptr;
117 }
118 cache_reader_tracker_.TryCancelAll();
119 shutdown_ = true;
120 base::FilePath path;
121 if (!GetCacheFilePath(&path))
122 return;
123 private_data_tracker_.TryCancelAll();
124 URLIndexPrivateData::WritePrivateDataToCacheFileTask(private_data_, path);
125 needs_to_be_cached_ = false;
126 }
127
128 void InMemoryURLIndex::ClearPrivateData() {
129 private_data_->Clear();
130 }
131
132 bool InMemoryURLIndex::GetCacheFilePath(base::FilePath* file_path) {
133 if (history_dir_.empty())
134 return false;
135 *file_path = history_dir_.Append(FILE_PATH_LITERAL("History Provider Cache"));
136 return true;
137 }
138
139 // Querying --------------------------------------------------------------------
140
141 ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms(
142 const base::string16& term_string,
143 size_t cursor_position,
144 size_t max_matches,
145 const ScoredHistoryMatch::Builder& builder) {
146 return private_data_->HistoryItemsForTerms(term_string, cursor_position,
147 max_matches, languages_, builder);
148 }
149
150 // Updating --------------------------------------------------------------------
151
152 void InMemoryURLIndex::DeleteURL(const GURL& url) {
153 private_data_->DeleteURL(url);
154 }
155
156 void InMemoryURLIndex::OnURLVisited(HistoryService* history_service,
157 ui::PageTransition transition,
158 const URLRow& row,
159 const RedirectList& redirects,
160 base::Time visit_time) {
161 DCHECK_EQ(history_service_, history_service);
162 needs_to_be_cached_ |= private_data_->UpdateURL(history_service_,
163 row,
164 languages_,
165 scheme_whitelist_,
166 &private_data_tracker_);
167 }
168
169 void InMemoryURLIndex::OnURLsModified(HistoryService* history_service,
170 const URLRows& changed_urls) {
171 DCHECK_EQ(history_service_, history_service);
172 for (const auto& row : changed_urls) {
173 needs_to_be_cached_ |= private_data_->UpdateURL(history_service_,
174 row,
175 languages_,
176 scheme_whitelist_,
177 &private_data_tracker_);
178 }
179 }
180
181 void InMemoryURLIndex::OnURLsDeleted(HistoryService* history_service,
182 bool all_history,
183 bool expired,
184 const URLRows& deleted_rows,
185 const std::set<GURL>& favicon_urls) {
186 if (all_history) {
187 ClearPrivateData();
188 needs_to_be_cached_ = true;
189 } else {
190 for (const auto& row : deleted_rows)
191 needs_to_be_cached_ |= private_data_->DeleteURL(row.url());
192 }
193 // If we made changes, destroy the previous cache. Otherwise, if we go
194 // through an unclean shutdown (and therefore fail to write a new cache file),
195 // when Chrome restarts and we restore from the previous cache, we'll end up
196 // searching over URLs that may be deleted. This would be wrong, and
197 // surprising to the user who bothered to delete some URLs from his/her
198 // history. In this situation, deleting the cache is a better solution than
199 // writing a new cache (after deleting the URLs from the in-memory structure)
200 // because deleting the cache forces it to be rebuilt from history upon
201 // startup. If we instead write a new, updated cache then at the time of next
202 // startup (after an unclean shutdown) we will not rebuild the in-memory data
203 // structures from history but rather use the cache. This solution is
204 // mediocre because this cache may not have the most-recently-visited URLs
205 // in it (URLs visited after user deleted some URLs from history), which
206 // would be odd and confusing. It's better to force a rebuild.
207 base::FilePath path;
208 if (needs_to_be_cached_ && GetCacheFilePath(&path)) {
209 content::BrowserThread::PostBlockingPoolTask(
210 FROM_HERE, base::Bind(DeleteCacheFile, path));
211 }
212 }
213
214 void InMemoryURLIndex::OnHistoryServiceLoaded(HistoryService* history_service) {
215 if (listen_to_history_service_loaded_)
216 ScheduleRebuildFromHistory();
217 listen_to_history_service_loaded_ = false;
218 }
219
220 // Restoring from Cache --------------------------------------------------------
221
222 void InMemoryURLIndex::PostRestoreFromCacheFileTask() {
223 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
224 TRACE_EVENT0("browser", "InMemoryURLIndex::PostRestoreFromCacheFileTask");
225
226 base::FilePath path;
227 if (!GetCacheFilePath(&path) || shutdown_) {
228 restored_ = true;
229 if (restore_cache_observer_)
230 restore_cache_observer_->OnCacheRestoreFinished(false);
231 return;
232 }
233
234 content::BrowserThread::PostTaskAndReplyWithResult
235 <scoped_refptr<URLIndexPrivateData> >(
236 content::BrowserThread::FILE, FROM_HERE,
237 base::Bind(&URLIndexPrivateData::RestoreFromFile, path, languages_),
238 base::Bind(&InMemoryURLIndex::OnCacheLoadDone, AsWeakPtr()));
239 }
240
241 void InMemoryURLIndex::OnCacheLoadDone(
242 scoped_refptr<URLIndexPrivateData> private_data) {
243 if (private_data.get() && !private_data->Empty()) {
244 private_data_tracker_.TryCancelAll();
245 private_data_ = private_data;
246 restored_ = true;
247 if (restore_cache_observer_)
248 restore_cache_observer_->OnCacheRestoreFinished(true);
249 } else if (history_service_) {
250 // When unable to restore from the cache file delete the cache file, if
251 // it exists, and then rebuild from the history database if it's available,
252 // otherwise wait until the history database loaded and then rebuild.
253 base::FilePath path;
254 if (!GetCacheFilePath(&path) || shutdown_)
255 return;
256 content::BrowserThread::PostBlockingPoolTask(
257 FROM_HERE, base::Bind(DeleteCacheFile, path));
258 if (history_service_->backend_loaded()) {
259 ScheduleRebuildFromHistory();
260 } else {
261 listen_to_history_service_loaded_ = true;
262 }
263 }
264 }
265
266 // Restoring from the History DB -----------------------------------------------
267
268 void InMemoryURLIndex::ScheduleRebuildFromHistory() {
269 DCHECK(history_service_);
270 history_service_->ScheduleDBTask(
271 scoped_ptr<history::HistoryDBTask>(
272 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(
273 this, languages_, scheme_whitelist_)),
274 &cache_reader_tracker_);
275 }
276
277 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB(
278 bool succeeded,
279 scoped_refptr<URLIndexPrivateData> private_data) {
280 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
281 if (succeeded) {
282 private_data_tracker_.TryCancelAll();
283 private_data_ = private_data;
284 PostSaveToCacheFileTask(); // Cache the newly rebuilt index.
285 } else {
286 private_data_->Clear(); // Dump the old private data.
287 // There is no need to do anything with the cache file as it was deleted
288 // when the rebuild from the history operation was kicked off.
289 }
290 restored_ = true;
291 if (restore_cache_observer_)
292 restore_cache_observer_->OnCacheRestoreFinished(succeeded);
293 }
294
295 void InMemoryURLIndex::RebuildFromHistory(HistoryDatabase* history_db) {
296 private_data_tracker_.TryCancelAll();
297 private_data_ = URLIndexPrivateData::RebuildFromHistory(history_db,
298 languages_,
299 scheme_whitelist_);
300 }
301
302 // Saving to Cache -------------------------------------------------------------
303
304 void InMemoryURLIndex::PostSaveToCacheFileTask() {
305 base::FilePath path;
306 if (!GetCacheFilePath(&path))
307 return;
308 // If there is anything in our private data then make a copy of it and tell
309 // it to save itself to a file.
310 if (private_data_.get() && !private_data_->Empty()) {
311 // Note that ownership of the copy of our private data is passed to the
312 // completion closure below.
313 scoped_refptr<URLIndexPrivateData> private_data_copy =
314 private_data_->Duplicate();
315 content::BrowserThread::PostTaskAndReplyWithResult<bool>(
316 content::BrowserThread::FILE, FROM_HERE,
317 base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask,
318 private_data_copy, path),
319 base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr()));
320 } else {
321 // If there is no data in our index then delete any existing cache file.
322 content::BrowserThread::PostBlockingPoolTask(
323 FROM_HERE,
324 base::Bind(DeleteCacheFile, path));
325 }
326 }
327
328 void InMemoryURLIndex::OnCacheSaveDone(bool succeeded) {
329 if (save_cache_observer_)
330 save_cache_observer_->OnCacheSaveFinished(succeeded);
331 }
332
333 } // namespace history
OLDNEW
« no previous file with comments | « chrome/browser/history/in_memory_url_index.h ('k') | chrome/browser/history/in_memory_url_index_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698