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_THUMBNAIL_DATABASE_H_
      6 #define CHROME_BROWSER_HISTORY_THUMBNAIL_DATABASE_H_
      7 
      8 #include <vector>
      9 
     10 #include "base/gtest_prod_util.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "chrome/browser/history/history_types.h"
     13 #include "sql/connection.h"
     14 #include "sql/init_status.h"
     15 #include "sql/meta_table.h"
     16 #include "sql/statement.h"
     17 
     18 struct ThumbnailScore;
     19 class SkBitmap;
     20 
     21 namespace base {
     22 class FilePath;
     23 class RefCountedMemory;
     24 class Time;
     25 }
     26 
     27 namespace gfx {
     28 class Image;
     29 }
     30 
     31 namespace history {
     32 
     33 class ExpireHistoryBackend;
     34 class HistoryPublisher;
     35 
     36 // This database interface is owned by the history backend and runs on the
     37 // history thread. It is a totally separate component from history partially
     38 // because we may want to move it to its own thread in the future. The
     39 // operations we will do on this database will be slow, but we can tolerate
     40 // higher latency (it's OK for thumbnails to come in slower than the rest
     41 // of the data). Moving this to a separate thread would not block potentially
     42 // higher priority history operations.
     43 class ThumbnailDatabase {
     44  public:
     45   ThumbnailDatabase();
     46   ~ThumbnailDatabase();
     47 
     48   // Must be called after creation but before any other methods are called.
     49   // When not INIT_OK, no other functions should be called.
     50   sql::InitStatus Init(const base::FilePath& db_name,
     51                        const HistoryPublisher* history_publisher,
     52                        URLDatabase* url_database);
     53 
     54   // Open database on a given filename. If the file does not exist,
     55   // it is created.
     56   // |db| is the database to open.
     57   // |db_name| is a path to the database file.
     58   static sql::InitStatus OpenDatabase(sql::Connection* db,
     59                                       const base::FilePath& db_name);
     60 
     61   // Computes and records various metrics for the database. Should only be
     62   // called once and only upon successful Init.
     63   void ComputeDatabaseMetrics();
     64 
     65   // Transactions on the database.
     66   void BeginTransaction();
     67   void CommitTransaction();
     68   int transaction_nesting() const {
     69     return db_.transaction_nesting();
     70   }
     71   void RollbackTransaction();
     72 
     73   // Vacuums the database. This will cause sqlite to defragment and collect
     74   // unused space in the file. It can be VERY SLOW.
     75   void Vacuum();
     76 
     77   // Try to trim the cache memory used by the database.  If |aggressively| is
     78   // true try to trim all unused cache, otherwise trim by half.
     79   void TrimMemory(bool aggressively);
     80 
     81   // Thumbnails ----------------------------------------------------------------
     82 
     83   // Sets the given data to be the thumbnail for the given URL,
     84   // overwriting any previous data. If the SkBitmap contains no pixel
     85   // data, the thumbnail will be deleted.
     86   bool SetPageThumbnail(const GURL& url,
     87                         URLID id,
     88                         const gfx::Image* thumbnail,
     89                         const ThumbnailScore& score,
     90                         base::Time time);
     91 
     92   // Retrieves thumbnail data for the given URL, returning true on success,
     93   // false if there is no such thumbnail or there was some other error.
     94   bool GetPageThumbnail(URLID id, std::vector<unsigned char>* data);
     95 
     96   // Delete the thumbnail with the provided id. Returns false on failure
     97   bool DeleteThumbnail(URLID id);
     98 
     99   // If there is a thumbnail score for the id provided, retrieves the
    100   // current thumbnail score and places it in |score| and returns
    101   // true. Returns false otherwise.
    102   bool ThumbnailScoreForId(URLID id, ThumbnailScore* score);
    103 
    104   // Called by the to delete all old thumbnails and make a clean table.
    105   // Returns true on success.
    106   bool RecreateThumbnailTable();
    107 
    108   // Favicon Bitmaps -----------------------------------------------------------
    109 
    110   // Returns true if there are favicon bitmaps for |icon_id|. If
    111   // |bitmap_id_sizes| is non NULL, sets it to a list of the favicon bitmap ids
    112   // and their associated pixel sizes for the favicon with |icon_id|.
    113   // The list contains results for the bitmaps which are cached in the
    114   // favicon_bitmaps table. The pixel sizes are a subset of the sizes in the
    115   // 'sizes' field of the favicons table for |icon_id|.
    116   bool GetFaviconBitmapIDSizes(
    117       chrome::FaviconID icon_id,
    118       std::vector<FaviconBitmapIDSize>* bitmap_id_sizes);
    119 
    120   // Returns true if there are any matched bitmaps for the given |icon_id|. All
    121   // matched results are returned if |favicon_bitmaps| is not NULL.
    122   bool GetFaviconBitmaps(chrome::FaviconID icon_id,
    123                          std::vector<FaviconBitmap>* favicon_bitmaps);
    124 
    125   // Gets the last updated time, bitmap data, and pixel size of the favicon
    126   // bitmap at |bitmap_id|. Returns true if successful.
    127   bool GetFaviconBitmap(FaviconBitmapID bitmap_id,
    128                         base::Time* last_updated,
    129                         scoped_refptr<base::RefCountedMemory>* png_icon_data,
    130                         gfx::Size* pixel_size);
    131 
    132   // Adds a bitmap component at |pixel_size| for the favicon with |icon_id|.
    133   // Only favicons representing a .ico file should have multiple favicon bitmaps
    134   // per favicon.
    135   // |icon_data| is the png encoded data.
    136   // The |time| indicates the access time, and is used to detect when the
    137   // favicon should be refreshed.
    138   // |pixel_size| is the pixel dimensions of |icon_data|.
    139   // Returns the id of the added bitmap or 0 if unsuccessful.
    140   FaviconBitmapID AddFaviconBitmap(
    141       chrome::FaviconID icon_id,
    142       const scoped_refptr<base::RefCountedMemory>& icon_data,
    143       base::Time time,
    144       const gfx::Size& pixel_size);
    145 
    146   // Sets the bitmap data and the last updated time for the favicon bitmap at
    147   // |bitmap_id|.
    148   // Returns true if successful.
    149   bool SetFaviconBitmap(FaviconBitmapID bitmap_id,
    150                         scoped_refptr<base::RefCountedMemory> bitmap_data,
    151                         base::Time time);
    152 
    153   // Sets the last updated time for the favicon bitmap at |bitmap_id|.
    154   // Returns true if successful.
    155   bool SetFaviconBitmapLastUpdateTime(FaviconBitmapID bitmap_id,
    156                                       base::Time time);
    157 
    158   // Deletes the favicon bitmaps for the favicon with with |icon_id|.
    159   // Returns true if successful.
    160   bool DeleteFaviconBitmapsForFavicon(chrome::FaviconID icon_id);
    161 
    162   // Deletes the favicon bitmap with |bitmap_id|.
    163   // Returns true if successful.
    164   bool DeleteFaviconBitmap(FaviconBitmapID bitmap_id);
    165 
    166   // Favicons ------------------------------------------------------------------
    167 
    168   // Sets the the favicon as out of date. This will set |last_updated| for all
    169   // of the bitmaps for |icon_id| to be out of date.
    170   bool SetFaviconOutOfDate(chrome::FaviconID icon_id);
    171 
    172   // Returns the id of the entry in the favicon database with the specified url
    173   // and icon type. If |required_icon_type| contains multiple icon types and
    174   // there are more than one matched icon in database, only one icon will be
    175   // returned in the priority of TOUCH_PRECOMPOSED_ICON, TOUCH_ICON, and
    176   // FAVICON, and the icon type is returned in icon_type parameter if it is not
    177   // NULL.
    178   // Returns 0 if no entry exists for the specified url.
    179   chrome::FaviconID GetFaviconIDForFaviconURL(const GURL& icon_url,
    180                                               int required_icon_type,
    181                                               chrome::IconType* icon_type);
    182 
    183   // Gets the icon_url, icon_type and sizes for the specified |icon_id|.
    184   bool GetFaviconHeader(chrome::FaviconID icon_id,
    185                         GURL* icon_url,
    186                         chrome::IconType* icon_type);
    187 
    188   // Adds favicon with |icon_url|, |icon_type| and |favicon_sizes| to the
    189   // favicon db, returning its id.
    190   chrome::FaviconID AddFavicon(const GURL& icon_url,
    191                                chrome::IconType icon_type);
    192 
    193   // Adds a favicon with a single bitmap. This call is equivalent to calling
    194   // AddFavicon and AddFaviconBitmap.
    195   chrome::FaviconID AddFavicon(
    196       const GURL& icon_url,
    197       chrome::IconType icon_type,
    198       const scoped_refptr<base::RefCountedMemory>& icon_data,
    199       base::Time time,
    200       const gfx::Size& pixel_size);
    201 
    202   // Delete the favicon with the provided id. Returns false on failure
    203   bool DeleteFavicon(chrome::FaviconID id);
    204 
    205   // Icon Mapping --------------------------------------------------------------
    206   //
    207   // Returns true if there is a matched icon mapping for the given page and
    208   // icon type.
    209   // The matched icon mapping is returned in the icon_mapping parameter if it is
    210   // not NULL.
    211 
    212   // Returns true if there are icon mappings for the given page and icon types.
    213   // If |required_icon_types| contains multiple icon types and there is more
    214   // than one matched icon type in the database, icons of only a single type
    215   // will be returned in the priority of TOUCH_PRECOMPOSED_ICON, TOUCH_ICON,
    216   // and FAVICON.
    217   // The matched icon mappings are returned in the |mapping_data| parameter if
    218   // it is not NULL.
    219   bool GetIconMappingsForPageURL(const GURL& page_url,
    220                                  int required_icon_types,
    221                                  std::vector<IconMapping>* mapping_data);
    222 
    223   // Returns true if there is any matched icon mapping for the given page.
    224   // All matched icon mappings are returned in descent order of IconType if
    225   // mapping_data is not NULL.
    226   bool GetIconMappingsForPageURL(const GURL& page_url,
    227                                  std::vector<IconMapping>* mapping_data);
    228 
    229   // Adds a mapping between the given page_url and icon_id.
    230   // Returns the new mapping id if the adding succeeds, otherwise 0 is returned.
    231   IconMappingID AddIconMapping(const GURL& page_url, chrome::FaviconID icon_id);
    232 
    233   // Updates the page and icon mapping for the given mapping_id with the given
    234   // icon_id.
    235   // Returns true if the update succeeded.
    236   bool UpdateIconMapping(IconMappingID mapping_id, chrome::FaviconID icon_id);
    237 
    238   // Deletes the icon mapping entries for the given page url.
    239   // Returns true if the deletion succeeded.
    240   bool DeleteIconMappings(const GURL& page_url);
    241 
    242   // Deletes the icon mapping with |mapping_id|.
    243   // Returns true if the deletion succeeded.
    244   bool DeleteIconMapping(IconMappingID mapping_id);
    245 
    246   // Checks whether a favicon is used by any URLs in the database.
    247   bool HasMappingFor(chrome::FaviconID id);
    248 
    249   // Clones the existing mappings from |old_page_url| if |new_page_url| has no
    250   // mappings. Otherwise, will leave mappings alone.
    251   bool CloneIconMappings(const GURL& old_page_url, const GURL& new_page_url);
    252 
    253   // The class to enumerate icon mappings. Use InitIconMappingEnumerator to
    254   // initialize.
    255   class IconMappingEnumerator {
    256    public:
    257     IconMappingEnumerator();
    258     ~IconMappingEnumerator();
    259 
    260     // Get the next icon mapping, return false if no more are available.
    261     bool GetNextIconMapping(IconMapping* icon_mapping);
    262 
    263    private:
    264     friend class ThumbnailDatabase;
    265 
    266     // Used to query database and return the data for filling IconMapping in
    267     // each call of GetNextIconMapping().
    268     sql::Statement statement_;
    269 
    270     DISALLOW_COPY_AND_ASSIGN(IconMappingEnumerator);
    271   };
    272 
    273   // Return all icon mappings of the given |icon_type|.
    274   bool InitIconMappingEnumerator(chrome::IconType type,
    275                                  IconMappingEnumerator* enumerator);
    276 
    277   // Temporary Tables ---------------------------------------------------------
    278   //
    279   // Creates empty temporary tables for each of the tables in the thumbnail
    280   // database. Favicon data which is not copied into the temporary tables will
    281   // be deleted when CommitTemporaryTables() is called. This is used to delete
    282   // most of the favicons when clearing history.
    283   bool InitTemporaryTables();
    284 
    285   // Replaces the main tables in the thumbnail database with the temporary
    286   // tables created with InitTemporaryTables(). This means that any data not
    287   // copied over will be deleted.
    288   bool CommitTemporaryTables();
    289 
    290   // Copies the given icon mapping from the "main" icon_mapping table to the
    291   // temporary one. This is only valid in between calls to
    292   // InitTemporaryTables() and CommitTemporaryTables().
    293   //
    294   // The ID of the favicon will change when this copy takes place. The new ID
    295   // is returned, or 0 on failure.
    296   IconMappingID AddToTemporaryIconMappingTable(const GURL& page_url,
    297                                                const chrome::FaviconID icon_id);
    298 
    299   // Copies the given favicon and associated favicon bitmaps from the "main"
    300   // favicon and favicon_bitmaps tables to the temporary ones. This is only
    301   // valid in between calls to InitTemporaryTables() and
    302   // CommitTemporaryTables().
    303   //
    304   // The ID of the favicon will change when this copy takes place. The new ID
    305   // is returned, or 0 on failure.
    306   chrome::FaviconID CopyFaviconAndFaviconBitmapsToTemporaryTables(
    307       chrome::FaviconID source);
    308 
    309   // Returns true iff the thumbnails table exists.
    310   // Migrating to TopSites is dropping the thumbnails table.
    311   bool NeedsMigrationToTopSites();
    312 
    313   // Renames the database file and drops the Thumbnails table.
    314   bool RenameAndDropThumbnails(const base::FilePath& old_db_file,
    315                                const base::FilePath& new_db_file);
    316 
    317  private:
    318   friend class ExpireHistoryBackend;
    319   FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest,
    320                            GetFaviconAfterMigrationToTopSites);
    321   FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion4);
    322   FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion5);
    323   FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion6);
    324   FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, UpgradeToVersion7);
    325   FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MigrationIconMapping);
    326 
    327   // Creates the thumbnail table, returning true if the table already exists
    328   // or was successfully created.
    329   bool InitThumbnailTable();
    330 
    331   // Helper function to handle cleanup on upgrade failures.
    332   sql::InitStatus CantUpgradeToVersion(int cur_version);
    333 
    334   // Adds support for the new metadata on web page thumbnails.
    335   bool UpgradeToVersion3();
    336 
    337   // Adds support for the icon_type in favicon table.
    338   bool UpgradeToVersion4();
    339 
    340   // Adds support for sizes in favicon table.
    341   bool UpgradeToVersion5();
    342 
    343   // Adds support for size in favicons table.
    344   bool UpgradeToVersion6();
    345 
    346   // Removes sizes column.
    347   bool UpgradeToVersion7();
    348 
    349   // Migrates the icon mapping data from URL database to Thumbnail database.
    350   // Return whether the migration succeeds.
    351   bool MigrateIconMappingData(URLDatabase* url_db);
    352 
    353   // Creates the favicon table, returning true if the table already exists,
    354   // or was successfully created. |is_temporary| will be false when generating
    355   // the "regular" favicons table. The expirer sets this to true to generate the
    356   // temporary table, which will have a different name but the same schema.
    357   // |db| is the connection to use for initializing the table.
    358   // A different connection is used in RenameAndDropThumbnails, when we
    359   // need to copy the favicons between two database files.
    360   bool InitFaviconsTable(sql::Connection* db, bool is_temporary);
    361 
    362   // Creates the index over the favicon table. This will be called during
    363   // initialization after the table is created. This is a separate function
    364   // because it is used by SwapFaviconTables to create an index over the
    365   // newly-renamed favicons table (formerly the temporary table with no index).
    366   bool InitFaviconsIndex();
    367 
    368   // Creates the favicon_bitmaps table, return true if the table already exists
    369   // or was successfully created.
    370   bool InitFaviconBitmapsTable(sql::Connection* db, bool is_temporary);
    371 
    372   // Creates the index over the favicon_bitmaps table. This will be called
    373   // during initialization after the table is created. This is a separate
    374   // function because it is used by CommitTemporaryTables to create an
    375   // index over the newly-renamed favicon_bitmaps table (formerly the temporary
    376   // table with no index).
    377   bool InitFaviconBitmapsIndex();
    378 
    379   // Creates the icon_map table, return true if the table already exists or was
    380   // successfully created.
    381   bool InitIconMappingTable(sql::Connection* db, bool is_temporary);
    382 
    383   // Creates the index over the icon_mapping table, This will be called during
    384   // initialization after the table is created. This is a separate function
    385   // because it is used by CommitTemporaryIconMappingTable to create an index
    386   // over the newly-renamed icon_mapping table (formerly the temporary table
    387   // with no index).
    388   bool InitIconMappingIndex();
    389 
    390   // Returns true if the |favicons| database is missing a column.
    391   bool IsFaviconDBStructureIncorrect();
    392 
    393   // Adds a mapping between the given page_url and icon_id; The mapping will be
    394   // added to temp_icon_mapping table if is_temporary is true.
    395   // Returns the new mapping id if the adding succeeds, otherwise 0 is returned.
    396   IconMappingID AddIconMapping(const GURL& page_url,
    397                                chrome::FaviconID icon_id,
    398                                bool is_temporary);
    399 
    400   // Returns True if the current database is latest.
    401   bool IsLatestVersion();
    402 
    403   sql::Connection db_;
    404   sql::MetaTable meta_table_;
    405 
    406   // This object is created and managed by the history backend. We maintain an
    407   // opaque pointer to the object for our use.
    408   // This can be NULL if there are no indexers registered to receive indexing
    409   // data from us.
    410   const HistoryPublisher* history_publisher_;
    411 
    412   // True if migration to TopSites has been done and the thumbnails
    413   // table should not be used.
    414   bool use_top_sites_;
    415 };
    416 
    417 }  // namespace history
    418 
    419 #endif  // CHROME_BROWSER_HISTORY_THUMBNAIL_DATABASE_H_
    420