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.h" | 16 #include "base/message_loop.h" |
17 #include "chrome/browser/bookmarks/bookmark_service.h" | 17 #include "chrome/browser/bookmarks/bookmark_service.h" |
18 #include "chrome/browser/history/archived_database.h" | 18 #include "chrome/browser/history/archived_database.h" |
19 #include "chrome/browser/history/history_database.h" | 19 #include "chrome/browser/history/history_database.h" |
20 #include "chrome/browser/history/history_notifications.h" | 20 #include "chrome/browser/history/history_notifications.h" |
21 #include "chrome/browser/history/text_database.h" | |
22 #include "chrome/browser/history/text_database_manager.h" | |
23 #include "chrome/browser/history/thumbnail_database.h" | 21 #include "chrome/browser/history/thumbnail_database.h" |
24 #include "chrome/common/chrome_notification_types.h" | 22 #include "chrome/common/chrome_notification_types.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 |
(...skipping 132 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 void ExpireHistoryBackend::DeleteVisitRelatedInfo( | 396 void ExpireHistoryBackend::DeleteVisitRelatedInfo( |
418 const VisitVector& visits, | 397 const VisitVector& visits, |
419 DeleteDependencies* dependencies) { | 398 DeleteDependencies* dependencies) { |
420 for (size_t i = 0; i < visits.size(); i++) { | 399 for (size_t i = 0; i < visits.size(); i++) { |
421 // Delete the visit itself. | 400 // Delete the visit itself. |
422 main_db_->DeleteVisit(visits[i]); | 401 main_db_->DeleteVisit(visits[i]); |
423 | 402 |
424 // Add the URL row to the affected URL list. | 403 // Add the URL row to the affected URL list. |
425 std::map<URLID, URLRow>::const_iterator found = | 404 std::map<URLID, URLRow>::const_iterator found = |
426 dependencies->affected_urls.find(visits[i].url_id); | 405 dependencies->affected_urls.find(visits[i].url_id); |
427 const URLRow* cur_row = NULL; | |
428 if (found == dependencies->affected_urls.end()) { | 406 if (found == dependencies->affected_urls.end()) { |
429 URLRow row; | 407 URLRow row; |
430 if (!main_db_->GetURLRow(visits[i].url_id, &row)) | 408 if (!main_db_->GetURLRow(visits[i].url_id, &row)) |
431 continue; | 409 continue; |
432 dependencies->affected_urls[visits[i].url_id] = row; | 410 dependencies->affected_urls[visits[i].url_id] = row; |
433 cur_row = &dependencies->affected_urls[visits[i].url_id]; | |
434 } else { | |
435 cur_row = &found->second; | |
436 } | |
437 | |
438 // Delete any associated full-text indexed data. | |
439 if (visits[i].is_indexed && text_db_) { | |
440 text_db_->DeletePageData(visits[i].visit_time, cur_row->url(), | |
441 &dependencies->text_db_changes); | |
442 } | 411 } |
443 } | 412 } |
444 } | 413 } |
445 | 414 |
446 void ExpireHistoryBackend::DeleteOneURL( | 415 void ExpireHistoryBackend::DeleteOneURL( |
447 const URLRow& url_row, | 416 const URLRow& url_row, |
448 bool is_bookmarked, | 417 bool is_bookmarked, |
449 DeleteDependencies* dependencies) { | 418 DeleteDependencies* dependencies) { |
450 main_db_->DeleteSegmentForURL(url_row.id()); | 419 main_db_->DeleteSegmentForURL(url_row.id()); |
451 | 420 |
452 // The URL may be in the text database manager's temporary cache. | |
453 if (text_db_) { | |
454 std::set<GURL> restrict_urls; | |
455 restrict_urls.insert(url_row.url()); | |
456 text_db_->DeleteFromUncommitted(restrict_urls, base::Time(), base::Time()); | |
457 } | |
458 | |
459 if (!is_bookmarked) { | 421 if (!is_bookmarked) { |
460 dependencies->deleted_urls.push_back(url_row); | 422 dependencies->deleted_urls.push_back(url_row); |
461 | 423 |
462 // Delete stuff that references this URL. | 424 // Delete stuff that references this URL. |
463 if (thumb_db_) { | 425 if (thumb_db_) { |
464 thumb_db_->DeleteThumbnail(url_row.id()); | 426 thumb_db_->DeleteThumbnail(url_row.id()); |
465 | 427 |
466 // Collect shared information. | 428 // Collect shared information. |
467 std::vector<IconMapping> icon_mappings; | 429 std::vector<IconMapping> icon_mappings; |
468 if (thumb_db_->GetIconMappingsForPageURL(url_row.url(), &icon_mappings)) { | 430 if (thumb_db_->GetIconMappingsForPageURL(url_row.url(), &icon_mappings)) { |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 // to not do anything if nothing was deleted. | 679 // to not do anything if nothing was deleted. |
718 BroadcastDeleteNotifications(&deleted_dependencies, DELETION_ARCHIVED); | 680 BroadcastDeleteNotifications(&deleted_dependencies, DELETION_ARCHIVED); |
719 | 681 |
720 return more_to_expire; | 682 return more_to_expire; |
721 } | 683 } |
722 | 684 |
723 void ExpireHistoryBackend::ParanoidExpireHistory() { | 685 void ExpireHistoryBackend::ParanoidExpireHistory() { |
724 // TODO(brettw): Bug 1067331: write this to clean up any errors. | 686 // TODO(brettw): Bug 1067331: write this to clean up any errors. |
725 } | 687 } |
726 | 688 |
727 void ExpireHistoryBackend::ScheduleExpireHistoryIndexFiles() { | |
728 if (!text_db_) { | |
729 // Can't expire old history index files because we | |
730 // don't know where they're located. | |
731 return; | |
732 } | |
733 | |
734 TimeDelta delay = TimeDelta::FromMinutes(kIndexExpirationDelayMin); | |
735 base::MessageLoop::current()->PostDelayedTask( | |
736 FROM_HERE, | |
737 base::Bind(&ExpireHistoryBackend::DoExpireHistoryIndexFiles, | |
738 weak_factory_.GetWeakPtr()), | |
739 delay); | |
740 } | |
741 | |
742 void ExpireHistoryBackend::DoExpireHistoryIndexFiles() { | |
743 if (!text_db_) { | |
744 // The text database may have been closed since the task was scheduled. | |
745 return; | |
746 } | |
747 | |
748 Time::Exploded exploded; | |
749 Time::Now().LocalExplode(&exploded); | |
750 int cutoff_month = | |
751 exploded.year * 12 + exploded.month - kStoreHistoryIndexesForMonths; | |
752 TextDatabase::DBIdent cutoff_id = | |
753 (cutoff_month / 12) * 100 + (cutoff_month % 12); | |
754 | |
755 base::FilePath::StringType history_index_files_pattern = | |
756 TextDatabase::file_base(); | |
757 history_index_files_pattern.append(FILE_PATH_LITERAL("*")); | |
758 base::FileEnumerator file_enumerator( | |
759 text_db_->GetDir(), false, base::FileEnumerator::FILES, | |
760 history_index_files_pattern); | |
761 for (base::FilePath file = file_enumerator.Next(); !file.empty(); | |
762 file = file_enumerator.Next()) { | |
763 TextDatabase::DBIdent file_id = TextDatabase::FileNameToID(file); | |
764 if (file_id < cutoff_id) | |
765 file_util::Delete(file, false); | |
766 } | |
767 } | |
768 | |
769 BookmarkService* ExpireHistoryBackend::GetBookmarkService() { | 689 BookmarkService* ExpireHistoryBackend::GetBookmarkService() { |
770 // We use the bookmark service to determine if a URL is bookmarked. The | 690 // We use the bookmark service to determine if a URL is bookmarked. The |
771 // bookmark service is loaded on a separate thread and may not be done by the | 691 // bookmark service is loaded on a separate thread and may not be done by the |
772 // time we get here. We therefor block until the bookmarks have finished | 692 // time we get here. We therefor block until the bookmarks have finished |
773 // loading. | 693 // loading. |
774 if (bookmark_service_) | 694 if (bookmark_service_) |
775 bookmark_service_->BlockTillLoaded(); | 695 bookmark_service_->BlockTillLoaded(); |
776 return bookmark_service_; | 696 return bookmark_service_; |
777 } | 697 } |
778 | 698 |
779 } // namespace history | 699 } // namespace history |
OLD | NEW |