1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/expire_history_backend.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <limits> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/compiler_specific.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_service.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/archived_database.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history_database.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history_notifications.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/text_database.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/text_database_manager.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/thumbnail_database.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time; 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace history { 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of days by which the expiration threshold is advanced for items 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that we want to expire early, such as those of AUTO_SUBFRAME transition type. 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kEarlyExpirationAdvanceDays = 30; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Reads all types of visits starting from beginning of time to the given end 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// time. This is the most general reader. 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass AllVisitsReader : public ExpiringVisitsReader { 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual bool Read(Time end_time, HistoryDatabase* db, 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector* visits, int max_visits) const { 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(db) << "must have a database to operate upon"; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(visits) << "visit vector has to exist in order to populate it"; 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db->GetAllVisitsInRange(Time(), end_time, max_visits, visits); 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we got the maximum number of visits we asked for, we say there could 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be additional things to expire now. 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return static_cast<int>(visits->size()) == max_visits; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Reads only AUTO_SUBFRAME visits, within a computed range. The range is 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// computed as follows: 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * |begin_time| is read from the meta table. This value is updated whenever 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// there are no more additional visits to expire by this reader. 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * |end_time| is advanced forward by a constant (kEarlyExpirationAdvanceDay), 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// but not past the current time. 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass AutoSubframeVisitsReader : public ExpiringVisitsReader { 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual bool Read(Time end_time, HistoryDatabase* db, 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector* visits, int max_visits) const { 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(db) << "must have a database to operate upon"; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(visits) << "visit vector has to exist in order to populate it"; 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time begin_time = db->GetEarlyExpirationThreshold(); 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Advance |end_time| to expire early. 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time early_end_time = end_time + 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta::FromDays(kEarlyExpirationAdvanceDays); 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't want to set the early expiration threshold to a time in the 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // future. 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time now = Time::Now(); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (early_end_time > now) 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch early_end_time = now; 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db->GetVisitsInRangeForTransition(begin_time, early_end_time, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch max_visits, 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::AUTO_SUBFRAME, 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visits); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool more = static_cast<int>(visits->size()) == max_visits; 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!more) 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db->UpdateEarlyExpirationThreshold(early_end_time); 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return more; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns true if this visit is worth archiving. Otherwise, this visit is not 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// worth saving (for example, subframe navigations and redirects) and we can 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// just delete it when it gets old. 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ShouldArchiveVisit(const VisitRow& visit) { 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int no_qualifier = PageTransition::StripQualifier(visit.transition); 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // These types of transitions are always "important" and the user will want 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to see them. 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (no_qualifier == PageTransition::TYPED || 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch no_qualifier == PageTransition::AUTO_BOOKMARK || 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch no_qualifier == PageTransition::START_PAGE) 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only archive these "less important" transitions when they were the final 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // navigation and not part of a redirect chain. 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((no_qualifier == PageTransition::LINK || 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch no_qualifier == PageTransition::FORM_SUBMIT || 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch no_qualifier == PageTransition::KEYWORD || 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch no_qualifier == PageTransition::GENERATED) && 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit.transition & PageTransition::CHAIN_END) 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The transition types we ignore are AUTO_SUBFRAME and MANUAL_SUBFRAME. 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of visits we will expire very time we check for old items. This 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Prevents us from doing too much work any given time. 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kNumExpirePerIteration = 10; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of seconds between checking for items that should be expired when 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// we think there might be more items to expire. This timeout is used when the 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// last expiration found at least kNumExpirePerIteration and we want to check 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// again "soon." 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kExpirationDelaySec = 30; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of minutes between checking, as with kExpirationDelaySec, but 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// when we didn't find enough things to expire last time. If there was no 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// history to expire last iteration, it's likely there is nothing next 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// iteration, so we want to wait longer before checking to avoid wasting CPU. 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kExpirationEmptyDelayMin = 5; 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of minutes that we wait for before scheduling a task to 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// delete old history index files. 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kIndexExpirationDelayMin = 2; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of the most recent months for which we do not want to delete 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the history index files. 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kStoreHistoryIndexesForMonths = 12; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct ExpireHistoryBackend::DeleteDependencies { 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The time range affected. These can be is_null() to be unbounded in one 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // or both directions. 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time begin_time, end_time; 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ----- Filled by DeleteVisitRelatedInfo or manually if a function doesn't 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // call that function. ----- 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The unique URL rows affected by this delete. 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<URLID, URLRow> affected_urls; 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ----- Filled by DeleteOneURL ----- 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The URLs deleted during this operation. 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<URLRow> deleted_urls; 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The list of all favicon IDs that the affected URLs had. Favicons will be 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // shared between all URLs with the same favicon, so this is the set of IDs 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that we will need to check when the delete operations are complete. 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::set<FaviconID> affected_favicons; 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tracks the set of databases that have changed so we can optimize when 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when we're done. 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextDatabaseManager::ChangeSet text_db_changes; 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochExpireHistoryBackend::ExpireHistoryBackend( 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BroadcastNotificationDelegate* delegate, 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkService* bookmark_service) 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : delegate_(delegate), 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch main_db_(NULL), 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_(NULL), 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumb_db_(NULL), 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_db_(NULL), 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)), 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_service_(bookmark_service) { 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochExpireHistoryBackend::~ExpireHistoryBackend() { 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::SetDatabases(HistoryDatabase* main_db, 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ArchivedDatabase* archived_db, 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ThumbnailDatabase* thumb_db, 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextDatabaseManager* text_db) { 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch main_db_ = main_db; 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_ = archived_db; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumb_db_ = thumb_db; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_db_ = text_db; 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::DeleteURL(const GURL& url) { 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!main_db_) 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow url_row; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!main_db_->GetRowForURL(url, &url_row)) 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; // Nothing to delete. 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Collect all the visits and delete them. Note that we don't give up if 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // there are no visits, since the URL could still have an entry that we should 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // delete. 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(brettw): bug 1171148: We should also delete from the archived DB. 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector visits; 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch main_db_->GetVisitsForURL(url_row.id(), &visits); 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteDependencies dependencies; 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteVisitRelatedInfo(visits, &dependencies); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We skip ExpireURLsForVisits (since we are deleting from the URL, and not 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // starting with visits in a given time range). We therefore need to call the 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // deletion and favicon update functions manually. 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkService* bookmark_service = GetBookmarkService(); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_bookmarked = 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (bookmark_service && bookmark_service->IsBookmarked(url)); 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteOneURL(url_row, is_bookmarked, &dependencies); 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!is_bookmarked) 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteFaviconsIfPossible(dependencies.affected_favicons); 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_db_) 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_db_->OptimizeChangedDatabases(dependencies.text_db_changes); 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BroadcastDeleteNotifications(&dependencies); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::ExpireHistoryBetween( 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::set<GURL>& restrict_urls, Time begin_time, Time end_time) { 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!main_db_) 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // There may be stuff in the text database manager's temporary cache. 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_db_) 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_db_->DeleteFromUncommitted(restrict_urls, begin_time, end_time); 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find the affected visits and delete them. 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(brettw): bug 1171164: We should query the archived database here, too. 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector visits; 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch main_db_->GetAllVisitsInRange(begin_time, end_time, 0, &visits); 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!restrict_urls.empty()) { 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<URLID> url_ids; 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::set<GURL>::const_iterator url = restrict_urls.begin(); 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url != restrict_urls.end(); ++url) 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_ids.insert(main_db_->GetRowForURL(*url, NULL)); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector all_visits; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch all_visits.swap(visits); 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (VisitVector::iterator visit = all_visits.begin(); 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit != all_visits.end(); ++visit) { 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url_ids.find(visit->url_id) != url_ids.end()) 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visits.push_back(*visit); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visits.empty()) 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteDependencies dependencies; 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteVisitRelatedInfo(visits, &dependencies); 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delete or update the URLs affected. We want to update the visit counts 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // since this is called by the user who wants to delete their recent history, 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and we don't want to leave any evidence. 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExpireURLsForVisits(visits, &dependencies); 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteFaviconsIfPossible(dependencies.affected_favicons); 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // An is_null begin time means that all history should be deleted. 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BroadcastDeleteNotifications(&dependencies); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Pick up any bits possibly left over. 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ParanoidExpireHistory(); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::ArchiveHistoryBefore(Time end_time) { 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!main_db_) 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Archive as much history as possible before the given date. 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ArchiveSomeOldHistory(end_time, GetAllVisitsReader(), 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::numeric_limits<size_t>::max()); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ParanoidExpireHistory(); 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::InitWorkQueue() { 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(work_queue_.empty()) << "queue has to be empty prior to init"; 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < readers_.size(); i++) 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch work_queue_.push(readers_[i]); 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst ExpiringVisitsReader* ExpireHistoryBackend::GetAllVisitsReader() { 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!all_visits_reader_.get()) 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch all_visits_reader_.reset(new AllVisitsReader()); 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return all_visits_reader_.get(); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst ExpiringVisitsReader* 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExpireHistoryBackend::GetAutoSubframeVisitsReader() { 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!auto_subframe_visits_reader_.get()) 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auto_subframe_visits_reader_.reset(new AutoSubframeVisitsReader()); 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return auto_subframe_visits_reader_.get(); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::StartArchivingOldStuff( 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta expiration_threshold) { 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch expiration_threshold_ = expiration_threshold; 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove all readers, just in case this was method was called before. 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch readers_.clear(); 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For now, we explicitly add all known readers. If we come up with more 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // reader types (in case we want to expire different types of visits in 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // different ways), we can make it be populated by creator/owner of 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ExpireHistoryBackend. 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch readers_.push_back(GetAllVisitsReader()); 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch readers_.push_back(GetAutoSubframeVisitsReader()); 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Initialize the queue with all tasks for the first set of iterations. 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InitWorkQueue(); 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleArchive(); 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleExpireHistoryIndexFiles(); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::DeleteFaviconsIfPossible( 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::set<FaviconID>& favicon_set) { 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thumb_db_) 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::set<FaviconID>::const_iterator i = favicon_set.begin(); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != favicon_set.end(); ++i) { 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thumb_db_->HasMappingFor(*i)) 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumb_db_->DeleteFavicon(*i); 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::BroadcastDeleteNotifications( 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteDependencies* dependencies) { 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dependencies->deleted_urls.empty()) { 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Broadcast the URL deleted notification. Note that we also broadcast when 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we were requested to delete everything even if that was a NOP, since 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // some components care to know when history is deleted (it's up to them to 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // determine if they care whether anything was deleted). 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLsDeletedDetails* deleted_details = new URLsDeletedDetails; 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deleted_details->all_history = false; 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<URLRow> typed_urls_changed; // Collect this for later. 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < dependencies->deleted_urls.size(); i++) { 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deleted_details->urls.insert(dependencies->deleted_urls[i].url()); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dependencies->deleted_urls[i].typed_count() > 0) 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_urls_changed.push_back(dependencies->deleted_urls[i]); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->BroadcastNotifications(NotificationType::HISTORY_URLS_DELETED, 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deleted_details); 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Broadcast the typed URL changed modification (this updates the inline 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // autocomplete database). 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note: if we ever need to broadcast changes to more than just typed URLs, 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this notification should be changed rather than a new "non-typed" 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // notification added. The in-memory database can always do the filtering 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // itself in that case. 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!typed_urls_changed.empty()) { 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLsModifiedDetails* modified_details = new URLsModifiedDetails; 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch modified_details->changed_urls.swap(typed_urls_changed); 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->BroadcastNotifications( 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::HISTORY_TYPED_URLS_MODIFIED, 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch modified_details); 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::DeleteVisitRelatedInfo( 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const VisitVector& visits, 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteDependencies* dependencies) { 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < visits.size(); i++) { 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delete the visit itself. 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch main_db_->DeleteVisit(visits[i]); 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add the URL row to the affected URL list. 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<URLID, URLRow>::const_iterator found = 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dependencies->affected_urls.find(visits[i].url_id); 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const URLRow* cur_row = NULL; 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (found == dependencies->affected_urls.end()) { 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow row; 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!main_db_->GetURLRow(visits[i].url_id, &row)) 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dependencies->affected_urls[visits[i].url_id] = row; 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cur_row = &dependencies->affected_urls[visits[i].url_id]; 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cur_row = &found->second; 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delete any associated full-text indexed data. 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visits[i].is_indexed && text_db_) { 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_db_->DeletePageData(visits[i].visit_time, cur_row->url(), 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &dependencies->text_db_changes); 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::DeleteOneURL( 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const URLRow& url_row, 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_bookmarked, 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteDependencies* dependencies) { 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch main_db_->DeleteSegmentForURL(url_row.id()); 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The URL may be in the text database manager's temporary cache. 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_db_) { 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<GURL> restrict_urls; 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch restrict_urls.insert(url_row.url()); 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_db_->DeleteFromUncommitted(restrict_urls, base::Time(), base::Time()); 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!is_bookmarked) { 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dependencies->deleted_urls.push_back(url_row); 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delete stuff that references this URL. 411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (thumb_db_) { 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumb_db_->DeleteThumbnail(url_row.id()); 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Collect shared information. 415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<IconMapping> icon_mappings; 416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (thumb_db_->GetIconMappingsForPageURL(url_row.url(), &icon_mappings)) { 417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen m != icon_mappings.end(); ++m) { 419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dependencies->affected_favicons.insert(m->icon_id); 420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Delete the mapping entries for the url. 422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumb_db_->DeleteIconMappings(url_row.url()); 423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Last, delete the URL entry. 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch main_db_->DeleteURLRow(url_row.id()); 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochURLID ExpireHistoryBackend::ArchiveOneURL(const URLRow& url_row) { 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!archived_db_) 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See if this URL is present in the archived database already. Note that 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we must look up by ID since the URL ID will be different. 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow archived_row; 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (archived_db_->GetRowForURL(url_row.url(), &archived_row)) { 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(sky): bug 1168470, need to archive past search terms. 439731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(brettw): should be copy the visit counts over? This will mean that 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the main DB's visit counts are only for the last 3 months rather than 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // accumulative. 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_row.set_last_visit(url_row.last_visit()); 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_->UpdateURLRow(archived_row.id(), archived_row); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return archived_row.id(); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This row is not in the archived DB, add it. 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return archived_db_->AddURL(url_row); 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct ChangedURL { 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChangedURL() : visit_count(0), typed_count(0) {} 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int visit_count; 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int typed_count; 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::ExpireURLsForVisits( 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const VisitVector& visits, 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteDependencies* dependencies) { 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First find all unique URLs and the number of visits we're deleting for 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // each one. 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<URLID, ChangedURL> changed_urls; 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < visits.size(); i++) { 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChangedURL& cur = changed_urls[visits[i].url_id]; 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cur.visit_count++; 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: This code must stay in sync with HistoryBackend::AddPageVisit(). 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(pkasting): http://b/1148304 We shouldn't be marking so many URLs as 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // typed, which would eliminate the need for this code. 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type transition = 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::StripQualifier(visits[i].transition); 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((transition == PageTransition::TYPED && 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !PageTransition::IsRedirect(visits[i].transition)) || 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transition == PageTransition::KEYWORD_GENERATED) 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cur.typed_count++; 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check each unique URL with deleted visits. 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkService* bookmark_service = GetBookmarkService(); 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::map<URLID, ChangedURL>::const_iterator i = changed_urls.begin(); 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != changed_urls.end(); ++i) { 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The unique URL rows should already be filled into the dependencies. 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow& url_row = dependencies->affected_urls[i->first]; 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url_row.id()) 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; // URL row doesn't exist in the database. 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check if there are any other visits for this URL and update the time 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (the time change may not actually be synced to disk below when we're 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // archiving). 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitRow last_visit; 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (main_db_->GetMostRecentVisitForURL(url_row.id(), &last_visit)) 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_row.set_last_visit(last_visit.visit_time); 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_row.set_last_visit(Time()); 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't delete URLs with visits still in the DB, or bookmarked. 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_bookmarked = 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (bookmark_service && bookmark_service->IsBookmarked(url_row.url())); 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!is_bookmarked && url_row.last_visit().is_null()) { 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Not bookmarked and no more visits. Nuke the url. 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteOneURL(url_row, is_bookmarked, dependencies); 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: The calls to std::max() below are a backstop, but they should 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // never actually be needed unless the database is corrupt (I think). 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_row.set_visit_count( 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(0, url_row.visit_count() - i->second.visit_count)); 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_row.set_typed_count( 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::max(0, url_row.typed_count() - i->second.typed_count)); 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the db with the new details. 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch main_db_->UpdateURLRow(url_row.id(), url_row); 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::ArchiveURLsAndVisits( 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const VisitVector& visits, 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteDependencies* dependencies) { 5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!archived_db_ || !main_db_) 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure all unique URL rows are added to the dependency list and the 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // archived database. We will also keep the mapping between the main DB URLID 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and the archived one. 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<URLID, URLID> main_id_to_archived_id; 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < visits.size(); i++) { 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<URLID, URLRow>::const_iterator found = 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dependencies->affected_urls.find(visits[i].url_id); 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (found == dependencies->affected_urls.end()) { 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unique URL encountered, archive it. 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow row; // Row in the main DB. 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID archived_id; // ID in the archived DB. 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!main_db_->GetURLRow(visits[i].url_id, &row) || 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !(archived_id = ArchiveOneURL(row))) { 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Failure archiving, skip this one. 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only add URL to the dependency list once we know we successfully 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // archived it. 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch main_id_to_archived_id[row.id()] = archived_id; 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dependencies->affected_urls[row.id()] = row; 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Retrieve the sources for all the archived visits before archiving. 5503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // The returned visit_sources vector should contain the source for each visit 5513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // from visits at the same index. 5523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick VisitSourceMap visit_sources; 5533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick main_db_->GetVisitsSource(visits, &visit_sources); 5543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now archive the visits since we know the URL ID to make them reference. 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The source visit list should still reference the visits in the main DB, but 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we will update it to reflect only the visits that were successfully 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // archived. 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < visits.size(); i++) { 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Construct the visit that we will add to the archived database. We do 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // not store referring visits since we delete many of the visits when 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // archiving. 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitRow cur_visit(visits[i]); 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cur_visit.url_id = main_id_to_archived_id[cur_visit.url_id]; 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cur_visit.referring_visit = 0; 5663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick VisitSourceMap::iterator iter = visit_sources.find(visits[i].visit_id); 56772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen archived_db_->AddVisit( 56872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &cur_visit, 5693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick iter == visit_sources.end() ? SOURCE_BROWSED : iter->second); 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ignore failures, we will delete it from the main DB no matter what. 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::ScheduleArchive() { 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta delay; 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (work_queue_.empty()) { 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If work queue is empty, reset the work queue to contain all tasks and 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // schedule next iteration after a longer delay. 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InitWorkQueue(); 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delay = TimeDelta::FromMinutes(kExpirationEmptyDelayMin); 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delay = TimeDelta::FromSeconds(kExpirationDelaySec); 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, factory_.NewRunnableMethod( 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ExpireHistoryBackend::DoArchiveIteration), delay.InMilliseconds()); 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::DoArchiveIteration() { 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!work_queue_.empty()) << "queue has to be non-empty"; 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ExpiringVisitsReader* reader = work_queue_.front(); 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool more_to_expire = ArchiveSomeOldHistory(GetCurrentArchiveTime(), reader, 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kNumExpirePerIteration); 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch work_queue_.pop(); 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If there are more items to expire, add the reader back to the queue, thus 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // creating a new task for future iterations. 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (more_to_expire) 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch work_queue_.push(reader); 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleArchive(); 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExpireHistoryBackend::ArchiveSomeOldHistory( 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time end_time, 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ExpiringVisitsReader* reader, 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int max_visits) { 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!main_db_) 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add an extra time unit to given end time, because 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GetAllVisitsInRange, et al. queries' end value is non-inclusive. 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time effective_end_time = 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time::FromInternalValue(end_time.ToInternalValue() + 1); 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector affected_visits; 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool more_to_expire = reader->Read(effective_end_time, main_db_, 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &affected_visits, max_visits); 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Some visits we'll delete while others we'll archive. 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector deleted_visits, archived_visits; 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < affected_visits.size(); i++) { 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ShouldArchiveVisit(affected_visits[i])) 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_visits.push_back(affected_visits[i]); 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deleted_visits.push_back(affected_visits[i]); 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do the actual archiving. 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteDependencies archived_dependencies; 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ArchiveURLsAndVisits(archived_visits, &archived_dependencies); 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteVisitRelatedInfo(archived_visits, &archived_dependencies); 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteDependencies deleted_dependencies; 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteVisitRelatedInfo(deleted_visits, &deleted_dependencies); 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This will remove or archive all the affected URLs. Must do the deleting 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cleanup before archiving so the delete dependencies structure references 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // only those URLs that were actually deleted instead of having some visits 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // archived and then the rest deleted. 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExpireURLsForVisits(deleted_visits, &deleted_dependencies); 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExpireURLsForVisits(archived_visits, &archived_dependencies); 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a union of all affected favicons (we don't store favicons for 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // archived URLs) and delete them. 647ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::set<FaviconID> affected_favicons( 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_dependencies.affected_favicons); 649ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::set<FaviconID>::const_iterator i = 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deleted_dependencies.affected_favicons.begin(); 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != deleted_dependencies.affected_favicons.end(); ++i) { 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch affected_favicons.insert(*i); 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteFaviconsIfPossible(affected_favicons); 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Send notifications for the stuff that was deleted. These won't normally be 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in history views since they were subframes, but they will be in the visited 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // link system, which needs to be updated now. This function is smart enough 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to not do anything if nothing was deleted. 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BroadcastDeleteNotifications(&deleted_dependencies); 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return more_to_expire; 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::ParanoidExpireHistory() { 666731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(brettw): Bug 1067331: write this to clean up any errors. 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::ScheduleExpireHistoryIndexFiles() { 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!text_db_) { 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Can't expire old history index files because we 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // don't know where they're located. 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta delay = TimeDelta::FromMinutes(kIndexExpirationDelayMin); 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask( 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, factory_.NewRunnableMethod( 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ExpireHistoryBackend::DoExpireHistoryIndexFiles), 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delay.InMilliseconds()); 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExpireHistoryBackend::DoExpireHistoryIndexFiles() { 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time::Exploded exploded; 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time::Now().LocalExplode(&exploded); 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int cutoff_month = 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch exploded.year * 12 + exploded.month - kStoreHistoryIndexesForMonths; 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextDatabase::DBIdent cutoff_id = 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (cutoff_month / 12) * 100 + (cutoff_month % 12); 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath::StringType history_index_files_pattern = TextDatabase::file_base(); 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_index_files_pattern.append(FILE_PATH_LITERAL("*")); 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_util::FileEnumerator file_enumerator( 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_db_->GetDir(), false, file_util::FileEnumerator::FILES, 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_index_files_pattern); 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (FilePath file = file_enumerator.Next(); !file.empty(); 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file = file_enumerator.Next()) { 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextDatabase::DBIdent file_id = TextDatabase::FileNameToID(file); 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (file_id < cutoff_id) 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_util::Delete(file, false); 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBookmarkService* ExpireHistoryBackend::GetBookmarkService() { 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We use the bookmark service to determine if a URL is bookmarked. The 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bookmark service is loaded on a separate thread and may not be done by the 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // time we get here. We therefor block until the bookmarks have finished 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // loading. 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bookmark_service_) 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_service_->BlockTillLoaded(); 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bookmark_service_; 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace history 715