summaryrefslogtreecommitdiffstats
path: root/components/favicon/core/favicon_handler.h
blob: 4ca783018154e33c770ed110ce5303360ae2d4e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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_HANDLER_H_
#define COMPONENTS_FAVICON_CORE_FAVICON_HANDLER_H_

#include <map>
#include <vector>

#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "base/task/cancelable_task_tracker.h"
#include "components/favicon/core/favicon_url.h"
#include "components/favicon_base/favicon_callback.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/image/image.h"
#include "url/gurl.h"

class SkBitmap;

namespace base {
class RefCountedMemory;
}

namespace favicon {

class FaviconDriver;
class FaviconService;
class TestFaviconHandler;

// FaviconHandler works with FaviconDriver to fetch the specific type of
// favicon.
//
// FetchFavicon requests the favicon from the favicon service which in turn
// requests the favicon from the history database. At this point
// we only know the URL of the page, and not necessarily the url of the
// favicon. To ensure we handle reloading stale favicons as well as
// reloading a favicon on page reload we always request the favicon from
// history regardless of whether the active favicon is valid.
//
// After the navigation two types of events are delivered (which is
// first depends upon who is faster): notification from the history
// db on our request for the favicon
// (OnFaviconDataForInitialURLFromFaviconService), or a message from the
// renderer giving us the URL of the favicon for the page (SetFaviconURL).
// . If the history db has a valid up to date favicon for the page, we update
//   the current page and use the favicon.
// . When we receive the favicon url if it matches that of the current page
//   and the current page's favicon is set, we do nothing (everything is
//   ok).
// . On the other hand if the database does not know the favicon for url, or
//   the favicon is out date, or the URL from the renderer does not match that
//   of the current page we proceed to DownloadFaviconOrAskHistory. Before we
//   invoke DownloadFaviconOrAskHistory we wait until we've received both
//   the favicon url and the callback from history. We wait to ensure we
//   truly know both the favicon url and the state of the database.
//
// DownloadFaviconOrAskHistory does the following:
// . If we have a valid favicon, but it is expired we ask the renderer to
//   download the favicon.
// . Otherwise we ask the history database to update the mapping from
//   page url to favicon url and call us back with the favicon. Remember, it is
//   possible for the db to already have the favicon, just not the mapping
//   between page to favicon url. The callback for this is OnFaviconData.
//
// OnFaviconData either updates the favicon of the current page (if the
// db knew about the favicon), or requests the renderer to download the
// favicon.
//
// When the renderer downloads favicons, it considers the entire list of
// favicon candidates, if |download_largest_favicon_| is true, the largest
// favicon will be used, otherwise the one that best matches the preferred size
// is chosen (or the first one if there is no preferred  size). Once the
// matching favicon has been determined, SetFavicon is called which updates
// the page's favicon and notifies the database to save the favicon.

class FaviconHandler {
 public:
  enum Type { FAVICON, TOUCH, LARGE };

  FaviconHandler(FaviconService* service,
                 FaviconDriver* driver,
                 Type handler_type,
                 bool download_largest_icon);
  virtual ~FaviconHandler();

  // Returns the bit mask of favicon_base::IconType based on the handler's type.
  static int GetIconTypesFromHandlerType(Type icon_type);

  // Initiates loading the favicon for the specified url.
  void FetchFavicon(const GURL& url);

  // Message Handler.  Must be public, because also called from
  // PrerenderContents. Collects the |image_urls| list.
  void OnUpdateFaviconURL(const GURL& page_url,
                          const std::vector<favicon::FaviconURL>& candidates);

  // Called when the history request for favicon data mapped to |url_| has
  // completed and the renderer has told us the icon URLs used by |url_|
  void OnGotInitialHistoryDataAndIconURLCandidates();

  // Message handler for ImageHostMsg_DidDownloadImage. Called when the image
  // at |image_url| has been downloaded.
  // |bitmaps| is a list of all the frames of the image at |image_url|.
  // |original_bitmap_sizes| are the sizes of |bitmaps| before they were resized
  // to the maximum bitmap size passed to DownloadFavicon().
  void OnDidDownloadFavicon(
      int id,
      const GURL& image_url,
      const std::vector<SkBitmap>& bitmaps,
      const std::vector<gfx::Size>& original_bitmap_sizes);

  // For testing.
  const std::vector<favicon::FaviconURL>& image_urls() const {
    return image_urls_;
  }

  // Returns whether the handler is waiting for a download to complete or for
  // data from the FaviconService. Reserved for testing.
  bool HasPendingTasksForTest();

 protected:
  // These virtual methods make FaviconHandler testable and are overridden by
  // TestFaviconHandler.

  // Asks the render to download favicon, returns the request id.
  virtual int DownloadFavicon(const GURL& image_url, int max_bitmap_size);

  // Ask the favicon from history
  virtual void UpdateFaviconMappingAndFetch(
      const GURL& page_url,
      const GURL& icon_url,
      favicon_base::IconType icon_type,
      const favicon_base::FaviconResultsCallback& callback,
      base::CancelableTaskTracker* tracker);

  virtual void GetFaviconFromFaviconService(
      const GURL& icon_url,
      favicon_base::IconType icon_type,
      const favicon_base::FaviconResultsCallback& callback,
      base::CancelableTaskTracker* tracker);

