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_FAVICON_FAVICON_SERVICE_H_
6#define CHROME_BROWSER_FAVICON_FAVICON_SERVICE_H_
7
8#include <vector>
9
10#include "base/callback.h"
11#include "base/containers/hash_tables.h"
12#include "base/memory/ref_counted.h"
13#include "base/task/cancelable_task_tracker.h"
14#include "components/favicon_base/favicon_callback.h"
15#include "components/favicon_base/favicon_types.h"
16#include "components/keyed_service/core/keyed_service.h"
17
18class FaviconClient;
19class GURL;
20class HistoryService;
21struct ImportedFaviconUsage;
22class Profile;
23
24// The favicon service provides methods to access favicons. It calls the history
25// backend behind the scenes. The callbacks are run asynchronously, even in the
26// case of an error.
27class FaviconService : public KeyedService {
28 public:
29  // TODO(jif): Remove usage of Profile. http://crbug.com/378208.
30  // The FaviconClient must outlive the constructed FaviconService.
31  FaviconService(Profile* profile, FaviconClient* favicon_client);
32
33  virtual ~FaviconService();
34
35  // We usually pass parameters with pointer to avoid copy. This function is a
36  // helper to run FaviconResultsCallback with pointer parameters.
37  static void FaviconResultsCallbackRunner(
38      const favicon_base::FaviconResultsCallback& callback,
39      const std::vector<favicon_base::FaviconRawBitmapResult>* results);
40
41  //////////////////////////////////////////////////////////////////////////////
42  // Methods to request favicon bitmaps from the history backend for |icon_url|.
43  // |icon_url| is the URL of the icon itself.
44  // (e.g. <http://www.google.com/favicon.ico>)
45
46  // Requests the favicon at |icon_url| of type favicon_base::FAVICON and of
47  // size gfx::kFaviconSize. The returned gfx::Image is populated with
48  // representations for all of the scale factors supported by the platform
49  // (e.g. MacOS). If data is unavailable for some or all of the scale factors,
50  // the bitmaps with the best matching sizes are resized.
51  base::CancelableTaskTracker::TaskId GetFaviconImage(
52      const GURL& icon_url,
53      const favicon_base::FaviconImageCallback& callback,
54      base::CancelableTaskTracker* tracker);
55
56  // Requests the favicon at |icon_url| of |icon_type| of size
57  // |desired_size_in_pixel|. If there is no favicon of size
58  // |desired_size_in_pixel|, the favicon bitmap which best matches
59  // |desired_size_in_pixel| is resized. If |desired_size_in_pixel| is 0,
60  // the largest favicon bitmap is returned.
61  base::CancelableTaskTracker::TaskId GetRawFavicon(
62      const GURL& icon_url,
63      favicon_base::IconType icon_type,
64      int desired_size_in_pixel,
65      const favicon_base::FaviconRawBitmapCallback& callback,
66      base::CancelableTaskTracker* tracker);
67
68  // The first argument for |callback| is the set of bitmaps for the passed in
69  // URL and icon types whose pixel sizes best match the passed in
70  // |desired_size_in_dip| at the resource scale factors supported by the
71  // current platform (eg MacOS) in addition to 1x. The vector has at most one
72  // result for each of the resource scale factors. There are less entries if a
73  // single/ result is the best bitmap to use for several resource scale
74  // factors.
75  base::CancelableTaskTracker::TaskId GetFavicon(
76      const GURL& icon_url,
77      favicon_base::IconType icon_type,
78      int desired_size_in_dip,
79      const favicon_base::FaviconResultsCallback& callback,
80      base::CancelableTaskTracker* tracker);
81
82  //////////////////////////////////////////////////////////////////////////////
83  // Methods to request favicon bitmaps from the history backend for |page_url|.
84  // |page_url| is the web page the favicon is associated with.
85  // (e.g. <http://www.google.com>)
86
87  // Requests the favicon for the page at |page_url| of type
88  // favicon_base::FAVICON and of size gfx::kFaviconSize. The returned
89  // gfx::Image is populated with representations for all of the scale factors
90  // supported by the platform (e.g. MacOS). If data is unavailable for some or
91  // all of the scale factors, the bitmaps with the best matching sizes are
92  // resized.
93  base::CancelableTaskTracker::TaskId GetFaviconImageForPageURL(
94      const GURL& page_url,
95      const favicon_base::FaviconImageCallback& callback,
96      base::CancelableTaskTracker* tracker);
97
98  // Requests the favicon for the page at |page_url| with one of |icon_types|
99  // and with |desired_size_in_pixel|. |icon_types| can be any combination of
100  // IconTypes. If favicon bitmaps for several IconTypes are available, the
101  // favicon bitmap is chosen in the priority of TOUCH_PRECOMPOSED_ICON,
102  // TOUCH_ICON and FAVICON. If there is no favicon bitmap of size
103  // |desired_size_in_pixel|, the favicon bitmap which best matches
104  // |desired_size_in_pixel| is resized. If |desired_size_in_pixel| is 0,
105  // the largest favicon bitmap is returned. Results with a higher priority
106  // IconType are preferred over an exact match of the favicon bitmap size.
107  base::CancelableTaskTracker::TaskId GetRawFaviconForPageURL(
108      const GURL& page_url,
109      int icon_types,
110      int desired_size_in_pixel,
111      const favicon_base::FaviconRawBitmapCallback& callback,
112      base::CancelableTaskTracker* tracker);
113
114  // See HistoryService::GetLargestFaviconForPageURL().
115  base::CancelableTaskTracker::TaskId GetLargestRawFaviconForPageURL(
116      const GURL& page_url,
117      const std::vector<int>& icon_types,
118      int minimum_size_in_pixels,
119      const favicon_base::FaviconRawBitmapCallback& callback,
120      base::CancelableTaskTracker* tracker);
121
122  base::CancelableTaskTracker::TaskId GetFaviconForPageURL(
123      const GURL& page_url,
124      int icon_types,
125      int desired_size_in_dip,
126      const favicon_base::FaviconResultsCallback& callback,
127      base::CancelableTaskTracker* tracker);
128
129  // Set the favicon mappings to |page_url| for |icon_types| in the history
130  // database.
131  // Sample |icon_urls|:
132  //  { ICON_URL1 -> TOUCH_ICON, known to the database,
133  //    ICON_URL2 -> TOUCH_ICON, not known to the database,
134  //    ICON_URL3 -> TOUCH_PRECOMPOSED_ICON, known to the database }
135  // The new mappings are computed from |icon_urls| with these rules:
136  // 1) Any urls in |icon_urls| which are not already known to the database are
137  //    rejected.
138  //    Sample new mappings to |page_url|: { ICON_URL1, ICON_URL3 }
139  // 2) If |icon_types| has multiple types, the mappings are only set for the
140  //    largest icon type.
141  //    Sample new mappings to |page_url|: { ICON_URL3 }
142  // |icon_types| can only have multiple IconTypes if
143  // |icon_types| == TOUCH_ICON | TOUCH_PRECOMPOSED_ICON.
144  // The favicon bitmaps which most closely match |desired_size_in_dip|
145  // at the reosurce scale factors supported by the current platform (eg MacOS)
146  // in addition to 1x from the favicons which were just mapped to |page_url|
147  // are returned. If |desired_size_in_dip| is 0, the largest favicon bitmap is
148  // returned.
149  base::CancelableTaskTracker::TaskId UpdateFaviconMappingsAndFetch(
150      const GURL& page_url,
151      const std::vector<GURL>& icon_urls,
152      int icon_types,
153      int desired_size_in_dip,
154      const favicon_base::FaviconResultsCallback& callback,
155      base::CancelableTaskTracker* tracker);
156
157  // Used to request a bitmap for the favicon with |favicon_id| which is not
158  // resized from the size it is stored at in the database. If there are
159  // multiple favicon bitmaps for |favicon_id|, the largest favicon bitmap is
160  // returned.
161  base::CancelableTaskTracker::TaskId GetLargestRawFaviconForID(
162      favicon_base::FaviconID favicon_id,
163      const favicon_base::FaviconRawBitmapCallback& callback,
164      base::CancelableTaskTracker* tracker);
165
166  // Marks all types of favicon for the page as being out of date.
167  void SetFaviconOutOfDateForPage(const GURL& page_url);
168
169  // Clones all icons from an existing page. This associates the icons from
170  // |old_page_url| with |new_page_url|, provided |new_page_url| has no
171  // recorded associations to any other icons.
172  // Needed if you want to declare favicons (tentatively) in advance, before a
173  // page is ever visited.
174  void CloneFavicon(const GURL& old_page_url, const GURL& new_page_url);
175
176  // Allows the importer to set many favicons for many pages at once. The pages
177  // must exist, any favicon sets for unknown pages will be discarded. Existing
178  // favicons will not be overwritten.
179  void SetImportedFavicons(
180      const std::vector<ImportedFaviconUsage>& favicon_usage);
181
182  // Set the favicon for |page_url| for |icon_type| in the thumbnail database.
183  // Unlike SetFavicons(), this method will not delete preexisting bitmap data
184  // which is associated to |page_url| if at all possible. Use this method if
185  // the favicon bitmaps for any of ui::GetSupportedScaleFactors() are not
186  // known.
187  void MergeFavicon(const GURL& page_url,
188                    const GURL& icon_url,
189                    favicon_base::IconType icon_type,
190                    scoped_refptr<base::RefCountedMemory> bitmap_data,
191                    const gfx::Size& pixel_size);
192
193  // Set the favicon for |page_url| for |icon_type| in the thumbnail database.
194  // |icon_url| is the single favicon to map to |page_url|. Mappings from
195  // |page_url| to favicons at different icon URLs will be deleted.
196  // A favicon bitmap is added for each image rep in |image|. Any preexisting
197  // bitmap data for |icon_url| is deleted. It is important that |image|
198  // contains image reps for all of ui::GetSupportedScaleFactors(). Use
199  // MergeFavicon() if it does not.
200  // TODO(pkotwicz): Save unresized favicon bitmaps to the database.
201  // TODO(pkotwicz): Support adding favicons for multiple icon URLs to the
202  // thumbnail database.
203  void SetFavicons(const GURL& page_url,
204                   const GURL& icon_url,
205                   favicon_base::IconType icon_type,
206                   const gfx::Image& image);
207
208  // Avoid repeated requests to download missing favicon.
209  void UnableToDownloadFavicon(const GURL& icon_url);
210  bool WasUnableToDownloadFavicon(const GURL& icon_url) const;
211  void ClearUnableToDownloadFavicons();
212
213 private:
214  typedef uint32 MissingFaviconURLHash;
215  base::hash_set<MissingFaviconURLHash> missing_favicon_urls_;
216  HistoryService* history_service_;
217  Profile* profile_;
218  FaviconClient* favicon_client_;
219
220  // Helper function for GetFaviconImageForPageURL(), GetRawFaviconForPageURL()
221  // and GetFaviconForPageURL().
222  base::CancelableTaskTracker::TaskId GetFaviconForPageURLImpl(
223      const GURL& page_url,
224      int icon_types,
225      const std::vector<int>& desired_sizes_in_pixel,
226      const favicon_base::FaviconResultsCallback& callback,
227      base::CancelableTaskTracker* tracker);
228
229  // Intermediate callback for GetFaviconImage() and GetFaviconImageForPageURL()
230  // so that history service can deal solely with FaviconResultsCallback.
231  // Builds favicon_base::FaviconImageResult from |favicon_bitmap_results| and
232  // runs |callback|.
233  void RunFaviconImageCallbackWithBitmapResults(
234      const favicon_base::FaviconImageCallback& callback,
235      int desired_size_in_dip,
236      const std::vector<favicon_base::FaviconRawBitmapResult>&
237          favicon_bitmap_results);
238
239  // Intermediate callback for GetRawFavicon() and GetRawFaviconForPageURL()
240  // so that history service can deal solely with FaviconResultsCallback.
241  // Resizes favicon_base::FaviconRawBitmapResult if necessary and runs
242  // |callback|.
243  void RunFaviconRawBitmapCallbackWithBitmapResults(
244      const favicon_base::FaviconRawBitmapCallback& callback,
245      int desired_size_in_pixel,
246      const std::vector<favicon_base::FaviconRawBitmapResult>&
247          favicon_bitmap_results);
248
249  DISALLOW_COPY_AND_ASSIGN(FaviconService);
250};
251
252#endif  // CHROME_BROWSER_FAVICON_FAVICON_SERVICE_H_
253