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 "components/history/core/browser/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
18namespace base {
19class FilePath;
20class RefCountedMemory;
21class Time;
22}
23
24namespace history {
25
26class HistoryClient;
27
28// This database interface is owned by the history backend and runs on the
29// history thread. It is a totally separate component from history partially
30// because we may want to move it to its own thread in the future. The
31// operations we will do on this database will be slow, but we can tolerate
32// higher latency (it's OK for thumbnails to come in slower than the rest
33// of the data). Moving this to a separate thread would not block potentially
34// higher priority history operations.
35class ThumbnailDatabase {
36 public:
37  explicit ThumbnailDatabase(HistoryClient* history_client);
38  ~ThumbnailDatabase();
39
40  // Must be called after creation but before any other methods are called.
41  // When not INIT_OK, no other functions should be called.
42  sql::InitStatus Init(const base::FilePath& db_name);
43
44  // Computes and records various metrics for the database. Should only be
45  // called once and only upon successful Init.
46  void ComputeDatabaseMetrics();
47
48  // Transactions on the database.
49  void BeginTransaction();
50  void CommitTransaction();
51  int transaction_nesting() const {
52    return db_.transaction_nesting();
53  }
54  void RollbackTransaction();
55
56  // Vacuums the database. This will cause sqlite to defragment and collect
57  // unused space in the file. It can be VERY SLOW.
58  void Vacuum();
59
60  // Try to trim the cache memory used by the database.  If |aggressively| is
61  // true try to trim all unused cache, otherwise trim by half.
62  void TrimMemory(bool aggressively);
63
64  // Favicon Bitmaps -----------------------------------------------------------
65
66  // Returns true if there are favicon bitmaps for |icon_id|. If
67  // |bitmap_id_sizes| is non NULL, sets it to a list of the favicon bitmap ids
68  // and their associated pixel sizes for the favicon with |icon_id|.
69  // The list contains results for the bitmaps which are cached in the
70  // favicon_bitmaps table. The pixel sizes are a subset of the sizes in the
71  // 'sizes' field of the favicons table for |icon_id|.
72  bool GetFaviconBitmapIDSizes(
73      favicon_base::FaviconID icon_id,
74      std::vector<FaviconBitmapIDSize>* bitmap_id_sizes);
75
76  // Returns true if there are any matched bitmaps for the given |icon_id|. All
77  // matched results are returned if |favicon_bitmaps| is not NULL.
78  bool GetFaviconBitmaps(favicon_base::FaviconID icon_id,
79                         std::vector<FaviconBitmap>* favicon_bitmaps);
80
81  // Gets the last updated time, bitmap data, and pixel size of the favicon
82  // bitmap at |bitmap_id|. Returns true if successful.
83  bool GetFaviconBitmap(FaviconBitmapID bitmap_id,
84                        base::Time* last_updated,
85                        scoped_refptr<base::RefCountedMemory>* png_icon_data,
86                        gfx::Size* pixel_size);
87
88  // Adds a bitmap component at |pixel_size| for the favicon with |icon_id|.
89  // Only favicons representing a .ico file should have multiple favicon bitmaps
90  // per favicon.
91  // |icon_data| is the png encoded data.
92  // The |time| indicates the access time, and is used to detect when the
93  // favicon should be refreshed.
94  // |pixel_size| is the pixel dimensions of |icon_data|.
95  // Returns the id of the added bitmap or 0 if unsuccessful.
96  FaviconBitmapID AddFaviconBitmap(
97      favicon_base::FaviconID icon_id,
98      const scoped_refptr<base::RefCountedMemory>& icon_data,
99      base::Time time,
100      const gfx::Size& pixel_size);
101
102  // Sets the bitmap data and the last updated time for the favicon bitmap at
103  // |bitmap_id|.
104  // Returns true if successful.
105  bool SetFaviconBitmap(FaviconBitmapID bitmap_id,
106                        scoped_refptr<base::RefCountedMemory> bitmap_data,
107                        base::Time time);
108
109  // Sets the last updated time for the favicon bitmap at |bitmap_id|.
110  // Returns true if successful.
111  bool SetFaviconBitmapLastUpdateTime(FaviconBitmapID bitmap_id,
112                                      base::Time time);
113
114  // Deletes the favicon bitmap with |bitmap_id|.
115  // Returns true if successful.
116  bool DeleteFaviconBitmap(FaviconBitmapID bitmap_id);
117
118  // Favicons ------------------------------------------------------------------
119
120  // Sets the the favicon as out of date. This will set |last_updated| for all
121  // of the bitmaps for |icon_id| to be out of date.
122  bool SetFaviconOutOfDate(favicon_base::FaviconID icon_id);
123
124  // Returns the id of the entry in the favicon database with the specified url
125  // and icon type. If |required_icon_type| contains multiple icon types and
126  // there are more than one matched icon in database, only one icon will be
127  // returned in the priority of TOUCH_PRECOMPOSED_ICON, TOUCH_ICON, and
128  // FAVICON, and the icon type is returned in icon_type parameter if it is not
129  // NULL.
130  // Returns 0 if no entry exists for the specified url.
131  favicon_base::FaviconID GetFaviconIDForFaviconURL(
132      const GURL& icon_url,
133      int required_icon_type,
134      favicon_base::IconType* icon_type);
135
136  // Gets the icon_url, icon_type and sizes for the specified |icon_id|.
137  bool GetFaviconHeader(favicon_base::FaviconID icon_id,
138                        GURL* icon_url,
139                        favicon_base::IconType* icon_type);
140
141  // Adds favicon with |icon_url|, |icon_type| and |favicon_sizes| to the
142  // favicon db, returning its id.
143  favicon_base::FaviconID AddFavicon(const GURL& icon_url,
144                                     favicon_base::IconType icon_type);
145
146  // Adds a favicon with a single bitmap. This call is equivalent to calling
147  // AddFavicon and AddFaviconBitmap.
148  favicon_base::FaviconID AddFavicon(
149      const GURL& icon_url,
150      favicon_base::IconType icon_type,
151      const scoped_refptr<base::RefCountedMemory>& icon_data,
152      base::Time time,
153      const gfx::Size& pixel_size);
154
155  // Delete the favicon with the provided id. Returns false on failure
156  bool DeleteFavicon(favicon_base::FaviconID id);
157
158  // Icon Mapping --------------------------------------------------------------
159  //
160  // Returns true if there is a matched icon mapping for the given page and
161  // icon type.
162  // The matched icon mapping is returned in the icon_mapping parameter if it is
163  // not NULL.
164
165  // Returns true if there are icon mappings for the given page and icon types.
166  // If |required_icon_types| contains multiple icon types and there is more
167  // than one matched icon type in the database, icons of only a single type
168  // will be returned in the priority of TOUCH_PRECOMPOSED_ICON, TOUCH_ICON,
169  // and FAVICON.
170  // The matched icon mappings are returned in the |mapping_data| parameter if
171  // it is not NULL.
172  bool GetIconMappingsForPageURL(const GURL& page_url,
173                                 int required_icon_types,
174                                 std::vector<IconMapping>* mapping_data);
175
176  // Returns true if there is any matched icon mapping for the given page.
177  // All matched icon mappings are returned in descent order of IconType if
178  // mapping_data is not NULL.
179  bool GetIconMappingsForPageURL(const GURL& page_url,
180                                 std::vector<IconMapping>* mapping_data);
181
182  // Adds a mapping between the given page_url and icon_id.
183  // Returns the new mapping id if the adding succeeds, otherwise 0 is returned.
184  IconMappingID AddIconMapping(const GURL& page_url,
185                               favicon_base::FaviconID icon_id);
186
187  // Updates the page and icon mapping for the given mapping_id with the given
188  // icon_id.
189  // Returns true if the update succeeded.
190  bool UpdateIconMapping(IconMappingID mapping_id,
191                         favicon_base::FaviconID icon_id);
192
193  // Deletes the icon mapping entries for the given page url.
194  // Returns true if the deletion succeeded.
195  bool DeleteIconMappings(const GURL& page_url);
196
197  // Deletes the icon mapping with |mapping_id|.
198  // Returns true if the deletion succeeded.
199  bool DeleteIconMapping(IconMappingID mapping_id);
200
201  // Checks whether a favicon is used by any URLs in the database.
202  bool HasMappingFor(favicon_base::FaviconID id);
203
204  // Clones the existing mappings from |old_page_url| if |new_page_url| has no
205  // mappings. Otherwise, will leave mappings alone.
206  bool CloneIconMappings(const GURL& old_page_url, const GURL& new_page_url);
207
208  // The class to enumerate icon mappings. Use InitIconMappingEnumerator to
209  // initialize.
210  class IconMappingEnumerator {
211   public:
212    IconMappingEnumerator();
213    ~IconMappingEnumerator();
214
215    // Get the next icon mapping, return false if no more are available.
216    bool GetNextIconMapping(IconMapping* icon_mapping);
217
218   private:
219    friend class ThumbnailDatabase;
220
221    // Used to query database and return the data for filling IconMapping in
222    // each call of GetNextIconMapping().
223    sql::Statement statement_;
224
225    DISALLOW_COPY_AND_ASSIGN(IconMappingEnumerator);
226  };
227
228  // Return all icon mappings of the given |icon_type|.
229  bool InitIconMappingEnumerator(favicon_base::IconType type,
230                                 IconMappingEnumerator* enumerator);
231
232  // Remove all data except that associated with the passed page urls.
233  // Returns false in case of failure.  A nested transaction is used,
234  // so failure causes any outer transaction to be rolled back.
235  bool RetainDataForPageUrls(const std::vector<GURL>& urls_to_keep);
236
237 private:
238  FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, RetainDataForPageUrls);
239  FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version3);
240  FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version4);
241  FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version5);
242  FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version6);
243  FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version7);
244  FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, WildSchema);
245
246  // Open database on a given filename. If the file does not exist,
247  // it is created.
248  // |db| is the database to open.
249  // |db_name| is a path to the database file.
250  sql::InitStatus OpenDatabase(sql::Connection* db,
251                               const base::FilePath& db_name);
252
253  // Helper function to implement internals of Init().  This allows
254  // Init() to retry in case of failure, since some failures run
255  // recovery code.
256  sql::InitStatus InitImpl(const base::FilePath& db_name);
257
258  // Helper function to handle cleanup on upgrade failures.
259  sql::InitStatus CantUpgradeToVersion(int cur_version);
260
261  // Adds support for size in favicons table.
262  bool UpgradeToVersion6();
263
264  // Removes sizes column.
265  bool UpgradeToVersion7();
266
267  // Returns true if the |favicons| database is missing a column.
268  bool IsFaviconDBStructureIncorrect();
269
270  sql::Connection db_;
271  sql::MetaTable meta_table_;
272
273  HistoryClient* history_client_;
274};
275
276}  // namespace history
277
278#endif  // CHROME_BROWSER_HISTORY_THUMBNAIL_DATABASE_H_
279