1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ 6 #define CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ 7 #pragma once 8 9 #include <queue> 10 #include <set> 11 #include <vector> 12 13 #include "base/basictypes.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/task.h" 17 #include "base/time.h" 18 #include "chrome/browser/history/history_types.h" 19 20 class BookmarkService; 21 class GURL; 22 class NotificationType; 23 class TestingProfile; 24 25 namespace history { 26 27 class ArchivedDatabase; 28 class HistoryDatabase; 29 struct HistoryDetails; 30 class TextDatabaseManager; 31 class ThumbnailDatabase; 32 33 // Delegate used to broadcast notifications to the main thread. 34 class BroadcastNotificationDelegate { 35 public: 36 // Schedules a broadcast of the given notification on the application main 37 // thread. The details argument will have ownership taken by this function. 38 virtual void BroadcastNotifications(NotificationType type, 39 HistoryDetails* details_deleted) = 0; 40 41 protected: ~BroadcastNotificationDelegate()42 virtual ~BroadcastNotificationDelegate() {} 43 }; 44 45 // Encapsulates visit expiration criteria and type of visits to expire. 46 class ExpiringVisitsReader { 47 public: ~ExpiringVisitsReader()48 virtual ~ExpiringVisitsReader() {} 49 // Populates |visits| from |db|, using provided |end_time| and |max_visits| 50 // cap. 51 virtual bool Read(base::Time end_time, HistoryDatabase* db, 52 VisitVector* visits, int max_visits) const = 0; 53 }; 54 55 typedef std::vector<const ExpiringVisitsReader*> ExpiringVisitsReaders; 56 57 // Helper component to HistoryBackend that manages expiration and deleting of 58 // history, as well as moving data from the main database to the archived 59 // database as it gets old. 60 // 61 // It will automatically start periodically archiving old history once you call 62 // StartArchivingOldStuff(). 63 class ExpireHistoryBackend { 64 public: 65 // The delegate pointer must be non-NULL. We will NOT take ownership of it. 66 // BookmarkService may be NULL. The BookmarkService is used when expiring 67 // URLs so that we don't remove any URLs or favicons that are bookmarked 68 // (visits are removed though). 69 ExpireHistoryBackend(BroadcastNotificationDelegate* delegate, 70 BookmarkService* bookmark_service); 71 ~ExpireHistoryBackend(); 72 73 // Completes initialization by setting the databases that this class will use. 74 void SetDatabases(HistoryDatabase* main_db, 75 ArchivedDatabase* archived_db, 76 ThumbnailDatabase* thumb_db, 77 TextDatabaseManager* text_db); 78 79 // Begins periodic expiration of history older than the given threshold. This 80 // will continue until the object is deleted. 81 void StartArchivingOldStuff(base::TimeDelta expiration_threshold); 82 83 // Deletes everything associated with a URL. 84 void DeleteURL(const GURL& url); 85 86 // Removes all visits to restrict_urls (or all URLs if empty) in the given 87 // time range, updating the URLs accordingly, 88 void ExpireHistoryBetween(const std::set<GURL>& restrict_urls, 89 base::Time begin_time, base::Time end_time); 90 91 // Archives all visits before and including the given time, updating the URLs 92 // accordingly. This function is intended for migrating old databases 93 // (which encompased all time) to the tiered structure and testing, and 94 // probably isn't useful for anything else. 95 void ArchiveHistoryBefore(base::Time end_time); 96 97 // Returns the current time that we are archiving stuff to. This will return 98 // the threshold in absolute time rather than a delta, so the caller should 99 // not save it. GetCurrentArchiveTime()100 base::Time GetCurrentArchiveTime() const { 101 return base::Time::Now() - expiration_threshold_; 102 } 103 104 private: 105 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, DeleteTextIndexForURL); 106 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, DeleteFaviconsIfPossible); 107 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ArchiveSomeOldHistory); 108 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ExpiringVisitsReader); 109 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ArchiveSomeOldHistoryWithSource); 110 friend class ::TestingProfile; 111 112 struct DeleteDependencies; 113 114 // Removes the data from the full text index associated with the given URL 115 // string/ID pair. If |update_visits| is set, the visits that reference the 116 // indexed data will be updated to reflect the fact that the indexed data is 117 // gone. Setting this to false is a performance optimization when the caller 118 // knows that the visits will be deleted after the call. 119 // 120 // TODO(brettw) when we have an "archived" history database, this should take 121 // a flag to optionally delete from there. This way it can be used for page 122 // re-indexing as well as for full URL deletion. 123 void DeleteTextIndexForURL(const GURL& url, URLID url_id, bool update_visits); 124 125 // Deletes the visit-related stuff for all the visits in the given list, and 126 // adds the rows for unique URLs affected to the affected_urls list in 127 // the dependencies structure. 128 // 129 // Deleted information is the visits themselves and the full-text index 130 // entries corresponding to them. 131 void DeleteVisitRelatedInfo(const VisitVector& visits, 132 DeleteDependencies* dependencies); 133 134 // Moves the given visits from the main database to the archived one. 135 void ArchiveVisits(const VisitVector& visits); 136 137 // Finds or deletes dependency information for the given URL. Information that 138 // is specific to this URL (URL row, thumbnails, full text indexed stuff, 139 // etc.) is deleted. 140 // 141 // This does not affect the visits! This is used for expiration as well as 142 // deleting from the UI, and they handle visits differently. 143 // 144 // Other information will be collected and returned in the output containers. 145 // This includes some of the things deleted that are needed elsewhere, plus 146 // some things like favicons that could be shared by many URLs, and need to 147 // be checked for deletion (this allows us to delete many URLs with only one 148 // check for shared information at the end). 149 // 150 // Assumes the main_db_ is non-NULL. 151 // 152 // NOTE: If the url is bookmarked only the segments and text db are updated, 153 // everything else is unchanged. This is done so that bookmarks retain their 154 // favicons and thumbnails. 155 void DeleteOneURL(const URLRow& url_row, 156 bool is_bookmarked, 157 DeleteDependencies* dependencies); 158 159 // Adds or merges the given URL row with the archived database, returning the 160 // ID of the URL in the archived database, or 0 on failure. The main (source) 161 // database will not be affected (the URL will have to be deleted later). 162 // 163 // Assumes the archived database is not NULL. 164 URLID ArchiveOneURL(const URLRow& url_row); 165 166 // Deletes all the URLs in the given vector and handles their dependencies. 167 // This will delete starred URLs 168 void DeleteURLs(const std::vector<URLRow>& urls, 169 DeleteDependencies* dependencies); 170 171 // Expiration involves removing visits, then propagating the visits out from 172 // there and delete any orphaned URLs. These will be added to the deleted URLs 173 // field of the dependencies and DeleteOneURL will handle deleting out from 174 // there. This function does not handle favicons. 175 // 176 // When a URL is not deleted and |archive| is not set, the last visit time and 177 // the visit and typed counts will be updated (we want to clear these when a 178 // user is deleting history manually, but not when we're normally expiring old 179 // things from history). 180 // 181 // The visits in the given vector should have already been deleted from the 182 // database, and the list of affected URLs already be filled into 183 // |depenencies->affected_urls|. 184 // 185 // Starred URLs will not be deleted. The information in the dependencies that 186 // DeleteOneURL fills in will be updated, and this function will also delete 187 // any now-unused favicons. 188 void ExpireURLsForVisits(const VisitVector& visits, 189 DeleteDependencies* dependencies); 190 191 // Creates entries in the archived database for the unique URLs referenced 192 // by the given visits. It will then add versions of the visits to that 193 // database. The source database WILL NOT BE MODIFIED. The source URLs and 194 // visits will have to be deleted in another pass. 195 // 196 // The affected URLs will be filled into the given dependencies structure. 197 void ArchiveURLsAndVisits(const VisitVector& visits, 198 DeleteDependencies* dependencies); 199 200 // Deletes the favicons listed in the set if unused. Fails silently (we don't 201 // care about favicons so much, so don't want to stop everything if it fails). 202 void DeleteFaviconsIfPossible(const std::set<FaviconID>& favicon_id); 203 204 // Broadcast the URL deleted notification. 205 void BroadcastDeleteNotifications(DeleteDependencies* dependencies); 206 207 // Schedules a call to DoArchiveIteration. 208 void ScheduleArchive(); 209 210 // Calls ArchiveSomeOldHistory to expire some amount of old history, according 211 // to the items in work queue, and schedules another call to happen in the 212 // future. 213 void DoArchiveIteration(); 214 215 // Tries to expire the oldest |max_visits| visits from history that are older 216 // than |time_threshold|. The return value indicates if we think there might 217 // be more history to expire with the current time threshold (it does not 218 // indicate success or failure). 219 bool ArchiveSomeOldHistory(base::Time end_time, 220 const ExpiringVisitsReader* reader, 221 int max_visits); 222 223 // Tries to detect possible bad history or inconsistencies in the database 224 // and deletes items. For example, URLs with no visits. 225 void ParanoidExpireHistory(); 226 227 // Schedules a call to DoExpireHistoryIndexFiles. 228 void ScheduleExpireHistoryIndexFiles(); 229 230 // Deletes old history index files. 231 void DoExpireHistoryIndexFiles(); 232 233 // Returns the BookmarkService, blocking until it is loaded. This may return 234 // NULL. 235 BookmarkService* GetBookmarkService(); 236 237 // Initializes periodic expiration work queue by populating it with with tasks 238 // for all known readers. 239 void InitWorkQueue(); 240 241 // Returns the reader for all visits. This method is only used by the unit 242 // tests. 243 const ExpiringVisitsReader* GetAllVisitsReader(); 244 245 // Returns the reader for AUTO_SUBFRAME visits. This method is only used by 246 // the unit tests. 247 const ExpiringVisitsReader* GetAutoSubframeVisitsReader(); 248 249 // Non-owning pointer to the notification delegate (guaranteed non-NULL). 250 BroadcastNotificationDelegate* delegate_; 251 252 // Non-owning pointers to the databases we deal with (MAY BE NULL). 253 HistoryDatabase* main_db_; // Main history database. 254 ArchivedDatabase* archived_db_; // Old history. 255 ThumbnailDatabase* thumb_db_; // Thumbnails and favicons. 256 TextDatabaseManager* text_db_; // Full text index. 257 258 // Used to generate runnable methods to do timers on this class. They will be 259 // automatically canceled when this class is deleted. 260 ScopedRunnableMethodFactory<ExpireHistoryBackend> factory_; 261 262 // The threshold for "old" history where we will automatically expire it to 263 // the archived database. 264 base::TimeDelta expiration_threshold_; 265 266 // List of all distinct types of readers. This list is used to populate the 267 // work queue. 268 ExpiringVisitsReaders readers_; 269 270 // Work queue for periodic expiration tasks, used by DoArchiveIteration() to 271 // determine what to do at an iteration, as well as populate it for future 272 // iterations. 273 std::queue<const ExpiringVisitsReader*> work_queue_; 274 275 // Readers for various types of visits. 276 // TODO(dglazkov): If you are adding another one, please consider reorganizing 277 // into a map. 278 scoped_ptr<ExpiringVisitsReader> all_visits_reader_; 279 scoped_ptr<ExpiringVisitsReader> auto_subframe_visits_reader_; 280 281 // The BookmarkService; may be null. This is owned by the Profile. 282 // 283 // Use GetBookmarkService to access this, which makes sure the service is 284 // loaded. 285 BookmarkService* bookmark_service_; 286 287 DISALLOW_COPY_AND_ASSIGN(ExpireHistoryBackend); 288 }; 289 290 } // namespace history 291 292 #endif // CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ 293