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

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

Issue 10872032: Revert 152946 - Replace HistoryQuickProvider protobuf-based caching with an SQLite-based database. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 4 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 | Annotate | Revision Log
OLDNEW
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/history/in_memory_url_index.h" 5 #include "chrome/browser/history/in_memory_url_index.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/history/history_notifications.h" 9 #include "chrome/browser/history/history_notifications.h"
10 #include "chrome/browser/history/history_service_factory.h" 10 #include "chrome/browser/history/history_service_factory.h"
11 #include "chrome/browser/history/in_memory_url_cache_database.h"
12 #include "chrome/browser/history/url_database.h" 11 #include "chrome/browser/history/url_database.h"
13 #include "chrome/browser/history/url_index_private_data.h" 12 #include "chrome/browser/history/url_index_private_data.h"
14 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/chrome_notification_types.h" 14 #include "chrome/common/chrome_notification_types.h"
15 #include "chrome/common/url_constants.h"
16 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/notification_details.h" 17 #include "content/public/browser/notification_details.h"
18 #include "content/public/browser/notification_service.h" 18 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_source.h" 19 #include "content/public/browser/notification_source.h"
20 20
21 using content::BrowserThread; 21 using in_memory_url_index::InMemoryURLIndexCacheItem;
22 22
23 namespace history { 23 namespace history {
24 24
25 // InMemoryURLIndex::Observer -------------------------------------------------- 25 // Called by DoSaveToCacheFile to delete any old cache file at |path| when
26 26 // there is no private data to save. Runs on the FILE thread.
27 InMemoryURLIndex::Observer::Observer(InMemoryURLIndex* index) 27 void DeleteCacheFile(const FilePath& path) {
28 : index_(index) { 28 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
29 DCHECK(index); 29 file_util::Delete(path, false);
30 index_->AddObserver(this);
31 } 30 }
32 31
33 InMemoryURLIndex::Observer::~Observer() { 32 // Initializes a whitelist of URL schemes.
34 index_->RemoveObserver(this); 33 void InitializeSchemeWhitelist(std::set<std::string>* whitelist) {
34 DCHECK(whitelist);
35 if (!whitelist->empty())
36 return; // Nothing to do, already initialized.
37 whitelist->insert(std::string(chrome::kAboutScheme));
38 whitelist->insert(std::string(chrome::kChromeUIScheme));
39 whitelist->insert(std::string(chrome::kFileScheme));
40 whitelist->insert(std::string(chrome::kFtpScheme));
41 whitelist->insert(std::string(chrome::kHttpScheme));
42 whitelist->insert(std::string(chrome::kHttpsScheme));
43 whitelist->insert(std::string(chrome::kMailToScheme));
35 } 44 }
36 45
37 void InMemoryURLIndex::Observer::Loaded() { 46 // RefCountedBool --------------------------------------------------------------
38 MessageLoop::current()->QuitNow(); 47
39 } 48 RefCountedBool::~RefCountedBool() {}
49
50 // Restore/SaveCacheObserver ---------------------------------------------------
51
52 InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() {}
53
54 InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() {}
40 55
41 // RebuildPrivateDataFromHistoryDBTask ----------------------------------------- 56 // RebuildPrivateDataFromHistoryDBTask -----------------------------------------
42 57
43 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 58 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
44 RebuildPrivateDataFromHistoryDBTask(InMemoryURLIndex* index) 59 RebuildPrivateDataFromHistoryDBTask(
60 InMemoryURLIndex* index,
61 const std::string& languages,
62 const std::set<std::string>& scheme_whitelist)
45 : index_(index), 63 : index_(index),
64 languages_(languages),
65 scheme_whitelist_(scheme_whitelist),
46 succeeded_(false) { 66 succeeded_(false) {
47 } 67 }
48 68
49 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
50 ~RebuildPrivateDataFromHistoryDBTask() {
51 }
52
53 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread( 69 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread(
54 HistoryBackend* backend, 70 HistoryBackend* backend,
55 HistoryDatabase* db) { 71 HistoryDatabase* db) {
56 data_ = URLIndexPrivateData::RebuildFromHistory(db, index_->private_data()); 72 data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_,
73 scheme_whitelist_);
57 succeeded_ = data_.get() && !data_->Empty(); 74 succeeded_ = data_.get() && !data_->Empty();
75 if (!succeeded_ && data_.get())
76 data_->Clear();
58 return true; 77 return true;
59 } 78 }
60 79
61 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 80 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
62 DoneRunOnMainThread() { 81 DoneRunOnMainThread() {
63 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_); 82 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_);
64 } 83 }
65 84
66 // IndexUpdateItem ------------------------------------------------------------- 85 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
67 86 ~RebuildPrivateDataFromHistoryDBTask() {
68 InMemoryURLIndex::IndexUpdateItem::IndexUpdateItem(UpdateType update_type,
69 URLRow row)
70 : update_type(update_type),
71 row(row) {
72 } 87 }
73 88
74 InMemoryURLIndex::IndexUpdateItem::~IndexUpdateItem() {}
75
76 // InMemoryURLIndex ------------------------------------------------------------ 89 // InMemoryURLIndex ------------------------------------------------------------
77 90
78 InMemoryURLIndex::InMemoryURLIndex(Profile* profile, 91 InMemoryURLIndex::InMemoryURLIndex(Profile* profile,
79 const FilePath& history_dir, 92 const FilePath& history_dir,
80 const std::string& languages) 93 const std::string& languages)
81 : profile_(profile), 94 : profile_(profile),
95 history_dir_(history_dir),
82 languages_(languages), 96 languages_(languages),
83 history_dir_(history_dir), 97 private_data_(new URLIndexPrivateData),
84 private_data_(new URLIndexPrivateData(history_dir, languages)), 98 restore_cache_observer_(NULL),
85 sequence_token_(BrowserThread::GetBlockingPool()->GetSequenceToken()), 99 save_cache_observer_(NULL),
86 index_available_(false),
87 shutdown_(false), 100 shutdown_(false),
88 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { 101 needs_to_be_cached_(false) {
102 InitializeSchemeWhitelist(&scheme_whitelist_);
89 if (profile) { 103 if (profile) {
104 // TODO(mrossetti): Register for language change notifications.
90 content::Source<Profile> source(profile); 105 content::Source<Profile> source(profile);
91 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source); 106 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source);
92 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 107 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
93 source); 108 source);
94 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source); 109 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source);
95 } 110 }
96 // Note: private_data_ will be reset after rebuilding from the history
97 // database but the ownership of the database passes to the new
98 // private_data_ instance so there is no need to re-register for the
99 // following notification at that time.
100 registrar_.Add(this,
101 chrome::NOTIFICATION_IN_MEMORY_URL_CACHE_DATABASE_FAILURE,
102 content::Source<InMemoryURLCacheDatabase>(
103 private_data_->cache_db()));
104 // TODO(mrossetti): Register for language change notifications.
105 } 111 }
106 112
107 // Called only by unit tests. 113 // Called only by unit tests.
108 InMemoryURLIndex::InMemoryURLIndex(const FilePath& history_dir, 114 InMemoryURLIndex::InMemoryURLIndex()
109 const std::string& languages)
110 : profile_(NULL), 115 : profile_(NULL),
111 languages_(languages), 116 private_data_(new URLIndexPrivateData),
112 history_dir_(history_dir), 117 restore_cache_observer_(NULL),
113 index_available_(false), 118 save_cache_observer_(NULL),
114 shutdown_(false), 119 shutdown_(false),
115 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { 120 needs_to_be_cached_(false) {
121 InitializeSchemeWhitelist(&scheme_whitelist_);
116 } 122 }
117 123
118 InMemoryURLIndex::~InMemoryURLIndex() {} 124 InMemoryURLIndex::~InMemoryURLIndex() {
119 125 // If there was a history directory (which there won't be for some unit tests)
120 void InMemoryURLIndex::Init(bool disable_cache) { 126 // then insure that the cache has already been saved.
121 if (disable_cache) { 127 DCHECK(history_dir_.empty() || !needs_to_be_cached_);
122 RebuildFromHistoryIfLoaded();
123 } else {
124 // It's safe to initialize the private data and the cache database without
125 // using the sequenced worker pool as no other database operations will be
126 // going on at the same time.
127 BrowserThread::PostTaskAndReplyWithResult<bool>(
128 BrowserThread::DB, FROM_HERE,
129 base::Bind(&URLIndexPrivateData::Init, private_data_, sequence_token_),
130 base::Bind(&InMemoryURLIndex::OnPrivateDataInitDone,
131 weak_ptr_factory_.GetWeakPtr()));
132 }
133 } 128 }
134 129
135 void InMemoryURLIndex::OnPrivateDataInitDone(bool succeeded) { 130 void InMemoryURLIndex::Init() {
136 if (shutdown_) 131 PostRestoreFromCacheFileTask();
137 return;
138 if (succeeded)
139 PostRestoreFromCacheTask();
140 else
141 RebuildFromHistoryIfLoaded();
142 } 132 }
143 133
144 void InMemoryURLIndex::Shutdown() { 134 void InMemoryURLIndex::ShutDown() {
145 // Close down the cache database as quickly as possible. Any pending cache DB
146 // transactions will detect that the database is no longer there and give up.
147 registrar_.RemoveAll(); 135 registrar_.RemoveAll();
148 cache_reader_consumer_.CancelAllRequests(); 136 cache_reader_consumer_.CancelAllRequests();
149 shutdown_ = true; 137 shutdown_ = true;
150 private_data_->Shutdown(); 138 FilePath path;
139 if (!GetCacheFilePath(&path))
140 return;
141 scoped_refptr<RefCountedBool> succeeded(new RefCountedBool(false));
142 URLIndexPrivateData::WritePrivateDataToCacheFileTask(
143 private_data_, path, succeeded);
144 needs_to_be_cached_ = false;
151 } 145 }
152 146
153 void InMemoryURLIndex::AddObserver(InMemoryURLIndex::Observer* observer) { 147 void InMemoryURLIndex::ClearPrivateData() {
154 observers_.AddObserver(observer); 148 private_data_->Clear();
155 } 149 }
156 150
157 void InMemoryURLIndex::RemoveObserver(InMemoryURLIndex::Observer* observer) { 151 bool InMemoryURLIndex::GetCacheFilePath(FilePath* file_path) {
158 observers_.RemoveObserver(observer); 152 if (history_dir_.empty())
153 return false;
154 *file_path = history_dir_.Append(FILE_PATH_LITERAL("History Provider Cache"));
155 return true;
159 } 156 }
160 157
161 // Querying -------------------------------------------------------------------- 158 // Querying --------------------------------------------------------------------
162 159
163 ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms( 160 ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms(
164 const string16& term_string) { 161 const string16& term_string) {
165 return private_data_->HistoryItemsForTerms(term_string); 162 return private_data_->HistoryItemsForTerms(term_string);
166 } 163 }
167 164
168 // Updating -------------------------------------------------------------------- 165 // Updating --------------------------------------------------------------------
169 166
170 void InMemoryURLIndex::DeleteURL(const GURL& url) {
171 private_data_->DeleteURL(url);
172 }
173
174 void InMemoryURLIndex::Observe(int notification_type, 167 void InMemoryURLIndex::Observe(int notification_type,
175 const content::NotificationSource& source, 168 const content::NotificationSource& source,
176 const content::NotificationDetails& details) { 169 const content::NotificationDetails& details) {
177 switch (notification_type) { 170 switch (notification_type) {
178 case chrome::NOTIFICATION_HISTORY_URL_VISITED: 171 case chrome::NOTIFICATION_HISTORY_URL_VISITED:
179 OnURLVisited(content::Details<URLVisitedDetails>(details).ptr()); 172 OnURLVisited(content::Details<URLVisitedDetails>(details).ptr());
180 break; 173 break;
181 case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED: 174 case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED:
182 OnURLsModified( 175 OnURLsModified(
183 content::Details<history::URLsModifiedDetails>(details).ptr()); 176 content::Details<history::URLsModifiedDetails>(details).ptr());
184 break; 177 break;
185 case chrome::NOTIFICATION_HISTORY_URLS_DELETED: 178 case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
186 OnURLsDeleted( 179 OnURLsDeleted(
187 content::Details<history::URLsDeletedDetails>(details).ptr()); 180 content::Details<history::URLsDeletedDetails>(details).ptr());
188 break; 181 break;
189 case chrome::NOTIFICATION_HISTORY_LOADED: 182 case chrome::NOTIFICATION_HISTORY_LOADED:
190 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED, 183 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED,
191 content::Source<Profile>(profile_)); 184 content::Source<Profile>(profile_));
192 ScheduleRebuildFromHistory(); 185 ScheduleRebuildFromHistory();
193 break; 186 break;
194 case chrome::NOTIFICATION_IN_MEMORY_URL_CACHE_DATABASE_FAILURE:
195 RepairCacheDatabase();
196 break;
197 default: 187 default:
198 // For simplicity, the unit tests send us all notifications, even when 188 // For simplicity, the unit tests send us all notifications, even when
199 // we haven't registered for them, so don't assert here. 189 // we haven't registered for them, so don't assert here.
200 break; 190 break;
201 } 191 }
202 } 192 }
203 193
204 void InMemoryURLIndex::OnURLVisited(const URLVisitedDetails* details) { 194 void InMemoryURLIndex::OnURLVisited(const URLVisitedDetails* details) {
205 if (index_available_) 195 needs_to_be_cached_ |=
206 private_data_->UpdateURL(details->row); 196 private_data_->UpdateURL(details->row, languages_, scheme_whitelist_);
207 else
208 pending_updates_.push_back(IndexUpdateItem(UPDATE_VISIT, details->row));
209 } 197 }
210 198
211 void InMemoryURLIndex::OnURLsModified(const URLsModifiedDetails* details) { 199 void InMemoryURLIndex::OnURLsModified(const URLsModifiedDetails* details) {
212 for (URLRows::const_iterator row = details->changed_urls.begin(); 200 for (URLRows::const_iterator row = details->changed_urls.begin();
213 row != details->changed_urls.end(); ++row) { 201 row != details->changed_urls.end(); ++row)
214 if (index_available_) 202 needs_to_be_cached_ |=
215 private_data_->UpdateURL(*row); 203 private_data_->UpdateURL(*row, languages_, scheme_whitelist_);
216 else
217 pending_updates_.push_back(IndexUpdateItem(UPDATE_VISIT, *row));
218 }
219 } 204 }
220 205
221 void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) { 206 void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) {
222 if (details->all_history) { 207 if (details->all_history) {
223 PostResetPrivateDataTask(); 208 ClearPrivateData();
209 needs_to_be_cached_ = true;
224 } else { 210 } else {
225 for (URLRows::const_iterator row = details->rows.begin(); 211 for (URLRows::const_iterator row = details->rows.begin();
226 row != details->rows.end(); ++row) { 212 row != details->rows.end(); ++row)
227 if (index_available_) 213 needs_to_be_cached_ |= private_data_->DeleteURL(row->url());
228 DeleteURL(row->url()); 214 }
229 else 215 }
230 pending_updates_.push_back(IndexUpdateItem(DELETE_VISIT, *row)); 216
217 // Restoring from Cache --------------------------------------------------------
218
219 void InMemoryURLIndex::PostRestoreFromCacheFileTask() {
220 FilePath path;
221 if (!GetCacheFilePath(&path) || shutdown_)
222 return;
223 scoped_refptr<URLIndexPrivateData> restored_private_data =
224 new URLIndexPrivateData;
225 content::BrowserThread::PostTaskAndReply(
226 content::BrowserThread::FILE, FROM_HERE,
227 base::Bind(&URLIndexPrivateData::RestoreFromFileTask, path,
228 restored_private_data, languages_),
229 base::Bind(&InMemoryURLIndex::OnCacheLoadDone, AsWeakPtr(),
230 restored_private_data));
231 }
232
233 void InMemoryURLIndex::OnCacheLoadDone(
234 scoped_refptr<URLIndexPrivateData> private_data) {
235 if (private_data.get() && !private_data->Empty()) {
236 private_data_ = private_data;
237 if (restore_cache_observer_)
238 restore_cache_observer_->OnCacheRestoreFinished(true);
239 } else if (profile_) {
240 // When unable to restore from the cache file delete the cache file, if
241 // it exists, and then rebuild from the history database if it's available,
242 // otherwise wait until the history database loaded and then rebuild.
243 FilePath path;
244 if (!GetCacheFilePath(&path) || shutdown_)
245 return;
246 content::BrowserThread::PostBlockingPoolTask(
247 FROM_HERE, base::Bind(DeleteCacheFile, path));
248 HistoryService* service =
249 HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
250 if (service && service->backend_loaded()) {
251 ScheduleRebuildFromHistory();
252 } else {
253 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED,
254 content::Source<Profile>(profile_));
231 } 255 }
232 } 256 }
233 } 257 }
234 258
235 void InMemoryURLIndex::FlushPendingUpdates() {
236 for (PendingUpdates::iterator i = pending_updates_.begin();
237 i != pending_updates_.end(); ++i) {
238 if (i->update_type == UPDATE_VISIT)
239 private_data_->UpdateURL(i->row);
240 else if (i->update_type == DELETE_VISIT)
241 DeleteURL(i->row.url());
242 }
243 pending_updates_.clear();
244 }
245
246 // Restoring from Cache --------------------------------------------------------
247
248 void InMemoryURLIndex::PostRestoreFromCacheTask() {
249 // It's safe to restore from the cache database without using the sequenced
250 // worker pool as no other database operations will be going on at the same
251 // time.
252 BrowserThread::PostTaskAndReplyWithResult<bool>(
253 BrowserThread::DB, FROM_HERE,
254 base::Bind(&URLIndexPrivateData::RestoreFromCacheTask, private_data_),
255 base::Bind(&InMemoryURLIndex::OnCacheRestoreDone,
256 weak_ptr_factory_.GetWeakPtr()));
257 }
258
259 void InMemoryURLIndex::OnCacheRestoreDone(bool succeeded) {
260 if (shutdown_) {
261 NotifyHasLoaded();
262 return;
263 }
264 if (succeeded) {
265 FlushPendingUpdates();
266 index_available_ = true;
267 NotifyHasLoaded();
268 } else if (profile_) {
269 RebuildFromHistoryIfLoaded();
270 }
271 }
272
273 void InMemoryURLIndex::NotifyHasLoaded() {
274 FOR_EACH_OBSERVER(InMemoryURLIndex::Observer, observers_, Loaded());
275 }
276
277 // Restoring from the History DB ----------------------------------------------- 259 // Restoring from the History DB -----------------------------------------------
278 260
279 void InMemoryURLIndex::RebuildFromHistoryIfLoaded() {
280 // When unable to restore from the cache database, rebuild from the history
281 // database, if it's available, otherwise wait until the history database
282 // has loaded and then rebuild the index.
283 HistoryService* service =
284 HistoryServiceFactory::GetForProfileIfExists(profile_,
285 Profile::EXPLICIT_ACCESS);
286 if (service && service->backend_loaded()) {
287 ScheduleRebuildFromHistory();
288 } else {
289 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED,
290 content::Source<Profile>(profile_));
291 }
292 }
293
294 void InMemoryURLIndex::ScheduleRebuildFromHistory() { 261 void InMemoryURLIndex::ScheduleRebuildFromHistory() {
295 // It's possible that we were waiting on history to finish loading when
296 // the profile was told to shut down.
297 if (shutdown_)
298 return;
299 // Reset availability here as this function is called directly by unit tests.
300 index_available_ = false;
301 HistoryService* service = 262 HistoryService* service =
302 HistoryServiceFactory::GetForProfile(profile_, 263 HistoryServiceFactory::GetForProfile(profile_,
303 Profile::EXPLICIT_ACCESS); 264 Profile::EXPLICIT_ACCESS);
304 // Do not update the cache database while rebuilding.
305 private_data_->set_cache_enabled(false);
306 service->ScheduleDBTask( 265 service->ScheduleDBTask(
307 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(this), 266 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(
267 this, languages_, scheme_whitelist_),
308 &cache_reader_consumer_); 268 &cache_reader_consumer_);
309 } 269 }
310 270
311 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB( 271 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB(
312 bool succeeded, 272 bool succeeded,
313 scoped_refptr<URLIndexPrivateData> private_data) { 273 scoped_refptr<URLIndexPrivateData> private_data) {
314 DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) || 274 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
315 BrowserThread::CurrentlyOn(BrowserThread::UI));
316 if (shutdown_)
317 return;
318 if (succeeded) { 275 if (succeeded) {
319 private_data_ = private_data; 276 private_data_ = private_data;
320 private_data_->set_cache_enabled(true); 277 PostSaveToCacheFileTask(); // Cache the newly rebuilt index.
321 PostRefreshCacheTask(); // Cache the newly rebuilt index.
322 } else { 278 } else {
323 private_data_->set_cache_enabled(true); 279 private_data_->Clear(); // Dump the old private data.
324 PostResetPrivateDataTask(); 280 // There is no need to do anything with the cache file as it was deleted
281 // when the rebuild from the history operation was kicked off.
282 }
283 if (restore_cache_observer_)
284 restore_cache_observer_->OnCacheRestoreFinished(succeeded);
285 }
286
287 void InMemoryURLIndex::RebuildFromHistory(HistoryDatabase* history_db) {
288 private_data_ = URLIndexPrivateData::RebuildFromHistory(history_db,
289 languages_,
290 scheme_whitelist_);
291 }
292
293 // Saving to Cache -------------------------------------------------------------
294
295 void InMemoryURLIndex::PostSaveToCacheFileTask() {
296 FilePath path;
297 if (!GetCacheFilePath(&path))
298 return;
299 // If there is anything in our private data then make a copy of it and tell
300 // it to save itself to a file.
301 if (private_data_.get() && !private_data_->Empty()) {
302 // Note that ownership of the copy of our private data is passed to the
303 // completion closure below.
304 scoped_refptr<URLIndexPrivateData> private_data_copy =
305 private_data_->Duplicate();
306 scoped_refptr<RefCountedBool> succeeded(new RefCountedBool(false));
307 content::BrowserThread::PostTaskAndReply(
308 content::BrowserThread::FILE, FROM_HERE,
309 base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask,
310 private_data_copy, path, succeeded),
311 base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr(), succeeded));
312 } else {
313 // If there is no data in our index then delete any existing cache file.
314 content::BrowserThread::PostBlockingPoolTask(
315 FROM_HERE,
316 base::Bind(DeleteCacheFile, path));
325 } 317 }
326 } 318 }
327 319
328 // Reset Cache ----------------------------------------------------------------- 320 void InMemoryURLIndex::OnCacheSaveDone(
329 321 scoped_refptr<RefCountedBool> succeeded) {
330 void InMemoryURLIndex::PostResetPrivateDataTask() { 322 if (save_cache_observer_)
331 index_available_ = false; 323 save_cache_observer_->OnCacheSaveFinished(succeeded->value());
332 scoped_refptr<base::SequencedTaskRunner> runner =
333 BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(sequence_token_);
334 DCHECK(runner.get());
335 runner->PostTaskAndReply(FROM_HERE,
336 base::Bind(&URLIndexPrivateData::Reset, private_data_),
337 base::Bind(&InMemoryURLIndex::OnCacheRefreshOrResetDone,
338 weak_ptr_factory_.GetWeakPtr()));
339 }
340
341 // Refresh Cache ---------------------------------------------------------------
342
343 void InMemoryURLIndex::PostRefreshCacheTask() {
344 scoped_refptr<base::SequencedTaskRunner> runner =
345 BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(sequence_token_);
346 DCHECK(runner.get());
347 runner->PostTaskAndReply(FROM_HERE,
348 base::Bind(&URLIndexPrivateData::RefreshCacheTask, private_data_),
349 base::Bind(&InMemoryURLIndex::OnCacheRefreshOrResetDone,
350 weak_ptr_factory_.GetWeakPtr()));
351 }
352
353 void InMemoryURLIndex::OnCacheRefreshOrResetDone() {
354 if (shutdown_) {
355 NotifyHasLoaded();
356 return;
357 }
358 FlushPendingUpdates();
359 index_available_ = true;
360 NotifyHasLoaded();
361 }
362
363 // Repair Cache ----------------------------------------------------------------
364
365 void InMemoryURLIndex::RepairCacheDatabase() {
366 // The database will disable itself when it detects an error so re-enable the
367 // database and try to refresh it from scratch. If that fails then the
368 // database will be left in a disabled state and will be rebuilt from the
369 // history database the next time the profile is opened.
370 private_data_->set_cache_enabled(true);
371 PostRefreshCacheTask(); // Cache the newly rebuilt index.
372 } 324 }
373 325
374 } // namespace history 326 } // namespace history
OLDNEW
« no previous file with comments | « chrome/browser/history/in_memory_url_index.h ('k') | chrome/browser/history/in_memory_url_index_base_unittest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698