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.
5 #ifndef CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_
6 #define CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_
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"
25 class HistoryDatabase;
26 struct HistoryDetails;
27 class ThumbnailDatabase;
29 // Delegate used to broadcast notifications to the main thread.
30 class BroadcastNotificationDelegate {
32 // Schedules a broadcast of the given notification on the application main
34 virtual void BroadcastNotifications(int type,
35 scoped_ptr<HistoryDetails> details) = 0;
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,
44 virtual ~BroadcastNotificationDelegate() {}
47 // Encapsulates visit expiration criteria and type of visits to expire.
48 class ExpiringVisitsReader {
50 virtual ~ExpiringVisitsReader() {}
51 // Populates |visits| from |db|, using provided |end_time| and |max_visits|
53 virtual bool Read(base::Time end_time, HistoryDatabase* db,
54 VisitVector* visits, int max_visits) const = 0;
57 typedef std::vector<const ExpiringVisitsReader*> ExpiringVisitsReaders;
59 // Helper component to HistoryBackend that manages expiration and deleting of
62 // It will automatically start periodically expiring old history once you call
63 // StartExpiringOldStuff().
64 class ExpireHistoryBackend {
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
70 ExpireHistoryBackend(BroadcastNotificationDelegate* delegate,
71 HistoryClient* history_client);
72 ~ExpireHistoryBackend();
74 // Completes initialization by setting the databases that this class will use.
75 void SetDatabases(HistoryDatabase* main_db,
76 ThumbnailDatabase* thumb_db);
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);
82 // Deletes everything associated with a URL.
83 void DeleteURL(const GURL& url);
85 // Deletes everything associated with each URL in the list.
86 void DeleteURLs(const std::vector<GURL>& url);
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);
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);
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);
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);
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_;
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;
120 struct DeleteEffects {
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;
128 // The unique URL rows affected by this delete.
129 std::map<URLID, URLRow> affected_urls;
131 // The URLs modified, but not deleted, during this operation.
132 URLRows modified_urls;
134 // The URLs deleted during this operation.
135 URLRows deleted_urls;
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;
142 // All favicon urls that were actually deleted from the thumbnail db.
143 std::set<GURL> deleted_favicons;
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);
152 // Finds or deletes dependency information for the given URL. Information that
153 // is specific to this URL (URL row, thumbnails, etc.) is deleted.
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.
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).
164 // Assumes the main_db_ is non-NULL.
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,
171 DeleteEffects* effects);
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);
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.
182 // When a URL is not deleted, the last visit time and the visit and typed
183 // counts will be updated.
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|.
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);
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
199 void DeleteFaviconsIfPossible(DeleteEffects* effects);
201 // Enum representing what type of action resulted in the history DB deletion.
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
210 // Broadcasts URL modified and deleted notifications.
211 void BroadcastNotifications(DeleteEffects* effects, DeletionType type);
213 // Schedules a call to DoExpireIteration.
214 void ScheduleExpire();
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
219 void DoExpireIteration();
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,
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();
233 // Returns the HistoryClient, blocking until the bookmarks are loaded. This
234 // may return NULL during testing.
235 HistoryClient* GetHistoryClient();
237 // Initializes periodic expiration work queue by populating it with with tasks
238 // for all known readers.
239 void InitWorkQueue();
241 // Returns the reader for all visits. This method is only used by the unit
243 const ExpiringVisitsReader* GetAllVisitsReader();
245 // Returns the reader for AUTO_SUBFRAME visits. This method is only used by
247 const ExpiringVisitsReader* GetAutoSubframeVisitsReader();
249 // Non-owning pointer to the notification delegate (guaranteed non-NULL).
250 BroadcastNotificationDelegate* delegate_;
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.
256 // The threshold for "old" history where we will automatically delete it.
257 base::TimeDelta expiration_threshold_;
259 // List of all distinct types of readers. This list is used to populate the
261 ExpiringVisitsReaders readers_;
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
266 std::queue<const ExpiringVisitsReader*> work_queue_;
268 // Readers for various types of visits.
269 // TODO(dglazkov): If you are adding another one, please consider reorganizing
271 scoped_ptr<ExpiringVisitsReader> all_visits_reader_;
272 scoped_ptr<ExpiringVisitsReader> auto_subframe_visits_reader_;
274 // The HistoryClient; may be NULL.
276 // Use GetHistoryClient to access this, which makes sure the bookmarks are
277 // loaded before returning.
278 HistoryClient* history_client_;
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_;
284 DISALLOW_COPY_AND_ASSIGN(ExpireHistoryBackend);
287 } // namespace history
289 #endif // CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_