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

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

Issue 10837244: Replace HistoryQuickProvider protobuf-based caching with an SQLite-based database. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Tweak suppression. 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"
11 #include "chrome/browser/history/url_database.h" 12 #include "chrome/browser/history/url_database.h"
12 #include "chrome/browser/history/url_index_private_data.h" 13 #include "chrome/browser/history/url_index_private_data.h"
13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/chrome_notification_types.h" 15 #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 in_memory_url_index::InMemoryURLIndexCacheItem; 21 using content::BrowserThread;
22 22
23 namespace history { 23 namespace history {
24 24
25 // Called by DoSaveToCacheFile to delete any old cache file at |path| when 25 // InMemoryURLIndex::Observer --------------------------------------------------
26 // there is no private data to save. Runs on the FILE thread. 26
27 void DeleteCacheFile(const FilePath& path) { 27 InMemoryURLIndex::Observer::Observer(InMemoryURLIndex* index)
28 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 28 : index_(index) {
29 file_util::Delete(path, false); 29 DCHECK(index);
30 index_->AddObserver(this);
30 } 31 }
31 32
32 // Initializes a whitelist of URL schemes. 33 InMemoryURLIndex::Observer::~Observer() {
33 void InitializeSchemeWhitelist(std::set<std::string>* whitelist) { 34 index_->RemoveObserver(this);
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));
44 } 35 }
45 36
46 // RefCountedBool -------------------------------------------------------------- 37 void InMemoryURLIndex::Observer::Loaded() {
47 38 MessageLoop::current()->QuitNow();
48 RefCountedBool::~RefCountedBool() {} 39 }
49
50 // Restore/SaveCacheObserver ---------------------------------------------------
51
52 InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() {}
53
54 InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() {}
55 40
56 // RebuildPrivateDataFromHistoryDBTask ----------------------------------------- 41 // RebuildPrivateDataFromHistoryDBTask -----------------------------------------
57 42
58 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 43 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
59 RebuildPrivateDataFromHistoryDBTask( 44 RebuildPrivateDataFromHistoryDBTask(InMemoryURLIndex* index)
60 InMemoryURLIndex* index,
61 const std::string& languages,
62 const std::set<std::string>& scheme_whitelist)
63 : index_(index), 45 : index_(index),
64 languages_(languages),
65 scheme_whitelist_(scheme_whitelist),
66 succeeded_(false) { 46 succeeded_(false) {
67 } 47 }
68 48
49 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
50 ~RebuildPrivateDataFromHistoryDBTask() {
51 }
52
69 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread( 53 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread(
70 HistoryBackend* backend, 54 HistoryBackend* backend,
71 HistoryDatabase* db) { 55 HistoryDatabase* db) {
72 data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_, 56 data_ = URLIndexPrivateData::RebuildFromHistory(db, index_->private_data());
73 scheme_whitelist_);
74 succeeded_ = data_.get() && !data_->Empty(); 57 succeeded_ = data_.get() && !data_->Empty();
75 if (!succeeded_ && data_.get())
76 data_->Clear();
77 return true; 58 return true;
78 } 59 }
79 60
80 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 61 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
81 DoneRunOnMainThread() { 62 DoneRunOnMainThread() {
82 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_); 63 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_);
83 } 64 }
84 65
85 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 66 // IndexUpdateItem -------------------------------------------------------------
86 ~RebuildPrivateDataFromHistoryDBTask() { 67
68 InMemoryURLIndex::IndexUpdateItem::IndexUpdateItem(UpdateType update_type,
69 URLRow row)
70 : update_type(update_type),
71 row(row) {
87 } 72 }
88 73
74 InMemoryURLIndex::IndexUpdateItem::~IndexUpdateItem() {}
75
89 // InMemoryURLIndex ------------------------------------------------------------ 76 // InMemoryURLIndex ------------------------------------------------------------
90 77
91 InMemoryURLIndex::InMemoryURLIndex(Profile* profile, 78 InMemoryURLIndex::InMemoryURLIndex(Profile* profile,
92 const FilePath& history_dir, 79 const FilePath& history_dir,
93 const std::string& languages) 80 const std::string& languages)
94 : profile_(profile), 81 : profile_(profile),
82 languages_(languages),
95 history_dir_(history_dir), 83 history_dir_(history_dir),
96 languages_(languages), 84 private_data_(new URLIndexPrivateData(history_dir, languages)),
97 private_data_(new URLIndexPrivateData), 85 sequence_token_(BrowserThread::GetBlockingPool()->GetSequenceToken()),
98 restore_cache_observer_(NULL), 86 index_available_(false),
99 save_cache_observer_(NULL),
100 shutdown_(false), 87 shutdown_(false),
101 needs_to_be_cached_(false) { 88 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
102 InitializeSchemeWhitelist(&scheme_whitelist_);
103 if (profile) { 89 if (profile) {
104 // TODO(mrossetti): Register for language change notifications.
105 content::Source<Profile> source(profile); 90 content::Source<Profile> source(profile);
106 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source); 91 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source);
107 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 92 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
108 source); 93 source);
109 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source); 94 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source);
110 } 95 }
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.
111 } 105 }
112 106
113 // Called only by unit tests. 107 // Called only by unit tests.
114 InMemoryURLIndex::InMemoryURLIndex() 108 InMemoryURLIndex::InMemoryURLIndex(const FilePath& history_dir,
109 const std::string& languages)
115 : profile_(NULL), 110 : profile_(NULL),
116 private_data_(new URLIndexPrivateData), 111 languages_(languages),
117 restore_cache_observer_(NULL), 112 history_dir_(history_dir),
118 save_cache_observer_(NULL), 113 index_available_(false),
119 shutdown_(false), 114 shutdown_(false),
120 needs_to_be_cached_(false) { 115 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
121 InitializeSchemeWhitelist(&scheme_whitelist_);
122 } 116 }
123 117
124 InMemoryURLIndex::~InMemoryURLIndex() { 118 InMemoryURLIndex::~InMemoryURLIndex() {}
125 // If there was a history directory (which there won't be for some unit tests) 119
126 // then insure that the cache has already been saved. 120 void InMemoryURLIndex::Init(bool disable_cache) {
127 DCHECK(history_dir_.empty() || !needs_to_be_cached_); 121 if (disable_cache) {
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 }
128 } 133 }
129 134
130 void InMemoryURLIndex::Init() { 135 void InMemoryURLIndex::OnPrivateDataInitDone(bool succeeded) {
131 PostRestoreFromCacheFileTask(); 136 if (shutdown_)
137 return;
138 if (succeeded)
139 PostRestoreFromCacheTask();
140 else
141 RebuildFromHistoryIfLoaded();
132 } 142 }
133 143
134 void InMemoryURLIndex::ShutDown() { 144 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.
135 registrar_.RemoveAll(); 147 registrar_.RemoveAll();
136 cache_reader_consumer_.CancelAllRequests(); 148 cache_reader_consumer_.CancelAllRequests();
137 shutdown_ = true; 149 shutdown_ = true;
138 FilePath path; 150 private_data_->Shutdown();
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;
145 } 151 }
146 152
147 void InMemoryURLIndex::ClearPrivateData() { 153 void InMemoryURLIndex::AddObserver(InMemoryURLIndex::Observer* observer) {
148 private_data_->Clear(); 154 observers_.AddObserver(observer);
149 } 155 }
150 156
151 bool InMemoryURLIndex::GetCacheFilePath(FilePath* file_path) { 157 void InMemoryURLIndex::RemoveObserver(InMemoryURLIndex::Observer* observer) {
152 if (history_dir_.empty()) 158 observers_.RemoveObserver(observer);
153 return false;
154 *file_path = history_dir_.Append(FILE_PATH_LITERAL("History Provider Cache"));
155 return true;
156 } 159 }
157 160
158 // Querying -------------------------------------------------------------------- 161 // Querying --------------------------------------------------------------------
159 162
160 ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms( 163 ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms(
161 const string16& term_string) { 164 const string16& term_string) {
162 return private_data_->HistoryItemsForTerms(term_string); 165 return private_data_->HistoryItemsForTerms(term_string);
163 } 166 }
164 167
165 // Updating -------------------------------------------------------------------- 168 // Updating --------------------------------------------------------------------
166 169
170 void InMemoryURLIndex::DeleteURL(const GURL& url) {
171 private_data_->DeleteURL(url);
172 }
173
167 void InMemoryURLIndex::Observe(int notification_type, 174 void InMemoryURLIndex::Observe(int notification_type,
168 const content::NotificationSource& source, 175 const content::NotificationSource& source,
169 const content::NotificationDetails& details) { 176 const content::NotificationDetails& details) {
170 switch (notification_type) { 177 switch (notification_type) {
171 case chrome::NOTIFICATION_HISTORY_URL_VISITED: 178 case chrome::NOTIFICATION_HISTORY_URL_VISITED:
172 OnURLVisited(content::Details<URLVisitedDetails>(details).ptr()); 179 OnURLVisited(content::Details<URLVisitedDetails>(details).ptr());
173 break; 180 break;
174 case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED: 181 case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED:
175 OnURLsModified( 182 OnURLsModified(
176 content::Details<history::URLsModifiedDetails>(details).ptr()); 183 content::Details<history::URLsModifiedDetails>(details).ptr());
177 break; 184 break;
178 case chrome::NOTIFICATION_HISTORY_URLS_DELETED: 185 case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
179 OnURLsDeleted( 186 OnURLsDeleted(
180 content::Details<history::URLsDeletedDetails>(details).ptr()); 187 content::Details<history::URLsDeletedDetails>(details).ptr());
181 break; 188 break;
182 case chrome::NOTIFICATION_HISTORY_LOADED: 189 case chrome::NOTIFICATION_HISTORY_LOADED:
183 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED, 190 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED,
184 content::Source<Profile>(profile_)); 191 content::Source<Profile>(profile_));
185 ScheduleRebuildFromHistory(); 192 ScheduleRebuildFromHistory();
186 break; 193 break;
194 case chrome::NOTIFICATION_IN_MEMORY_URL_CACHE_DATABASE_FAILURE:
195 RepairCacheDatabase();
196 break;
187 default: 197 default:
188 // For simplicity, the unit tests send us all notifications, even when 198 // For simplicity, the unit tests send us all notifications, even when
189 // we haven't registered for them, so don't assert here. 199 // we haven't registered for them, so don't assert here.
190 break; 200 break;
191 } 201 }
192 } 202 }
193 203
194 void InMemoryURLIndex::OnURLVisited(const URLVisitedDetails* details) { 204 void InMemoryURLIndex::OnURLVisited(const URLVisitedDetails* details) {
195 needs_to_be_cached_ |= 205 if (index_available_)
196 private_data_->UpdateURL(details->row, languages_, scheme_whitelist_); 206 private_data_->UpdateURL(details->row);
207 else
208 pending_updates_.push_back(IndexUpdateItem(UPDATE_VISIT, details->row));
197 } 209 }
198 210
199 void InMemoryURLIndex::OnURLsModified(const URLsModifiedDetails* details) { 211 void InMemoryURLIndex::OnURLsModified(const URLsModifiedDetails* details) {
200 for (URLRows::const_iterator row = details->changed_urls.begin(); 212 for (URLRows::const_iterator row = details->changed_urls.begin();
201 row != details->changed_urls.end(); ++row) 213 row != details->changed_urls.end(); ++row) {
202 needs_to_be_cached_ |= 214 if (index_available_)
203 private_data_->UpdateURL(*row, languages_, scheme_whitelist_); 215 private_data_->UpdateURL(*row);
216 else
217 pending_updates_.push_back(IndexUpdateItem(UPDATE_VISIT, *row));
218 }
204 } 219 }
205 220
206 void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) { 221 void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) {
207 if (details->all_history) { 222 if (details->all_history) {
208 ClearPrivateData(); 223 PostResetPrivateDataTask();
209 needs_to_be_cached_ = true;
210 } else { 224 } else {
211 for (URLRows::const_iterator row = details->rows.begin(); 225 for (URLRows::const_iterator row = details->rows.begin();
212 row != details->rows.end(); ++row) 226 row != details->rows.end(); ++row) {
213 needs_to_be_cached_ |= private_data_->DeleteURL(row->url()); 227 if (index_available_)
228 DeleteURL(row->url());
229 else
230 pending_updates_.push_back(IndexUpdateItem(DELETE_VISIT, *row));
231 }
214 } 232 }
215 } 233 }
216 234
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
217 // Restoring from Cache -------------------------------------------------------- 246 // Restoring from Cache --------------------------------------------------------
218 247
219 void InMemoryURLIndex::PostRestoreFromCacheFileTask() { 248 void InMemoryURLIndex::PostRestoreFromCacheTask() {
220 FilePath path; 249 // It's safe to restore from the cache database without using the sequenced
221 if (!GetCacheFilePath(&path) || shutdown_) 250 // worker pool as no other database operations will be going on at the same
222 return; 251 // time.
223 scoped_refptr<URLIndexPrivateData> restored_private_data = 252 BrowserThread::PostTaskAndReplyWithResult<bool>(
224 new URLIndexPrivateData; 253 BrowserThread::DB, FROM_HERE,
225 content::BrowserThread::PostTaskAndReply( 254 base::Bind(&URLIndexPrivateData::RestoreFromCacheTask, private_data_),
226 content::BrowserThread::FILE, FROM_HERE, 255 base::Bind(&InMemoryURLIndex::OnCacheRestoreDone,
227 base::Bind(&URLIndexPrivateData::RestoreFromFileTask, path, 256 weak_ptr_factory_.GetWeakPtr()));
228 restored_private_data, languages_),
229 base::Bind(&InMemoryURLIndex::OnCacheLoadDone, AsWeakPtr(),
230 restored_private_data));
231 } 257 }
232 258
233 void InMemoryURLIndex::OnCacheLoadDone( 259 void InMemoryURLIndex::OnCacheRestoreDone(bool succeeded) {
234 scoped_refptr<URLIndexPrivateData> private_data) { 260 if (shutdown_) {
235 if (private_data.get() && !private_data->Empty()) { 261 NotifyHasLoaded();
236 private_data_ = private_data; 262 return;
237 if (restore_cache_observer_) 263 }
238 restore_cache_observer_->OnCacheRestoreFinished(true); 264 if (succeeded) {
265 FlushPendingUpdates();
266 index_available_ = true;
267 NotifyHasLoaded();
239 } else if (profile_) { 268 } else if (profile_) {
240 // When unable to restore from the cache file delete the cache file, if 269 RebuildFromHistoryIfLoaded();
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_));
255 }
256 } 270 }
257 } 271 }
258 272
273 void InMemoryURLIndex::NotifyHasLoaded() {
274 FOR_EACH_OBSERVER(InMemoryURLIndex::Observer, observers_, Loaded());
275 }
276
259 // Restoring from the History DB ----------------------------------------------- 277 // Restoring from the History DB -----------------------------------------------
260 278
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
261 void InMemoryURLIndex::ScheduleRebuildFromHistory() { 294 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;
262 HistoryService* service = 301 HistoryService* service =
263 HistoryServiceFactory::GetForProfile(profile_, 302 HistoryServiceFactory::GetForProfile(profile_,
264 Profile::EXPLICIT_ACCESS); 303 Profile::EXPLICIT_ACCESS);
304 // Do not update the cache database while rebuilding.
305 private_data_->set_cache_enabled(false);
265 service->ScheduleDBTask( 306 service->ScheduleDBTask(
266 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask( 307 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(this),
267 this, languages_, scheme_whitelist_),
268 &cache_reader_consumer_); 308 &cache_reader_consumer_);
269 } 309 }
270 310
271 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB( 311 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB(
272 bool succeeded, 312 bool succeeded,
273 scoped_refptr<URLIndexPrivateData> private_data) { 313 scoped_refptr<URLIndexPrivateData> private_data) {
274 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 314 DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
315 BrowserThread::CurrentlyOn(BrowserThread::UI));
316 if (shutdown_)
317 return;
275 if (succeeded) { 318 if (succeeded) {
276 private_data_ = private_data; 319 private_data_ = private_data;
277 PostSaveToCacheFileTask(); // Cache the newly rebuilt index. 320 private_data_->set_cache_enabled(true);
321 PostRefreshCacheTask(); // Cache the newly rebuilt index.
278 } else { 322 } else {
279 private_data_->Clear(); // Dump the old private data. 323 private_data_->set_cache_enabled(true);
280 // There is no need to do anything with the cache file as it was deleted 324 PostResetPrivateDataTask();
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));
317 } 325 }
318 } 326 }
319 327
320 void InMemoryURLIndex::OnCacheSaveDone( 328 // Reset Cache -----------------------------------------------------------------
321 scoped_refptr<RefCountedBool> succeeded) { 329
322 if (save_cache_observer_) 330 void InMemoryURLIndex::PostResetPrivateDataTask() {
323 save_cache_observer_->OnCacheSaveFinished(succeeded->value()); 331 index_available_ = false;
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.
324 } 372 }
325 373
326 } // namespace history 374 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698