| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_FAVICON_CORE_FAVICON_DATABASE_H_ |
| #define COMPONENTS_FAVICON_CORE_FAVICON_DATABASE_H_ |
| |
| #include <optional> |
| #include <vector> |
| |
| #include "base/feature_list.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/ref_counted.h" |
| #include "components/favicon/core/favicon_types.h" |
| #include "sql/database.h" |
| #include "sql/init_status.h" |
| #include "sql/meta_table.h" |
| #include "sql/statement.h" |
| |
| namespace base { |
| class FilePath; |
| class RefCountedMemory; |
| class Time; |
| } // namespace base |
| |
| namespace url { |
| class Origin; |
| } // namespace url |
| |
| namespace favicon { |
| |
| // The minimum number of days after which last_requested field gets updated. |
| // All earlier updates are ignored. |
| static const int kFaviconUpdateLastRequestedAfterDays = 10; |
| |
| // This database interface is owned by the history backend and runs on the |
| // history thread. |
| class FaviconDatabase { |
| public: |
| FaviconDatabase(); |
| ~FaviconDatabase(); |
| |
| // Must be called after creation but before any other methods are called. |
| // When not INIT_OK, no other functions should be called. |
| sql::InitStatus Init(const base::FilePath& db_name); |
| |
| // Computes and records various metrics for the database. Should only be |
| // called once and only upon successful Init. |
| void ComputeDatabaseMetrics(); |
| |
| // Transactions on the database. |
| void BeginTransaction(); |
| void CommitTransaction(); |
| int transaction_nesting() const { return db_.transaction_nesting(); } |
| void RollbackTransaction(); |
| |
| // Vacuums the database. This will cause sqlite to defragment and collect |
| // unused space in the file. It can be VERY SLOW. |
| void Vacuum(); |
| |
| // Release all non-essential memory associated with this database connection. |
| void TrimMemory(); |
| |
| // Get all on-demand favicon bitmaps that have been last requested prior to |
| // `threshold`. |
| std::map<favicon_base::FaviconID, IconMappingsForExpiry> |
| GetOldOnDemandFavicons(base::Time threshold); |
| |
| // Favicon Bitmaps ----------------------------------------------------------- |
| |
| // Returns true if there are favicon bitmaps for `icon_id`. If |
| // `bitmap_id_sizes` is non NULL, sets it to a list of the favicon bitmap ids |
| // and their associated pixel sizes for the favicon with `icon_id`. |
| // The list contains results for the bitmaps which are cached in the |
| // favicon_bitmaps table. The pixel sizes are a subset of the sizes in the |
| // 'sizes' field of the favicons table for `icon_id`. |
| bool GetFaviconBitmapIDSizes( |
| favicon_base::FaviconID icon_id, |
| std::vector<FaviconBitmapIDSize>* bitmap_id_sizes); |
| |
| // Returns true if there are any matched bitmaps for the given `icon_id`. All |
| // matched results are returned if `favicon_bitmaps` is not NULL. |
| bool GetFaviconBitmaps(favicon_base::FaviconID icon_id, |
| std::vector<FaviconBitmap>* favicon_bitmaps); |
| |
| // Gets the last updated time, bitmap data, and pixel size of the favicon |
| // bitmap at `bitmap_id`. Returns true if successful. |
| bool GetFaviconBitmap(FaviconBitmapID bitmap_id, |
| base::Time* last_updated, |
| base::Time* last_requested, |
| scoped_refptr<base::RefCountedMemory>* png_icon_data, |
| gfx::Size* pixel_size); |
| |
| // Adds a bitmap component of `type` at `pixel_size` for the favicon with |
| // `icon_id`. Only favicons representing a .ico file should have multiple |
| // favicon bitmaps per favicon. |
| // `icon_data` is the png encoded data. |
| // The `type` indicates how the lifetime of this icon should be managed. |
| // The `time` is used for lifetime management of the bitmap (should be Now()). |
| // `pixel_size` is the pixel dimensions of `icon_data`. |
| // Returns the id of the added bitmap or 0 if unsuccessful. |
| FaviconBitmapID AddFaviconBitmap( |
| favicon_base::FaviconID icon_id, |
| scoped_refptr<base::RefCountedMemory> icon_data, |
| FaviconBitmapType type, |
| base::Time time, |
| const gfx::Size& pixel_size); |
| |
| // Sets the bitmap data and the last updated time for the favicon bitmap at |
| // `bitmap_id`. Should not be called for bitmaps of type ON_DEMAND as they |
| // should never get updated (the call silently changes the type to ON_VISIT). |
| // Returns true if successful. |
| bool SetFaviconBitmap(FaviconBitmapID bitmap_id, |
| scoped_refptr<base::RefCountedMemory> bitmap_data, |
| base::Time time); |
| |
| // Sets the last_updated time for the favicon bitmap at `bitmap_id`. Should |
| // not be called for bitmaps of type ON_DEMAND as last_updated time is only |
| // tracked for ON_VISIT bitmaps (the call silently changes the type to |
| // ON_VISIT). Returns true if successful. |
| bool SetFaviconBitmapLastUpdateTime(FaviconBitmapID bitmap_id, |
| base::Time time); |
| |
| // Deletes the favicon bitmap with `bitmap_id`. |
| // Returns true if successful. |
| bool DeleteFaviconBitmap(FaviconBitmapID bitmap_id); |
| |
| // Favicons ------------------------------------------------------------------ |
| |
| // Sets the the favicon as out of date. This will set `last_updated` for all |
| // of the bitmaps for `icon_id` to be out of date. |
| bool SetFaviconOutOfDate(favicon_base::FaviconID icon_id); |
| |
| // Mark all favicons as out of date that have been modified at or after |
| // `begin` and before `end`. This will set `last_updated` for all matching |
| // bitmaps to be out of date. |
| bool SetFaviconsOutOfDateBetween(base::Time begin, base::Time end); |
| |
| // Retrieves the newest `last_updated` time across all bitmaps for `icon_id`. |
| // Returns true if successful and if there is at least one bitmap. |
| bool GetFaviconLastUpdatedTime(favicon_base::FaviconID icon_id, |
| base::Time* last_updated); |
| |
| // Mark all bitmaps of type ON_DEMAND at `icon_url` as requested at `time`. |
| // This postpones their automatic eviction from the database. Not all calls |
| // end up in a write into the DB: |
| // - it is no-op if the bitmaps are not of type ON_DEMAND; |
| // - the updates of the "last requested time" have limited frequency for each |
| // particular bitmap (e.g. once per week). This limits the overhead of |
| // cache management for on-demand favicons. |
| // Returns true if successful. |
| bool TouchOnDemandFavicon(const GURL& icon_url, base::Time time); |
| |
| // Returns the id of the entry in the favicon database with the specified |
| // `icon_url` and `icon_type` that has an existing mapping to `page_origin` |
| // (and 0 if no entry exists). See crbug.com/1300214 for more context. |
| favicon_base::FaviconID GetFaviconIDForFaviconURL( |
| const GURL& icon_url, |
| favicon_base::IconType icon_type, |
| const url::Origin& page_origin); |
| |
| // Returns the id of the entry in the favicon database with the specified |
| // `icon_url` and `icon_type` (and 0 if no entry exists). This function does |
| // not respect cross-origin partitioning and returns an entry from the cache |
| // without verifying it was stored for the origin requesting it. This can leak |
| // navigation history, see crbug.com/1300214 for more context. |
| favicon_base::FaviconID GetFaviconIDForFaviconURL( |
| const GURL& icon_url, |
| favicon_base::IconType icon_type); |
| |
| // Gets the icon_url, icon_type and sizes for the specified `icon_id`. |
| bool GetFaviconHeader(favicon_base::FaviconID icon_id, |
| GURL* icon_url, |
| favicon_base::IconType* icon_type); |
| |
| // Adds favicon with `icon_url`, `icon_type` and `favicon_sizes` to the |
| // favicon db, returning its id. |
| favicon_base::FaviconID AddFavicon(const GURL& icon_url, |
| favicon_base::IconType icon_type); |
| |
| // Adds a favicon with a single bitmap. This call is equivalent to calling |
| // AddFavicon and AddFaviconBitmap of type `type`. |
| favicon_base::FaviconID AddFavicon( |
| const GURL& icon_url, |
| favicon_base::IconType icon_type, |
| scoped_refptr<base::RefCountedMemory> icon_data, |
| FaviconBitmapType type, |
| base::Time time, |
| const gfx::Size& pixel_size); |
| |
| // Delete the favicon with the provided id. Returns false on failure |
| bool DeleteFavicon(favicon_base::FaviconID id); |
| |
| // Icon Mapping -------------------------------------------------------------- |
| // |
| // Returns true if there is a matched icon mapping for the given page and |
| // icon type. |
| // The matched icon mapping is returned in the icon_mapping parameter if it is |
| // not NULL. |
| |
| // Returns true if there are icon mappings for the given page and icon types. |
| // The matched icon mappings are returned in the `mapping_data` parameter if |
| // it is not NULL. |
| bool GetIconMappingsForPageURL( |
| const GURL& page_url, |
| const favicon_base::IconTypeSet& required_icon_types, |
| std::vector<IconMapping>* mapping_data); |
| |
| // Returns true if there is any matched icon mapping for the given page. |
| // All matched icon mappings are returned in descent order of IconType if |
| // mapping_data is not NULL. |
| bool GetIconMappingsForPageURL(const GURL& page_url, |
| std::vector<IconMapping>* mapping_data); |
| |
| // Given `url`, returns the `page_url` page mapped to an icon with |
| // `required_icon_types`, where `page_url` has host = url.host(). The search |
| // prioritizes `PageUrlType::kRegular` over `PageUrlType::kRedirect` on the |
| // assumption that `url` is not a cross-host redirect. This enables icons |
| // to be retrieved when a full URL is not available. For example, |
| // `url` = http://www.google.com would match |
| // `page_url` = https://www.google.com/search. |
| // The returned optional will be empty if no such `page_url` exists. |
| std::optional<GURL> FindBestPageURLForHost( |
| const GURL& url, |
| const favicon_base::IconTypeSet& required_icon_types); |
| |
| // Adds a mapping between the given `page_url` and `icon_id`. A |
| // `page_url_type` must also be provided. It is not possible to store multiple |
| // entries for a (`page_url`, `icon_id`) pair with different `page_url_type`s. |
| // Returns the new mapping id if the adding succeeds, otherwise 0 is returned. |
| IconMappingID AddIconMapping(const GURL& page_url, |
| favicon_base::FaviconID icon_id, |
| PageUrlType page_url_type); |
| |
| // Deletes the icon mapping entries for the given page url. |
| // Returns true if the deletion succeeded. |
| bool DeleteIconMappings(const GURL& page_url); |
| |
| // Deletes the icon mapping entries for the given favicon ID. |
| // Returns true if the deletion succeeded. |
| bool DeleteIconMappingsForFaviconId(favicon_base::FaviconID id); |
| |
| // Deletes the icon mapping with `mapping_id`. |
| // Returns true if the deletion succeeded. |
| bool DeleteIconMapping(IconMappingID mapping_id); |
| |
| // Checks whether a favicon is used by any URLs in the database. |
| bool HasMappingFor(favicon_base::FaviconID id); |
| |
| // Returns the ids of favicons which were last updated before `time`. This |
| // returns at most `max_count` ids. |
| std::vector<favicon_base::FaviconID> GetFaviconsLastUpdatedBefore( |
| base::Time time, |
| int max_count); |
| |
| // The class to enumerate icon mappings. Use InitIconMappingEnumerator to |
| // initialize. |
| class IconMappingEnumerator { |
| public: |
| IconMappingEnumerator(); |
| |
| IconMappingEnumerator(const IconMappingEnumerator&) = delete; |
| IconMappingEnumerator& operator=(const IconMappingEnumerator&) = delete; |
| |
| ~IconMappingEnumerator(); |
| |
| // Get the next icon mapping, return false if no more are available. |
| bool GetNextIconMapping(IconMapping* icon_mapping); |
| |
| private: |
| friend class FaviconDatabase; |
| |
| // Used to query database and return the data for filling IconMapping in |
| // each call of GetNextIconMapping(). |
| sql::Statement statement_; |
| }; |
| |
| // Return all icon mappings of the given `icon_type`. |
| bool InitIconMappingEnumerator(favicon_base::IconType type, |
| IconMappingEnumerator* enumerator); |
| |
| // Remove all data except that associated with the passed page urls. |
| // Returns false in case of failure. A nested transaction is used, |
| // so failure causes any outer transaction to be rolled back. |
| bool RetainDataForPageUrls(const std::vector<GURL>& urls_to_keep); |
| |
| private: |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseIconTypeTest, |
| ShouldBeBackwardCompatible); |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseTest, RetainDataForPageUrls); |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseTest, |
| RetainDataForPageUrlsExpiresRetainedFavicons); |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseTest, Version3); |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseTest, Version4); |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseTest, Version5); |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseTest, Version6); |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseTest, Version7); |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseTest, Version8); |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseTest, Version9); |
| FRIEND_TEST_ALL_PREFIXES(FaviconDatabaseTest, WildSchema); |
| |
| // For historical reasons, and for backward compatibility, the icon type |
| // values stored in the DB are powers of two. Conversion functions |
| // exposed publicly for testing. |
| static int ToPersistedIconType(favicon_base::IconType icon_type); |
| static favicon_base::IconType FromPersistedIconType(int icon_type); |
| |
| // `page_url_type` is stored as an int representation of the enum. |
| static int ToPersistedPageUrlType(PageUrlType page_url_type); |
| static PageUrlType FromPersistedPageUrlType(int page_url_type); |
| |
| // Fills `icon_mapping` with data from `statement` for `page_url`. The |
| // format of the data in `statement` is an internal implementation detail. |
| static void FillIconMapping(const GURL& page_url, |
| sql::Statement& statement, |
| IconMapping* icon_mapping); |
| |
| // Open database on a given filename. If the file does not exist, |
| // it is created. |
| // `db` is the database to open. |
| // `db_name` is a path to the database file. |
| sql::InitStatus OpenDatabase(sql::Database* db, |
| const base::FilePath& db_name); |
| |
| // Helper function to implement internals of Init(). This allows |
| // Init() to retry in case of failure, since some failures run |
| // recovery code. |
| sql::InitStatus InitImpl(const base::FilePath& db_name); |
| |
| // Helper function to handle cleanup on upgrade failures. |
| sql::InitStatus CantUpgradeToVersion(int cur_version); |
| |
| // Adds column for `page_url_type` to `icon_mapping` table. |
| bool UpgradeToVersion9(); |
| |
| // Returns true if the `favicons` database is missing a column. |
| bool IsFaviconDBStructureIncorrect(); |
| |
| sql::Database db_; |
| sql::MetaTable meta_table_; |
| }; |
| |
| } // namespace favicon |
| |
| #endif // COMPONENTS_FAVICON_CORE_FAVICON_DATABASE_H_ |