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

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

Issue 9030031: Move InMemoryURLIndex Caching Operations to FILE Thread (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Syncing with hopes of pleasing trybot update Created 8 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 | 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/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
8 #include "chrome/browser/history/history_notifications.h" 9 #include "chrome/browser/history/history_notifications.h"
9 #include "chrome/browser/history/url_database.h" 10 #include "chrome/browser/history/url_database.h"
10 #include "chrome/browser/history/url_index_private_data.h" 11 #include "chrome/browser/history/url_index_private_data.h"
11 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/common/chrome_notification_types.h" 13 #include "chrome/common/chrome_notification_types.h"
14 #include "chrome/common/url_constants.h"
15 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/notification_details.h" 16 #include "content/public/browser/notification_details.h"
17 #include "content/public/browser/notification_service.h"
14 #include "content/public/browser/notification_source.h" 18 #include "content/public/browser/notification_source.h"
15 19
16 using in_memory_url_index::InMemoryURLIndexCacheItem; 20 using in_memory_url_index::InMemoryURLIndexCacheItem;
17 21
18 namespace history { 22 namespace history {
19 23
24 // Called by DoSaveToCacheFile to delete any old cache file at |path| when
25 // there is no private data to save. Runs on the FILE thread.
26 void DeleteCacheFile(const FilePath& path) {
27 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
28 file_util::Delete(path, false);
29 }
30
31 // RefCountedBool --------------------------------------------------------------
32
33 RefCountedBool::~RefCountedBool() {}
34
35 // Restore/SaveCacheObserver ---------------------------------------------------
36
37 InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() {}
38
39 InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() {}
40
41 // RebuildPrivateDataFromHistoryDBTask -----------------------------------------
42
20 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 43 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
21 RebuildPrivateDataFromHistoryDBTask(InMemoryURLIndex* index) 44 RebuildPrivateDataFromHistoryDBTask(
45 InMemoryURLIndex* index,
46 const std::string& languages,
47 const std::set<std::string>& scheme_whitelist)
22 : index_(index), 48 : index_(index),
23 succeeded_(false) {} 49 languages_(languages),
50 scheme_whitelist_(scheme_whitelist),
51 succeeded_(false) {
52 }
24 53
25 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 54 InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
26 ~RebuildPrivateDataFromHistoryDBTask() {} 55 ~RebuildPrivateDataFromHistoryDBTask() {}
27 56
28 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread( 57 bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread(
29 HistoryBackend* backend, 58 HistoryBackend* backend,
30 HistoryDatabase* db) { 59 HistoryDatabase* db) {
31 data_.reset(URLIndexPrivateData::RebuildFromHistory(db)); 60 data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_,
32 succeeded_ = data_.get() && !data_->history_info_map_.empty(); 61 scheme_whitelist_);
62 succeeded_ = data_.get() && !data_->Empty();
33 if (!succeeded_) 63 if (!succeeded_)
34 data_.reset(); 64 data_->Clear();
35 return true; 65 return true;
36 } 66 }
37 67
38 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask:: 68 void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
39 DoneRunOnMainThread() { 69 DoneRunOnMainThread() {
40 if (succeeded_) 70 index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_.release());
41 index_->DoneRebuidingPrivateDataFromHistoryDB(data_.release());
42 } 71 }
43 72
73 // InMemoryURLIndex ------------------------------------------------------------
74
44 InMemoryURLIndex::InMemoryURLIndex(Profile* profile, 75 InMemoryURLIndex::InMemoryURLIndex(Profile* profile,
45 const FilePath& history_dir, 76 const FilePath& history_dir,
46 const std::string& languages) 77 const std::string& languages)
47 : profile_(profile), 78 : profile_(profile),
48 history_dir_(history_dir), 79 history_dir_(history_dir),
80 languages_(languages),
49 private_data_(new URLIndexPrivateData), 81 private_data_(new URLIndexPrivateData),
82 restore_cache_observer_(NULL),
83 save_cache_observer_(NULL),
50 shutdown_(false), 84 shutdown_(false),
51 needs_to_be_cached_(false) { 85 needs_to_be_cached_(false) {
52 private_data_->set_languages(languages); 86 InMemoryURLIndex::InitializeSchemeWhitelist(&scheme_whitelist_);
53 if (profile) { 87 if (profile) {
54 // TODO(mrossetti): Register for language change notifications. 88 // TODO(mrossetti): Register for language change notifications.
55 content::Source<Profile> source(profile); 89 content::Source<Profile> source(profile);
56 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source); 90 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source);
57 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_TYPED_URLS_MODIFIED, 91 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_TYPED_URLS_MODIFIED,
58 source); 92 source);
59 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source); 93 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source);
60 } 94 }
61 } 95 }
62 96
63 // Called only by unit tests. 97 // Called only by unit tests.
64 InMemoryURLIndex::InMemoryURLIndex() 98 InMemoryURLIndex::InMemoryURLIndex()
65 : profile_(NULL), 99 : profile_(NULL),
66 private_data_(new URLIndexPrivateData), 100 private_data_(new URLIndexPrivateData),
101 restore_cache_observer_(NULL),
102 save_cache_observer_(NULL),
67 shutdown_(false), 103 shutdown_(false),
68 needs_to_be_cached_(false) { 104 needs_to_be_cached_(false) {
105 InMemoryURLIndex::InitializeSchemeWhitelist(&scheme_whitelist_);
69 } 106 }
70 107
71 InMemoryURLIndex::~InMemoryURLIndex() { 108 InMemoryURLIndex::~InMemoryURLIndex() {
72 // If there was a history directory (which there won't be for some unit tests) 109 // If there was a history directory (which there won't be for some unit tests)
73 // then insure that the cache has already been saved. 110 // then insure that the cache has already been saved.
74 DCHECK(history_dir_.empty() || !needs_to_be_cached_); 111 DCHECK(history_dir_.empty() || !needs_to_be_cached_);
75 } 112 }
76 113
77 void InMemoryURLIndex::Init() { 114 void InMemoryURLIndex::Init() {
78 RestoreFromCacheFile(); 115 PostRestoreFromCacheFileTask();
79 } 116 }
80 117
81 void InMemoryURLIndex::ShutDown() { 118 void InMemoryURLIndex::ShutDown() {
82 registrar_.RemoveAll(); 119 registrar_.RemoveAll();
83 cache_reader_consumer_.CancelAllRequests(); 120 cache_reader_consumer_.CancelAllRequests();
84 shutdown_ = true; 121 shutdown_ = true;
85 SaveToCacheFile(); 122 PostSaveToCacheFileTask();
86 needs_to_be_cached_ = false; 123 needs_to_be_cached_ = false;
87 } 124 }
88 125
89 void InMemoryURLIndex::ClearPrivateData() { 126 void InMemoryURLIndex::ClearPrivateData() {
90 private_data_->Clear(); 127 private_data_->Clear();
91 } 128 }
92 129
93 bool InMemoryURLIndex::GetCacheFilePath(FilePath* file_path) { 130 bool InMemoryURLIndex::GetCacheFilePath(FilePath* file_path) {
94 if (history_dir_.empty()) 131 if (history_dir_.empty())
95 return false; 132 return false;
(...skipping 18 matching lines...) Expand all
114 OnURLVisited(content::Details<URLVisitedDetails>(details).ptr()); 151 OnURLVisited(content::Details<URLVisitedDetails>(details).ptr());
115 break; 152 break;
116 case chrome::NOTIFICATION_HISTORY_TYPED_URLS_MODIFIED: 153 case chrome::NOTIFICATION_HISTORY_TYPED_URLS_MODIFIED:
117 OnURLsModified( 154 OnURLsModified(
118 content::Details<history::URLsModifiedDetails>(details).ptr()); 155 content::Details<history::URLsModifiedDetails>(details).ptr());
119 break; 156 break;
120 case chrome::NOTIFICATION_HISTORY_URLS_DELETED: 157 case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
121 OnURLsDeleted( 158 OnURLsDeleted(
122 content::Details<history::URLsDeletedDetails>(details).ptr()); 159 content::Details<history::URLsDeletedDetails>(details).ptr());
123 break; 160 break;
124 case chrome::NOTIFICATION_HISTORY_LOADED: { 161 case chrome::NOTIFICATION_HISTORY_LOADED:
125 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED, 162 registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED,
126 content::Source<Profile>(profile_)); 163 content::Source<Profile>(profile_));
127 ScheduleRebuildFromHistory(); 164 ScheduleRebuildFromHistory();
128 break; 165 break;
129 }
130 default: 166 default:
131 // For simplicity, the unit tests send us all notifications, even when 167 // For simplicity, the unit tests send us all notifications, even when
132 // we haven't registered for them, so don't assert here. 168 // we haven't registered for them, so don't assert here.
133 break; 169 break;
134 } 170 }
135 } 171 }
136 172
137 void InMemoryURLIndex::OnURLVisited(const URLVisitedDetails* details) { 173 void InMemoryURLIndex::OnURLVisited(const URLVisitedDetails* details) {
138 needs_to_be_cached_ |= private_data_->UpdateURL(details->row); 174 needs_to_be_cached_ |=
175 private_data_->UpdateURL(details->row, languages_, scheme_whitelist_);
139 } 176 }
140 177
141 void InMemoryURLIndex::OnURLsModified(const URLsModifiedDetails* details) { 178 void InMemoryURLIndex::OnURLsModified(const URLsModifiedDetails* details) {
142 for (URLRows::const_iterator row = details->changed_urls.begin(); 179 for (URLRows::const_iterator row = details->changed_urls.begin();
143 row != details->changed_urls.end(); ++row) 180 row != details->changed_urls.end(); ++row)
144 needs_to_be_cached_ |= private_data_->UpdateURL(*row); 181 needs_to_be_cached_ |=
182 private_data_->UpdateURL(*row, languages_, scheme_whitelist_);
145 } 183 }
146 184
147 void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) { 185 void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) {
148 if (details->all_history) { 186 if (details->all_history) {
149 ClearPrivateData(); 187 ClearPrivateData();
150 needs_to_be_cached_ = true; 188 needs_to_be_cached_ = true;
151 } else { 189 } else {
152 for (URLRows::const_iterator row = details->rows.begin(); 190 for (URLRows::const_iterator row = details->rows.begin();
153 row != details->rows.end(); ++row) 191 row != details->rows.end(); ++row)
154 needs_to_be_cached_ |= private_data_->DeleteURL(row->url()); 192 needs_to_be_cached_ |= private_data_->DeleteURL(row->url());
155 } 193 }
156 } 194 }
157 195
158 // Restoring from Cache -------------------------------------------------------- 196 // Restoring from Cache --------------------------------------------------------
159 197
160 void InMemoryURLIndex::RestoreFromCacheFile() { 198 void InMemoryURLIndex::PostRestoreFromCacheFileTask() {
161 FilePath path; 199 FilePath path;
162 if (GetCacheFilePath(&path) && !shutdown_) 200 if (!GetCacheFilePath(&path) || shutdown_)
163 DoRestoreFromCacheFile(path); 201 return;
202 scoped_refptr<URLIndexPrivateData> restored_private_data =
203 new URLIndexPrivateData;
204 content::BrowserThread::PostTaskAndReply(
205 content::BrowserThread::FILE, FROM_HERE,
206 base::Bind(&URLIndexPrivateData::RestoreFromFileTask, path,
207 restored_private_data, languages_),
208 base::Bind(&InMemoryURLIndex::OnCacheLoadDone, AsWeakPtr(),
209 restored_private_data));
164 } 210 }
165 211
166 void InMemoryURLIndex::DoRestoreFromCacheFile(const FilePath& path) { 212 void InMemoryURLIndex::OnCacheLoadDone(
167 if (private_data_->RestoreFromFile(path)) 213 scoped_refptr<URLIndexPrivateData> private_data) {
168 return; 214 if (private_data.get() && !private_data->Empty()) {
169 215 private_data_ = private_data;
170 // When unable to restore from the cache file we must rebuild from the 216 if (restore_cache_observer_)
171 // history database. 217 restore_cache_observer_->OnCacheRestoreFinished(true);
172 HistoryService* service = profile_->GetHistoryServiceWithoutCreating(); 218 } else if (profile_) {
173 if (service && service->backend_loaded()) 219 // When unable to restore from the cache file delete the cache file, if
174 ScheduleRebuildFromHistory(); 220 // it exists, and then rebuild from the history database if it's available,
175 // We must wait to rebuild until the history backend has been loaded. 221 // otherwise wait until the history database loaded and then rebuild.
176 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED, 222 FilePath path;
177 content::Source<Profile>(profile_)); 223 if (!GetCacheFilePath(&path) || shutdown_)
224 return;
225 content::BrowserThread::PostBlockingPoolTask(
226 FROM_HERE, base::Bind(DeleteCacheFile, path));
227 HistoryService* service = profile_->GetHistoryServiceWithoutCreating();
228 if (service && service->backend_loaded()) {
229 ScheduleRebuildFromHistory();
230 } else {
231 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED,
232 content::Source<Profile>(profile_));
233 }
234 }
178 } 235 }
179 236
180 // Restoring from the History DB ----------------------------------------------- 237 // Restoring from the History DB -----------------------------------------------
181 238
182 void InMemoryURLIndex::ScheduleRebuildFromHistory() { 239 void InMemoryURLIndex::ScheduleRebuildFromHistory() {
183 HistoryService* service = 240 HistoryService* service =
184 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 241 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
185 service->ScheduleDBTask( 242 service->ScheduleDBTask(
186 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(this), 243 new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(
244 this, languages_, scheme_whitelist_),
187 &cache_reader_consumer_); 245 &cache_reader_consumer_);
188 } 246 }
189 247
190 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB( 248 void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB(
249 bool succeeded,
191 URLIndexPrivateData* data) { 250 URLIndexPrivateData* data) {
192 scoped_ptr<URLIndexPrivateData> private_data(data); 251 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
193 private_data_.swap(private_data); 252 scoped_refptr<URLIndexPrivateData> private_data(data);
194 // Cache the newly rebuilt index. 253 if (succeeded) {
195 FilePath cache_file_path; 254 private_data_ = private_data;
196 if (GetCacheFilePath(&cache_file_path)) 255 PostSaveToCacheFileTask(); // Cache the newly rebuilt index.
197 private_data_->SaveToFile(cache_file_path); 256 } else {
257 private_data_->Clear(); // Dump the old private data.
258 // There is no need to do anything with the cache file as it was deleted
259 // when the rebuild from the history operation was kicked off.
260 }
261 if (restore_cache_observer_)
262 restore_cache_observer_->OnCacheRestoreFinished(succeeded);
198 } 263 }
199 264
200 void InMemoryURLIndex::RebuildFromHistory(HistoryDatabase* history_db) { 265 void InMemoryURLIndex::RebuildFromHistory(HistoryDatabase* history_db) {
201 private_data_.reset(URLIndexPrivateData::RebuildFromHistory(history_db)); 266 private_data_ = URLIndexPrivateData::RebuildFromHistory(history_db,
267 languages_,
268 scheme_whitelist_);
202 } 269 }
203 270
204 // Saving to Cache ------------------------------------------------------------- 271 // Saving to Cache -------------------------------------------------------------
205 272
206 void InMemoryURLIndex::SaveToCacheFile() { 273 void InMemoryURLIndex::PostSaveToCacheFileTask() {
207 FilePath path; 274 FilePath path;
208 if (GetCacheFilePath(&path)) 275 if (!GetCacheFilePath(&path))
209 DoSaveToCacheFile(path); 276 return;
277 // If there is anything in our private data then make a copy of it and tell
278 // it to save itself to a file.
279 URLIndexPrivateData* private_data = private_data_.get();
280 if (private_data && !private_data->Empty()) {
281 // Note that ownership of the copy of our private data is passed to the
282 // completion closure below.
283 scoped_refptr<URLIndexPrivateData> private_data_copy =
284 private_data->Duplicate();
285 scoped_refptr<RefCountedBool> succeeded(new RefCountedBool(false));
286 content::BrowserThread::PostTaskAndReply(
287 content::BrowserThread::FILE, FROM_HERE,
288 base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask,
289 private_data_copy, path, succeeded),
290 base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr(), succeeded));
291 } else {
292 // If there is no data in our index then delete any existing cache file.
293 content::BrowserThread::PostBlockingPoolTask(
294 FROM_HERE,
295 base::Bind(DeleteCacheFile, path));
296 }
210 } 297 }
211 298
212 void InMemoryURLIndex::DoSaveToCacheFile(const FilePath& path) { 299 void InMemoryURLIndex::OnCacheSaveDone(
213 private_data_->SaveToFile(path); 300 scoped_refptr<RefCountedBool> succeeded) {
301 if (save_cache_observer_)
302 save_cache_observer_->OnCacheSaveFinished(succeeded->value());
303 }
304
305 // static
306 void InMemoryURLIndex::InitializeSchemeWhitelist(
307 std::set<std::string>* whitelist) {
308 DCHECK(whitelist);
309 whitelist->insert(std::string(chrome::kAboutScheme));
310 whitelist->insert(std::string(chrome::kChromeUIScheme));
311 whitelist->insert(std::string(chrome::kFileScheme));
312 whitelist->insert(std::string(chrome::kFtpScheme));
313 whitelist->insert(std::string(chrome::kHttpScheme));
314 whitelist->insert(std::string(chrome::kHttpsScheme));
315 whitelist->insert(std::string(chrome::kMailToScheme));
214 } 316 }
215 317
216 } // namespace history 318 } // 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