OLD | NEW |
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/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | 10 #include "chrome/browser/bookmarks/bookmark_model_factory.h" |
11 #include "chrome/browser/chrome_notification_types.h" | |
12 #include "chrome/browser/history/history_notifications.h" | |
13 #include "chrome/browser/history/history_service.h" | 11 #include "chrome/browser/history/history_service.h" |
14 #include "chrome/browser/history/history_service_factory.h" | 12 #include "chrome/browser/history/history_service_factory.h" |
15 #include "chrome/browser/history/url_index_private_data.h" | 13 #include "chrome/browser/history/url_index_private_data.h" |
16 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/common/url_constants.h" | 15 #include "chrome/common/url_constants.h" |
18 #include "components/bookmarks/browser/bookmark_model.h" | 16 #include "components/bookmarks/browser/bookmark_model.h" |
19 #include "components/history/core/browser/url_database.h" | 17 #include "components/history/core/browser/url_database.h" |
20 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
21 #include "content/public/browser/notification_details.h" | |
22 #include "content/public/browser/notification_service.h" | |
23 #include "content/public/browser/notification_source.h" | |
24 | 19 |
25 using in_memory_url_index::InMemoryURLIndexCacheItem; | 20 using in_memory_url_index::InMemoryURLIndexCacheItem; |
26 | 21 |
27 namespace history { | 22 namespace history { |
28 | 23 |
29 // Called by DoSaveToCacheFile to delete any old cache file at |path| when | 24 // Called by DoSaveToCacheFile to delete any old cache file at |path| when |
30 // there is no private data to save. Runs on the FILE thread. | 25 // there is no private data to save. Runs on the FILE thread. |
31 void DeleteCacheFile(const base::FilePath& path) { | 26 void DeleteCacheFile(const base::FilePath& path) { |
32 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 27 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
33 base::DeleteFile(path, false); | 28 base::DeleteFile(path, false); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 history_dir_(history_dir), | 94 history_dir_(history_dir), |
100 languages_(languages), | 95 languages_(languages), |
101 private_data_(new URLIndexPrivateData), | 96 private_data_(new URLIndexPrivateData), |
102 restore_cache_observer_(NULL), | 97 restore_cache_observer_(NULL), |
103 save_cache_observer_(NULL), | 98 save_cache_observer_(NULL), |
104 shutdown_(false), | 99 shutdown_(false), |
105 restored_(false), | 100 restored_(false), |
106 needs_to_be_cached_(false), | 101 needs_to_be_cached_(false), |
107 history_service_observer_(this) { | 102 history_service_observer_(this) { |
108 InitializeSchemeWhitelist(&scheme_whitelist_); | 103 InitializeSchemeWhitelist(&scheme_whitelist_); |
109 if (profile) { | 104 // TODO(mrossetti): Register for language change notifications. |
110 // TODO(mrossetti): Register for language change notifications. | |
111 content::Source<Profile> source(profile); | |
112 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source); | |
113 } | |
114 if (history_service_) | 105 if (history_service_) |
115 history_service_observer_.Add(history_service_); | 106 history_service_observer_.Add(history_service_); |
116 } | 107 } |
117 | 108 |
118 // Called only by unit tests. | 109 // Called only by unit tests. |
119 InMemoryURLIndex::InMemoryURLIndex() | 110 InMemoryURLIndex::InMemoryURLIndex() |
120 : profile_(NULL), | 111 : profile_(NULL), |
121 history_service_(nullptr), | 112 history_service_(nullptr), |
122 history_client_(NULL), | 113 history_client_(NULL), |
123 private_data_(new URLIndexPrivateData), | 114 private_data_(new URLIndexPrivateData), |
(...skipping 11 matching lines...) Expand all Loading... |
135 // then insure that the cache has already been saved. | 126 // then insure that the cache has already been saved. |
136 DCHECK(history_dir_.empty() || !needs_to_be_cached_); | 127 DCHECK(history_dir_.empty() || !needs_to_be_cached_); |
137 } | 128 } |
138 | 129 |
139 void InMemoryURLIndex::Init() { | 130 void InMemoryURLIndex::Init() { |
140 PostRestoreFromCacheFileTask(); | 131 PostRestoreFromCacheFileTask(); |
141 } | 132 } |
142 | 133 |
143 void InMemoryURLIndex::ShutDown() { | 134 void InMemoryURLIndex::ShutDown() { |
144 history_service_observer_.RemoveAll(); | 135 history_service_observer_.RemoveAll(); |
145 registrar_.RemoveAll(); | |
146 cache_reader_tracker_.TryCancelAll(); | 136 cache_reader_tracker_.TryCancelAll(); |
147 shutdown_ = true; | 137 shutdown_ = true; |
148 base::FilePath path; | 138 base::FilePath path; |
149 if (!GetCacheFilePath(&path)) | 139 if (!GetCacheFilePath(&path)) |
150 return; | 140 return; |
151 private_data_tracker_.TryCancelAll(); | 141 private_data_tracker_.TryCancelAll(); |
152 URLIndexPrivateData::WritePrivateDataToCacheFileTask(private_data_, path); | 142 URLIndexPrivateData::WritePrivateDataToCacheFileTask(private_data_, path); |
153 needs_to_be_cached_ = false; | 143 needs_to_be_cached_ = false; |
154 } | 144 } |
155 | 145 |
(...skipping 21 matching lines...) Expand all Loading... |
177 languages_, | 167 languages_, |
178 history_client_); | 168 history_client_); |
179 } | 169 } |
180 | 170 |
181 // Updating -------------------------------------------------------------------- | 171 // Updating -------------------------------------------------------------------- |
182 | 172 |
183 void InMemoryURLIndex::DeleteURL(const GURL& url) { | 173 void InMemoryURLIndex::DeleteURL(const GURL& url) { |
184 private_data_->DeleteURL(url); | 174 private_data_->DeleteURL(url); |
185 } | 175 } |
186 | 176 |
187 void InMemoryURLIndex::Observe(int notification_type, | |
188 const content::NotificationSource& source, | |
189 const content::NotificationDetails& details) { | |
190 switch (notification_type) { | |
191 case chrome::NOTIFICATION_HISTORY_URLS_DELETED: | |
192 OnURLsDeleted( | |
193 content::Details<history::URLsDeletedDetails>(details).ptr()); | |
194 break; | |
195 default: | |
196 // For simplicity, the unit tests send us all notifications, even when | |
197 // we haven't registered for them, so don't assert here. | |
198 break; | |
199 } | |
200 } | |
201 | |
202 void InMemoryURLIndex::OnURLVisited(HistoryService* history_service, | 177 void InMemoryURLIndex::OnURLVisited(HistoryService* history_service, |
203 ui::PageTransition transition, | 178 ui::PageTransition transition, |
204 const URLRow& row, | 179 const URLRow& row, |
205 const RedirectList& redirects, | 180 const RedirectList& redirects, |
206 base::Time visit_time) { | 181 base::Time visit_time) { |
207 DCHECK_EQ(history_service_, history_service); | 182 DCHECK_EQ(history_service_, history_service); |
208 needs_to_be_cached_ |= private_data_->UpdateURL(history_service_, | 183 needs_to_be_cached_ |= private_data_->UpdateURL(history_service_, |
209 row, | 184 row, |
210 languages_, | 185 languages_, |
211 scheme_whitelist_, | 186 scheme_whitelist_, |
212 &private_data_tracker_); | 187 &private_data_tracker_); |
213 } | 188 } |
214 | 189 |
215 void InMemoryURLIndex::OnURLsModified(HistoryService* history_service, | 190 void InMemoryURLIndex::OnURLsModified(HistoryService* history_service, |
216 const URLRows& changed_urls) { | 191 const URLRows& changed_urls) { |
217 DCHECK_EQ(history_service_, history_service); | 192 DCHECK_EQ(history_service_, history_service); |
218 for (const auto& row : changed_urls) { | 193 for (const auto& row : changed_urls) { |
219 needs_to_be_cached_ |= private_data_->UpdateURL(history_service_, | 194 needs_to_be_cached_ |= private_data_->UpdateURL(history_service_, |
220 row, | 195 row, |
221 languages_, | 196 languages_, |
222 scheme_whitelist_, | 197 scheme_whitelist_, |
223 &private_data_tracker_); | 198 &private_data_tracker_); |
224 } | 199 } |
225 } | 200 } |
226 | 201 |
227 void InMemoryURLIndex::OnHistoryServiceLoaded(HistoryService* history_service) { | 202 void InMemoryURLIndex::OnURLsDeleted(HistoryService* history_service, |
228 ScheduleRebuildFromHistory(); | 203 bool all_history, |
229 } | 204 bool expired, |
230 | 205 const URLRows& deleted_rows, |
231 void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) { | 206 const std::set<GURL>& favicon_urls) { |
232 if (details->all_history) { | 207 if (all_history) { |
233 ClearPrivateData(); | 208 ClearPrivateData(); |
234 needs_to_be_cached_ = true; | 209 needs_to_be_cached_ = true; |
235 } else { | 210 } else { |
236 for (URLRows::const_iterator row = details->rows.begin(); | 211 for (const auto& row : deleted_rows) |
237 row != details->rows.end(); ++row) | 212 needs_to_be_cached_ |= private_data_->DeleteURL(row.url()); |
238 needs_to_be_cached_ |= private_data_->DeleteURL(row->url()); | |
239 } | 213 } |
240 // If we made changes, destroy the previous cache. Otherwise, if we go | 214 // If we made changes, destroy the previous cache. Otherwise, if we go |
241 // through an unclean shutdown (and therefore fail to write a new cache file), | 215 // through an unclean shutdown (and therefore fail to write a new cache file), |
242 // when Chrome restarts and we restore from the previous cache, we'll end up | 216 // when Chrome restarts and we restore from the previous cache, we'll end up |
243 // searching over URLs that may be deleted. This would be wrong, and | 217 // searching over URLs that may be deleted. This would be wrong, and |
244 // surprising to the user who bothered to delete some URLs from his/her | 218 // surprising to the user who bothered to delete some URLs from his/her |
245 // history. In this situation, deleting the cache is a better solution than | 219 // history. In this situation, deleting the cache is a better solution than |
246 // writing a new cache (after deleting the URLs from the in-memory structure) | 220 // writing a new cache (after deleting the URLs from the in-memory structure) |
247 // because deleting the cache forces it to be rebuilt from history upon | 221 // because deleting the cache forces it to be rebuilt from history upon |
248 // startup. If we instead write a new, updated cache then at the time of next | 222 // startup. If we instead write a new, updated cache then at the time of next |
249 // startup (after an unclean shutdown) we will not rebuild the in-memory data | 223 // startup (after an unclean shutdown) we will not rebuild the in-memory data |
250 // structures from history but rather use the cache. This solution is | 224 // structures from history but rather use the cache. This solution is |
251 // mediocre because this cache may not have the most-recently-visited URLs | 225 // mediocre because this cache may not have the most-recently-visited URLs |
252 // in it (URLs visited after user deleted some URLs from history), which | 226 // in it (URLs visited after user deleted some URLs from history), which |
253 // would be odd and confusing. It's better to force a rebuild. | 227 // would be odd and confusing. It's better to force a rebuild. |
254 base::FilePath path; | 228 base::FilePath path; |
255 if (needs_to_be_cached_ && GetCacheFilePath(&path)) { | 229 if (needs_to_be_cached_ && GetCacheFilePath(&path)) { |
256 content::BrowserThread::PostBlockingPoolTask( | 230 content::BrowserThread::PostBlockingPoolTask( |
257 FROM_HERE, base::Bind(DeleteCacheFile, path)); | 231 FROM_HERE, base::Bind(DeleteCacheFile, path)); |
258 } | 232 } |
259 } | 233 } |
260 | 234 |
| 235 void InMemoryURLIndex::OnHistoryServiceLoaded(HistoryService* history_service) { |
| 236 ScheduleRebuildFromHistory(); |
| 237 } |
| 238 |
261 // Restoring from Cache -------------------------------------------------------- | 239 // Restoring from Cache -------------------------------------------------------- |
262 | 240 |
263 void InMemoryURLIndex::PostRestoreFromCacheFileTask() { | 241 void InMemoryURLIndex::PostRestoreFromCacheFileTask() { |
264 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 242 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
265 TRACE_EVENT0("browser", "InMemoryURLIndex::PostRestoreFromCacheFileTask"); | 243 TRACE_EVENT0("browser", "InMemoryURLIndex::PostRestoreFromCacheFileTask"); |
266 | 244 |
267 base::FilePath path; | 245 base::FilePath path; |
268 if (!GetCacheFilePath(&path) || shutdown_) { | 246 if (!GetCacheFilePath(&path) || shutdown_) { |
269 restored_ = true; | 247 restored_ = true; |
270 if (restore_cache_observer_) | 248 if (restore_cache_observer_) |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 base::Bind(DeleteCacheFile, path)); | 350 base::Bind(DeleteCacheFile, path)); |
373 } | 351 } |
374 } | 352 } |
375 | 353 |
376 void InMemoryURLIndex::OnCacheSaveDone(bool succeeded) { | 354 void InMemoryURLIndex::OnCacheSaveDone(bool succeeded) { |
377 if (save_cache_observer_) | 355 if (save_cache_observer_) |
378 save_cache_observer_->OnCacheSaveFinished(succeeded); | 356 save_cache_observer_->OnCacheSaveFinished(succeeded); |
379 } | 357 } |
380 | 358 |
381 } // namespace history | 359 } // namespace history |
OLD | NEW |