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