Home | History | Annotate | Download | only in history
      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