  virtual void GetFaviconForURLFromFaviconService(
      const GURL& page_url,
      int icon_types,
      const favicon_base::FaviconResultsCallback& callback,
      base::CancelableTaskTracker* tracker);

  virtual void SetHistoryFavicons(const GURL& page_url,
                                  const GURL& icon_url,
                                  favicon_base::IconType icon_type,
                                  const gfx::Image& image);

  // Returns true if the favicon should be saved.
  virtual bool ShouldSaveFavicon();

 private:
  // For testing:
  friend class TestFaviconHandler;

  // Represents an in progress download of an image from the renderer.
  struct DownloadRequest {
    DownloadRequest();
    ~DownloadRequest();

    DownloadRequest(const GURL& image_url, favicon_base::IconType icon_type);

    GURL image_url;
    favicon_base::IconType icon_type;
  };

  // Used to track a candidate for the favicon.
  struct FaviconCandidate {
    FaviconCandidate();
    ~FaviconCandidate();

    FaviconCandidate(const GURL& image_url,
                     const gfx::Image& image,
                     float score,
                     favicon_base::IconType icon_type);

    GURL image_url;
    gfx::Image image;
    float score;
    favicon_base::IconType icon_type;
  };

  // Get the maximal icon size in pixels for a icon of type |icon_type| for the
  // current platform.
  static int GetMaximalIconSize(favicon_base::IconType icon_type);

  // See description above class for details.
  void OnFaviconDataForInitialURLFromFaviconService(const std::vector<
      favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results);

  // If the favicon currently mapped to |url_| has expired, downloads the
  // current candidate favicon from the renderer. Otherwise requests data for
  // the current favicon from history. If data is requested from history,
  // OnFaviconData() is called with the history data once it has been retrieved.
  void DownloadCurrentCandidateOrAskFaviconService();

  // See description above class for details.
  void OnFaviconData(const std::vector<favicon_base::FaviconRawBitmapResult>&
                         favicon_bitmap_results);

  // Schedules a download for the specified entry. This adds the request to
  // download_requests_.
  void ScheduleDownload(const GURL& image_url,
                        favicon_base::IconType icon_type);

  // Updates |favicon_candidate_| and returns true if it is an exact match.
  bool UpdateFaviconCandidate(const GURL& image_url,
                              const gfx::Image& image,
                              float score,
                              favicon_base::IconType icon_type);

  // Sets the image data for the favicon.
  void SetFavicon(const GURL& icon_url,
                  const gfx::Image& image,
                  favicon_base::IconType icon_type);

  // Notifies |driver_| favicon available. See
  // FaviconDriver::NotifyFaviconAvailable() for |is_active_favicon| in detail.
  void NotifyFaviconAvailable(
      const std::vector<favicon_base::FaviconRawBitmapResult>&
          favicon_bitmap_results);
  void NotifyFaviconAvailable(const GURL& icon_url,
                              const gfx::Image& image);

  // Return the current candidate if any.
  favicon::FaviconURL* current_candidate() {
    return current_candidate_index_ < image_urls_.size()
               ? &image_urls_[current_candidate_index_]
               : nullptr;
  }

  // Returns the preferred size of the image. 0 means no preference (any size
  // will do).
  int preferred_icon_size() const {
    if (download_largest_icon_)
      return 0;
    return handler_type_ == FAVICON ? gfx::kFaviconSize : 0;
  }

  // Used for FaviconService requests.
  base::CancelableTaskTracker cancelable_task_tracker_;

  // URL of the page we're requesting the favicon for.
  GURL url_;

  // Whether we got data back for the initial request to the FaviconService.
  bool got_favicon_from_history_;

  // Whether the favicon is out of date or the favicon data in
  // |history_results_| is known to be incomplete. If true, it means history
  // knows about the favicon, but we need to download the favicon because the
  // icon has expired or the data in the database is incomplete.
  bool favicon_expired_or_incomplete_;

  // Requests to the renderer to download favicons.
  typedef std::map<int, DownloadRequest> DownloadRequests;
  DownloadRequests download_requests_;

  // The type of the current handler.
  const Type handler_type_;

  // The combination of the supported icon types.
  const int icon_types_;

  // Whether the largest icon should be downloaded.
  const bool download_largest_icon_;

  // The prioritized favicon candidates from the page back from the renderer.
  std::vector<favicon::FaviconURL> image_urls_;

  // The FaviconRawBitmapResults from history.
  std::vector<favicon_base::FaviconRawBitmapResult> history_results_;

  // The FaviconService which implements favicon operations. May be null during
  // testing.
  FaviconService* service_;

  // This handler's driver, owns this object.
  FaviconDriver* driver_;

  // The index of the favicon URL in |image_urls_| which is currently being
  // requested from history or downloaded.
  size_t current_candidate_index_;

  // Best image we've seen so far.  As images are downloaded from the page they
  // are stored here. When there is an exact match, or no more images are
  // available the favicon service and the current page are updated (assuming
  // the image is for a favicon).
  FaviconCandidate best_favicon_candidate_;

  DISALLOW_COPY_AND_ASSIGN(FaviconHandler);
};

}  // namespace favicon

#endif  // COMPONENTS_FAVICON_CORE_FAVICON_HANDLER_H_