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 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 8 #include <queue> 9 #include <set> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/time/time.h" 17 #include "components/history/core/browser/history_types.h" 18 19 class GURL; 20 class TestingProfile; 21 22 namespace history { 23 24 class HistoryClient; 25 class HistoryDatabase; 26 struct HistoryDetails; 27 class ThumbnailDatabase; 28 29 // Delegate used to broadcast notifications to the main thread. 30 class BroadcastNotificationDelegate { 31 public: 32 // Schedules a broadcast of the given notification on the application main 33 // thread. 34 virtual void BroadcastNotifications(int type, 35 scoped_ptr<HistoryDetails> details) = 0; 36 37 // Tells typed url sync code to handle URL modifications or deletions. 38 virtual void NotifySyncURLsModified(URLRows* rows) = 0; 39 virtual void NotifySyncURLsDeleted(bool all_history, 40 bool expired, 41 URLRows* rows) = 0; 42 43 protected: 44 virtual ~BroadcastNotificationDelegate() {} 45 }; 46 47 // Encapsulates visit expiration criteria and type of visits to expire. 48 class ExpiringVisitsReader { 49 public: 50 virtual ~ExpiringVisitsReader() {} 51 // Populates |visits| from |db|, using provided |end_time| and |max_visits| 52 // cap. 53 virtual bool Read(base::Time end_time, HistoryDatabase* db, 54 VisitVector* visits, int max_visits) const = 0; 55 }; 56 57 typedef std::vector<const ExpiringVisitsReader*> ExpiringVisitsReaders; 58 59 // Helper component to HistoryBackend that manages expiration and deleting of 60 // history. 61 // 62 // It will automatically start periodically expiring old history once you call 63 // StartExpiringOldStuff(). 64 class ExpireHistoryBackend { 65 public: 66 // The delegate pointer must be non-NULL. We will NOT take ownership of it. 67 // HistoryClient may be NULL. The HistoryClient is used when expiring URLS so 68 // that we don't remove any URLs or favicons that are bookmarked (visits are 69 // removed though). 70 ExpireHistoryBackend(BroadcastNotificationDelegate* delegate, 71 HistoryClient* history_client); 72 ~ExpireHistoryBackend(); 73 74 // Completes initialization by setting the databases that this class will use. 75 void SetDatabases(HistoryDatabase* main_db, 76 ThumbnailDatabase* thumb_db); 77 78 // Begins periodic expiration of history older than the given threshold. This 79 // will continue until the object is deleted. 80 void StartExpiringOldStuff(base::TimeDelta expiration_threshold); 81 82 // Deletes everything associated with a URL. 83 void DeleteURL(const GURL& url); 84 85 // Deletes everything associated with each URL in the list. 86 void DeleteURLs(const std::vector<GURL>& url); 87 88 // Removes all visits to restrict_urls (or all URLs if empty) in the given 89 // time range, updating the URLs accordingly. 90 void ExpireHistoryBetween(const std::set<GURL>& restrict_urls, 91 base::Time begin_time, base::Time end_time); 92 93 // Removes all visits to all URLs with the given times, updating the 94 // URLs accordingly. |times| must be in reverse chronological order 95 // and not contain any duplicates. 96 void ExpireHistoryForTimes(const std::vector<base::Time>& times); 97 98 // Removes the given list of visits, updating the URLs accordingly (similar to 99 // ExpireHistoryBetween(), but affecting a specific set of visits). 100 void ExpireVisits(const VisitVector& visits); 101 102 // Expires all visits before and including the given time, updating the URLs 103 // accordingly. Currently only used for testing. 104 void ExpireHistoryBefore(base::Time end_time); 105 106 // Returns the current cut-off time before which we will start expiring stuff. 107 // Note that this as an absolute time rather than a delta, so the caller 108 // should not save it. 109 base::Time GetCurrentExpirationTime() const { 110 return base::Time::Now() - expiration_threshold_; 111 } 112 113 private: 114 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, DeleteFaviconsIfPossible); 115 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ExpireSomeOldHistory); 116 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ExpiringVisitsReader); 117 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ExpireSomeOldHistoryWithSource); 118 friend class ::TestingProfile; 119 120 struct DeleteEffects { 121 DeleteEffects(); 122 ~DeleteEffects(); 123 124 // The time range affected. These can be is_null() to be unbounded in one 125 // or both directions. 126 base::Time begin_time, end_time; 127 128 // The unique URL rows affected by this delete. 129 std::map<URLID, URLRow> affected_urls; 130 131 // The URLs modified, but not deleted, during this operation. 132 URLRows modified_urls; 133 134 // The URLs deleted during this operation. 135 URLRows deleted_urls; 136 137 // All favicon IDs that the deleted URLs had. Favicons will be shared 138 // between all URLs with the same favicon, so this is the set of IDs that we 139 // will need to check when the delete operations are complete. 140 std::set<favicon_base::FaviconID> affected_favicons; 141 142 // All favicon urls that were actually deleted from the thumbnail db. 143 std::set<GURL> deleted_favicons; 144 }; 145 146 // Deletes the visit-related stuff for all the visits in the given list, and 147 // adds the rows for unique URLs affected to the affected_urls list in 148 // the dependencies structure. 149 void DeleteVisitRelatedInfo(const VisitVector& visits, 150 DeleteEffects* effects); 151 152 // Finds or deletes dependency information for the given URL. Information that 153 // is specific to this URL (URL row, thumbnails, etc.) is deleted. 154 // 155 // This does not affect the visits! This is used for expiration as well as 156 // deleting from the UI, and they handle visits differently. 157 // 158 // Other information will be collected and returned in the output containers. 159 // This includes some of the things deleted that are needed elsewhere, plus 160 // some things like favicons that could be shared by many URLs, and need to 161 // be checked for deletion (this allows us to delete many URLs with only one 162 // check for shared information at the end). 163 // 164 // Assumes the main_db_ is non-NULL. 165 // 166 // NOTE: If the url is bookmarked only the segments and text db are updated, 167 // everything else is unchanged. This is done so that bookmarks retain their 168 // favicons and thumbnails. 169 void DeleteOneURL(const URLRow& url_row, 170 bool is_bookmarked, 171 DeleteEffects* effects); 172 173 // Deletes all the URLs in the given vector and handles their dependencies. 174 // This will delete starred URLs 175 void DeleteURLs(const URLRows& urls, DeleteEffects* effects); 176 177 // Expiration involves removing visits, then propagating the visits out from 178 // there and delete any orphaned URLs. These will be added to the deleted URLs 179 // field of the dependencies and DeleteOneURL will handle deleting out from 180 // there. This function does not handle favicons. 181 // 182 // When a URL is not deleted, the last visit time and the visit and typed 183 // counts will be updated. 184 // 185 // The visits in the given vector should have already been deleted from the 186 // database, and the list of affected URLs already be filled into 187 // |depenencies->affected_urls|. 188 // 189 // Starred URLs will not be deleted. The information in the dependencies that 190 // DeleteOneURL fills in will be updated, and this function will also delete 191 // any now-unused favicons. 192 void ExpireURLsForVisits(const VisitVector& visits, DeleteEffects* effects); 193 194 // Deletes the favicons listed in |effects->affected_favicons| if they are 195 // unsued. Fails silently (we don't care about favicons so much, so don't want 196 // to stop everything if it fails). Fills |expired_favicons| with the set of 197 // favicon urls that no longer have associated visits and were therefore 198 // expired. 199 void DeleteFaviconsIfPossible(DeleteEffects* effects); 200 201 // Enum representing what type of action resulted in the history DB deletion. 202 enum DeletionType { 203 // User initiated the deletion from the History UI. 204 DELETION_USER_INITIATED, 205 // History data was automatically expired due to being more than 90 days 206 // old. 207 DELETION_EXPIRED 208 }; 209 210 // Broadcasts URL modified and deleted notifications. 211 void BroadcastNotifications(DeleteEffects* effects, DeletionType type); 212 213 // Schedules a call to DoExpireIteration. 214 void ScheduleExpire(); 215 216 // Calls ExpireSomeOldHistory to expire some amount of old history, according 217 // to the items in work queue, and schedules another call to happen in the 218 // future. 219 void DoExpireIteration(); 220 221 // Tries to expire the oldest |max_visits| visits from history that are older 222 // than |time_threshold|. The return value indicates if we think there might 223 // be more history to expire with the current time threshold (it does not 224 // indicate success or failure). 225 bool ExpireSomeOldHistory(base::Time end_time, 226 const ExpiringVisitsReader* reader, 227 int max_visits); 228 229 // Tries to detect possible bad history or inconsistencies in the database 230 // and deletes items. For example, URLs with no visits. 231 void ParanoidExpireHistory(); 232 233 // Returns the HistoryClient, blocking until the bookmarks are loaded. This 234 // may return NULL during testing. 235 HistoryClient* GetHistoryClient(); 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 ThumbnailDatabase* thumb_db_; // Thumbnails and favicons. 255 256 // The threshold for "old" history where we will automatically delete it. 257 base::TimeDelta expiration_threshold_; 258 259 // List of all distinct types of readers. This list is used to populate the 260 // work queue. 261 ExpiringVisitsReaders readers_; 262 263 // Work queue for periodic expiration tasks, used by DoExpireIteration() to 264 // determine what to do at an iteration, as well as populate it for future 265 // iterations. 266 std::queue<const ExpiringVisitsReader*> work_queue_; 267 268 // Readers for various types of visits. 269 // TODO(dglazkov): If you are adding another one, please consider reorganizing 270 // into a map. 271 scoped_ptr<ExpiringVisitsReader> all_visits_reader_; 272 scoped_ptr<ExpiringVisitsReader> auto_subframe_visits_reader_; 273 274 // The HistoryClient; may be NULL. 275 // 276 // Use GetHistoryClient to access this, which makes sure the bookmarks are 277 // loaded before returning. 278 HistoryClient* history_client_; 279 280 // Used to generate runnable methods to do timers on this class. They will be 281 // automatically canceled when this class is deleted. 282 base::WeakPtrFactory<ExpireHistoryBackend> weak_factory_; 283 284 DISALLOW_COPY_AND_ASSIGN(ExpireHistoryBackend); 285 }; 286 287 } // namespace history 288 289 #endif // CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ 290