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