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