expire_history_backend.h revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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
20class BookmarkService;
21class GURL;
22class NotificationType;
23class TestingProfile;
24
25namespace history {
26
27class ArchivedDatabase;
28class HistoryDatabase;
29struct HistoryDetails;
30class TextDatabaseManager;
31class ThumbnailDatabase;
32
33// Delegate used to broadcast notifications to the main thread.
34class 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:
42  virtual ~BroadcastNotificationDelegate() {}
43};
44
45// Encapsulates visit expiration criteria and type of visits to expire.
46class ExpiringVisitsReader {
47 public:
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
55typedef 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().
63class 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.
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