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/expire_history_backend.h" | 5 #include "chrome/browser/history/expire_history_backend.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <functional> | 8 #include <functional> |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
14 #include "base/files/file_enumerator.h" | 14 #include "base/files/file_enumerator.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
17 #include "chrome/browser/bookmarks/bookmark_service.h" | 17 #include "chrome/browser/bookmarks/bookmark_service.h" |
18 #include "chrome/browser/chrome_notification_types.h" | 18 #include "chrome/browser/chrome_notification_types.h" |
19 #include "chrome/browser/history/archived_database.h" | 19 #include "chrome/browser/history/archived_database.h" |
20 #include "chrome/browser/history/history_database.h" | 20 #include "chrome/browser/history/history_database.h" |
21 #include "chrome/browser/history/history_notifications.h" | 21 #include "chrome/browser/history/history_notifications.h" |
22 #include "chrome/browser/history/text_database.h" | |
23 #include "chrome/browser/history/text_database_manager.h" | |
24 #include "chrome/browser/history/thumbnail_database.h" | 22 #include "chrome/browser/history/thumbnail_database.h" |
25 | 23 |
26 using base::Time; | 24 using base::Time; |
27 using base::TimeDelta; | 25 using base::TimeDelta; |
28 | 26 |
29 namespace history { | 27 namespace history { |
30 | 28 |
31 namespace { | 29 namespace { |
32 | 30 |
33 // The number of days by which the expiration threshold is advanced for items | 31 // The number of days by which the expiration threshold is advanced for items |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 URLRows deleted_urls; | 163 URLRows deleted_urls; |
166 | 164 |
167 // The list of all favicon IDs that the affected URLs had. Favicons will be | 165 // The list of all favicon IDs that the affected URLs had. Favicons will be |
168 // shared between all URLs with the same favicon, so this is the set of IDs | 166 // shared between all URLs with the same favicon, so this is the set of IDs |
169 // that we will need to check when the delete operations are complete. | 167 // that we will need to check when the delete operations are complete. |
170 std::set<chrome::FaviconID> affected_favicons; | 168 std::set<chrome::FaviconID> affected_favicons; |
171 | 169 |
172 // The list of all favicon urls that were actually deleted from the thumbnail | 170 // The list of all favicon urls that were actually deleted from the thumbnail |
173 // db. | 171 // db. |
174 std::set<GURL> expired_favicons; | 172 std::set<GURL> expired_favicons; |
175 | |
176 // Tracks the set of databases that have changed so we can optimize when | |
177 // when we're done. | |
178 TextDatabaseManager::ChangeSet text_db_changes; | |
179 }; | 173 }; |
180 | 174 |
181 ExpireHistoryBackend::ExpireHistoryBackend( | 175 ExpireHistoryBackend::ExpireHistoryBackend( |
182 BroadcastNotificationDelegate* delegate, | 176 BroadcastNotificationDelegate* delegate, |
183 BookmarkService* bookmark_service) | 177 BookmarkService* bookmark_service) |
184 : delegate_(delegate), | 178 : delegate_(delegate), |
185 main_db_(NULL), | 179 main_db_(NULL), |
186 archived_db_(NULL), | 180 archived_db_(NULL), |
187 thumb_db_(NULL), | 181 thumb_db_(NULL), |
188 text_db_(NULL), | |
189 weak_factory_(this), | 182 weak_factory_(this), |
190 bookmark_service_(bookmark_service) { | 183 bookmark_service_(bookmark_service) { |
191 } | 184 } |
192 | 185 |
193 ExpireHistoryBackend::~ExpireHistoryBackend() { | 186 ExpireHistoryBackend::~ExpireHistoryBackend() { |
194 } | 187 } |
195 | 188 |
196 void ExpireHistoryBackend::SetDatabases(HistoryDatabase* main_db, | 189 void ExpireHistoryBackend::SetDatabases(HistoryDatabase* main_db, |
197 ArchivedDatabase* archived_db, | 190 ArchivedDatabase* archived_db, |
198 ThumbnailDatabase* thumb_db, | 191 ThumbnailDatabase* thumb_db) { |
199 TextDatabaseManager* text_db) { | |
200 main_db_ = main_db; | 192 main_db_ = main_db; |
201 archived_db_ = archived_db; | 193 archived_db_ = archived_db; |
202 thumb_db_ = thumb_db; | 194 thumb_db_ = thumb_db; |
203 text_db_ = text_db; | |
204 } | 195 } |
205 | 196 |
206 void ExpireHistoryBackend::DeleteURL(const GURL& url) { | 197 void ExpireHistoryBackend::DeleteURL(const GURL& url) { |
207 DeleteURLs(std::vector<GURL>(1, url)); | 198 DeleteURLs(std::vector<GURL>(1, url)); |
208 } | 199 } |
209 | 200 |
210 void ExpireHistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { | 201 void ExpireHistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { |
211 if (!main_db_) | 202 if (!main_db_) |
212 return; | 203 return; |
213 | 204 |
(...skipping 21 matching lines...) Expand all Loading... |
235 BookmarkService* bookmark_service = GetBookmarkService(); | 226 BookmarkService* bookmark_service = GetBookmarkService(); |
236 bool is_bookmarked = | 227 bool is_bookmarked = |
237 (bookmark_service && bookmark_service->IsBookmarked(*url)); | 228 (bookmark_service && bookmark_service->IsBookmarked(*url)); |
238 | 229 |
239 DeleteOneURL(url_row, is_bookmarked, &dependencies); | 230 DeleteOneURL(url_row, is_bookmarked, &dependencies); |
240 } | 231 } |
241 | 232 |
242 DeleteFaviconsIfPossible(dependencies.affected_favicons, | 233 DeleteFaviconsIfPossible(dependencies.affected_favicons, |
243 &dependencies.expired_favicons); | 234 &dependencies.expired_favicons); |
244 | 235 |
245 if (text_db_) | |
246 text_db_->OptimizeChangedDatabases(dependencies.text_db_changes); | |
247 | |
248 BroadcastDeleteNotifications(&dependencies, DELETION_USER_INITIATED); | 236 BroadcastDeleteNotifications(&dependencies, DELETION_USER_INITIATED); |
249 } | 237 } |
250 | 238 |
251 void ExpireHistoryBackend::ExpireHistoryBetween( | 239 void ExpireHistoryBackend::ExpireHistoryBetween( |
252 const std::set<GURL>& restrict_urls, Time begin_time, Time end_time) { | 240 const std::set<GURL>& restrict_urls, Time begin_time, Time end_time) { |
253 if (!main_db_) | 241 if (!main_db_) |
254 return; | 242 return; |
255 | 243 |
256 // There may be stuff in the text database manager's temporary cache. | |
257 if (text_db_) | |
258 text_db_->DeleteFromUncommitted(restrict_urls, begin_time, end_time); | |
259 | |
260 // Find the affected visits and delete them. | 244 // Find the affected visits and delete them. |
261 // TODO(brettw): bug 1171164: We should query the archived database here, too. | 245 // TODO(brettw): bug 1171164: We should query the archived database here, too. |
262 VisitVector visits; | 246 VisitVector visits; |
263 main_db_->GetAllVisitsInRange(begin_time, end_time, 0, &visits); | 247 main_db_->GetAllVisitsInRange(begin_time, end_time, 0, &visits); |
264 if (!restrict_urls.empty()) { | 248 if (!restrict_urls.empty()) { |
265 std::set<URLID> url_ids; | 249 std::set<URLID> url_ids; |
266 for (std::set<GURL>::const_iterator url = restrict_urls.begin(); | 250 for (std::set<GURL>::const_iterator url = restrict_urls.begin(); |
267 url != restrict_urls.end(); ++url) | 251 url != restrict_urls.end(); ++url) |
268 url_ids.insert(main_db_->GetRowForURL(*url, NULL)); | 252 url_ids.insert(main_db_->GetRowForURL(*url, NULL)); |
269 VisitVector all_visits; | 253 VisitVector all_visits; |
(...skipping 13 matching lines...) Expand all Loading... |
283 // duplicates, i.e. each member must be earlier than the one before | 267 // duplicates, i.e. each member must be earlier than the one before |
284 // it. | 268 // it. |
285 DCHECK( | 269 DCHECK( |
286 std::adjacent_find( | 270 std::adjacent_find( |
287 times.begin(), times.end(), std::less_equal<base::Time>()) == | 271 times.begin(), times.end(), std::less_equal<base::Time>()) == |
288 times.end()); | 272 times.end()); |
289 | 273 |
290 if (!main_db_) | 274 if (!main_db_) |
291 return; | 275 return; |
292 | 276 |
293 // There may be stuff in the text database manager's temporary cache. | |
294 if (text_db_) | |
295 text_db_->DeleteFromUncommittedForTimes(times); | |
296 | |
297 // Find the affected visits and delete them. | 277 // Find the affected visits and delete them. |
298 // TODO(brettw): bug 1171164: We should query the archived database here, too. | 278 // TODO(brettw): bug 1171164: We should query the archived database here, too. |
299 VisitVector visits; | 279 VisitVector visits; |
300 main_db_->GetVisitsForTimes(times, &visits); | 280 main_db_->GetVisitsForTimes(times, &visits); |
301 ExpireVisits(visits); | 281 ExpireVisits(visits); |
302 } | 282 } |
303 | 283 |
304 void ExpireHistoryBackend::ExpireVisits(const VisitVector& visits) { | 284 void ExpireHistoryBackend::ExpireVisits(const VisitVector& visits) { |
305 if (visits.empty()) | 285 if (visits.empty()) |
306 return; | 286 return; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 // For now, we explicitly add all known readers. If we come up with more | 341 // For now, we explicitly add all known readers. If we come up with more |
362 // reader types (in case we want to expire different types of visits in | 342 // reader types (in case we want to expire different types of visits in |
363 // different ways), we can make it be populated by creator/owner of | 343 // different ways), we can make it be populated by creator/owner of |
364 // ExpireHistoryBackend. | 344 // ExpireHistoryBackend. |
365 readers_.push_back(GetAllVisitsReader()); | 345 readers_.push_back(GetAllVisitsReader()); |
366 readers_.push_back(GetAutoSubframeVisitsReader()); | 346 readers_.push_back(GetAutoSubframeVisitsReader()); |
367 | 347 |
368 // Initialize the queue with all tasks for the first set of iterations. | 348 // Initialize the queue with all tasks for the first set of iterations. |
369 InitWorkQueue(); | 349 InitWorkQueue(); |
370 ScheduleArchive(); | 350 ScheduleArchive(); |
371 ScheduleExpireHistoryIndexFiles(); | |
372 } | 351 } |
373 | 352 |
374 void ExpireHistoryBackend::DeleteFaviconsIfPossible( | 353 void ExpireHistoryBackend::DeleteFaviconsIfPossible( |
375 const std::set<chrome::FaviconID>& favicon_set, | 354 const std::set<chrome::FaviconID>& favicon_set, |
376 std::set<GURL>* expired_favicons) { | 355 std::set<GURL>* expired_favicons) { |
377 if (!thumb_db_) | 356 if (!thumb_db_) |
378 return; | 357 return; |
379 | 358 |
380 for (std::set<chrome::FaviconID>::const_iterator i = favicon_set.begin(); | 359 for (std::set<chrome::FaviconID>::const_iterator i = favicon_set.begin(); |
381 i != favicon_set.end(); ++i) { | 360 i != favicon_set.end(); ++i) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 void ExpireHistoryBackend::DeleteVisitRelatedInfo( | 394 void ExpireHistoryBackend::DeleteVisitRelatedInfo( |
416 const VisitVector& visits, | 395 const VisitVector& visits, |
417 DeleteDependencies* dependencies) { | 396 DeleteDependencies* dependencies) { |
418 for (size_t i = 0; i < visits.size(); i++) { | 397 for (size_t i = 0; i < visits.size(); i++) { |
419 // Delete the visit itself. | 398 // Delete the visit itself. |
420 main_db_->DeleteVisit(visits[i]); | 399 main_db_->DeleteVisit(visits[i]); |
421 | 400 |
422 // Add the URL row to the affected URL list. | 401 // Add the URL row to the affected URL list. |
423 std::map<URLID, URLRow>::const_iterator found = | 402 std::map<URLID, URLRow>::const_iterator found = |
424 dependencies->affected_urls.find(visits[i].url_id); | 403 dependencies->affected_urls.find(visits[i].url_id); |
425 const URLRow* cur_row = NULL; | |
426 if (found == dependencies->affected_urls.end()) { | 404 if (found == dependencies->affected_urls.end()) { |
427 URLRow row; | 405 URLRow row; |
428 if (!main_db_->GetURLRow(visits[i].url_id, &row)) | 406 if (!main_db_->GetURLRow(visits[i].url_id, &row)) |
429 continue; | 407 continue; |
430 dependencies->affected_urls[visits[i].url_id] = row; | 408 dependencies->affected_urls[visits[i].url_id] = row; |
431 cur_row = &dependencies->affected_urls[visits[i].url_id]; | |
432 } else { | |
433 cur_row = &found->second; | |
434 } | |
435 | |
436 // Delete any associated full-text indexed data. | |
437 if (visits[i].is_indexed && text_db_) { | |
438 text_db_->DeletePageData(visits[i].visit_time, cur_row->url(), | |
439 &dependencies->text_db_changes); | |
440 } | 409 } |
441 } | 410 } |
442 } | 411 } |
443 | 412 |
444 void ExpireHistoryBackend::DeleteOneURL( | 413 void ExpireHistoryBackend::DeleteOneURL( |
445 const URLRow& url_row, | 414 const URLRow& url_row, |
446 bool is_bookmarked, | 415 bool is_bookmarked, |
447 DeleteDependencies* dependencies) { | 416 DeleteDependencies* dependencies) { |
448 main_db_->DeleteSegmentForURL(url_row.id()); | 417 main_db_->DeleteSegmentForURL(url_row.id()); |
449 | 418 |
450 // The URL may be in the text database manager's temporary cache. | |
451 if (text_db_) { | |
452 std::set<GURL> restrict_urls; | |
453 restrict_urls.insert(url_row.url()); | |
454 text_db_->DeleteFromUncommitted(restrict_urls, base::Time(), base::Time()); | |
455 } | |
456 | |
457 if (!is_bookmarked) { | 419 if (!is_bookmarked) { |
458 dependencies->deleted_urls.push_back(url_row); | 420 dependencies->deleted_urls.push_back(url_row); |
459 | 421 |
460 // Delete stuff that references this URL. | 422 // Delete stuff that references this URL. |
461 if (thumb_db_) { | 423 if (thumb_db_) { |
462 thumb_db_->DeleteThumbnail(url_row.id()); | 424 thumb_db_->DeleteThumbnail(url_row.id()); |
463 | 425 |
464 // Collect shared information. | 426 // Collect shared information. |
465 std::vector<IconMapping> icon_mappings; | 427 std::vector<IconMapping> icon_mappings; |
466 if (thumb_db_->GetIconMappingsForPageURL(url_row.url(), &icon_mappings)) { | 428 if (thumb_db_->GetIconMappingsForPageURL(url_row.url(), &icon_mappings)) { |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 // to not do anything if nothing was deleted. | 677 // to not do anything if nothing was deleted. |
716 BroadcastDeleteNotifications(&deleted_dependencies, DELETION_ARCHIVED); | 678 BroadcastDeleteNotifications(&deleted_dependencies, DELETION_ARCHIVED); |
717 | 679 |
718 return more_to_expire; | 680 return more_to_expire; |
719 } | 681 } |
720 | 682 |
721 void ExpireHistoryBackend::ParanoidExpireHistory() { | 683 void ExpireHistoryBackend::ParanoidExpireHistory() { |
722 // TODO(brettw): Bug 1067331: write this to clean up any errors. | 684 // TODO(brettw): Bug 1067331: write this to clean up any errors. |
723 } | 685 } |
724 | 686 |
725 void ExpireHistoryBackend::ScheduleExpireHistoryIndexFiles() { | |
726 if (!text_db_) { | |
727 // Can't expire old history index files because we | |
728 // don't know where they're located. | |
729 return; | |
730 } | |
731 | |
732 TimeDelta delay = TimeDelta::FromMinutes(kIndexExpirationDelayMin); | |
733 base::MessageLoop::current()->PostDelayedTask( | |
734 FROM_HERE, | |
735 base::Bind(&ExpireHistoryBackend::DoExpireHistoryIndexFiles, | |
736 weak_factory_.GetWeakPtr()), | |
737 delay); | |
738 } | |
739 | |
740 void ExpireHistoryBackend::DoExpireHistoryIndexFiles() { | |
741 if (!text_db_) { | |
742 // The text database may have been closed since the task was scheduled. | |
743 return; | |
744 } | |
745 | |
746 Time::Exploded exploded; | |
747 Time::Now().LocalExplode(&exploded); | |
748 int cutoff_month = | |
749 exploded.year * 12 + exploded.month - kStoreHistoryIndexesForMonths; | |
750 TextDatabase::DBIdent cutoff_id = | |
751 (cutoff_month / 12) * 100 + (cutoff_month % 12); | |
752 | |
753 base::FilePath::StringType history_index_files_pattern = | |
754 TextDatabase::file_base(); | |
755 history_index_files_pattern.append(FILE_PATH_LITERAL("*")); | |
756 base::FileEnumerator file_enumerator( | |
757 text_db_->GetDir(), false, base::FileEnumerator::FILES, | |
758 history_index_files_pattern); | |
759 for (base::FilePath file = file_enumerator.Next(); !file.empty(); | |
760 file = file_enumerator.Next()) { | |
761 TextDatabase::DBIdent file_id = TextDatabase::FileNameToID(file); | |
762 if (file_id < cutoff_id) | |
763 sql::Connection::Delete(file); | |
764 } | |
765 } | |
766 | |
767 BookmarkService* ExpireHistoryBackend::GetBookmarkService() { | 687 BookmarkService* ExpireHistoryBackend::GetBookmarkService() { |
768 // We use the bookmark service to determine if a URL is bookmarked. The | 688 // We use the bookmark service to determine if a URL is bookmarked. The |
769 // bookmark service is loaded on a separate thread and may not be done by the | 689 // bookmark service is loaded on a separate thread and may not be done by the |
770 // time we get here. We therefor block until the bookmarks have finished | 690 // time we get here. We therefor block until the bookmarks have finished |
771 // loading. | 691 // loading. |
772 if (bookmark_service_) | 692 if (bookmark_service_) |
773 bookmark_service_->BlockTillLoaded(); | 693 bookmark_service_->BlockTillLoaded(); |
774 return bookmark_service_; | 694 return bookmark_service_; |
775 } | 695 } |
776 | 696 |
777 } // namespace history | 697 } // namespace history |
OLD | NEW |