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.
5 #ifndef CHROME_BROWSER_FAVICON_FAVICON_HANDLER_H_
6 #define CHROME_BROWSER_FAVICON_FAVICON_HANDLER_H_
10 #include "base/basictypes.h"
11 #include "base/callback_forward.h"
12 #include "base/memory/ref_counted.h"
13 #include "chrome/browser/favicon/favicon_service.h"
14 #include "chrome/browser/favicon/favicon_tab_helper.h"
15 #include "chrome/common/cancelable_task_tracker.h"
16 #include "chrome/common/ref_counted_util.h"
17 #include "content/public/common/favicon_url.h"
18 #include "ui/gfx/favicon_size.h"
19 #include "ui/gfx/image/image.h"
22 class FaviconHandlerDelegate
;
27 class RefCountedMemory
;
31 class NavigationEntry
;
34 // FaviconHandler works with FaviconTabHelper to fetch the specific type of
37 // FetchFavicon requests the favicon from the favicon service which in turn
38 // requests the favicon from the history database. At this point
39 // we only know the URL of the page, and not necessarily the url of the
40 // favicon. To ensure we handle reloading stale favicons as well as
41 // reloading a favicon on page reload we always request the favicon from
42 // history regardless of whether the NavigationEntry has a favicon.
44 // After the navigation two types of events are delivered (which is
45 // first depends upon who is faster): notification from the history
46 // db on our request for the favicon (OnFaviconDataForInitialURL),
47 // or a message from the renderer giving us the URL of the favicon for
48 // the page (SetFaviconURL).
49 // . If the history db has a valid up to date favicon for the page, we update
50 // the NavigationEntry and use the favicon.
51 // . When we receive the favicon url if it matches that of the NavigationEntry
52 // and the NavigationEntry's favicon is set, we do nothing (everything is
54 // . On the other hand if the database does not know the favicon for url, or
55 // the favicon is out date, or the URL from the renderer does not match that
56 // NavigationEntry we proceed to DownloadFaviconOrAskHistory. Before we
57 // invoke DownloadFaviconOrAskHistory we wait until we've received both
58 // the favicon url and the callback from history. We wait to ensure we
59 // truly know both the favicon url and the state of the database.
61 // DownloadFaviconOrAskHistory does the following:
62 // . If we have a valid favicon, but it is expired we ask the renderer to
63 // download the favicon.
64 // . Otherwise we ask the history database to update the mapping from
65 // page url to favicon url and call us back with the favicon. Remember, it is
66 // possible for the db to already have the favicon, just not the mapping
67 // between page to favicon url. The callback for this is OnFaviconData.
69 // OnFaviconData either updates the favicon of the NavigationEntry (if the
70 // db knew about the favicon), or requests the renderer to download the
73 // When the renderer downloads favicons, it considers the entire list of
74 // favicon candidates and chooses the one that best matches the preferred size
75 // (or the first one if there is no preferred size). Once the matching favicon
76 // has been determined, SetFavicon is called which updates the favicon of the
77 // NavigationEntry and notifies the database to save the favicon.
79 class FaviconHandler
{
86 FaviconHandler(Profile
* profile
,
87 FaviconHandlerDelegate
* delegate
,
89 virtual ~FaviconHandler();
91 // Initiates loading the favicon for the specified url.
92 void FetchFavicon(const GURL
& url
);
94 // Message Handler. Must be public, because also called from
95 // PrerenderContents. Collects the |image_urls| list.
96 void OnUpdateFaviconURL(int32 page_id
,
97 const std::vector
<content::FaviconURL
>& candidates
);
99 // Processes the current image_irls_ entry, requesting the image from the
100 // history / download service.
101 void ProcessCurrentUrl();
103 // Message handler for ImageHostMsg_DidDownloadImage. Called when the image
104 // at |image_url| has been downloaded.
105 // |bitmaps| is a list of all the frames of the image at |image_url|.
106 // |original_bitmap_sizes| are the sizes of |bitmaps| before they were resized
107 // to the maximum bitmap size passed to DownloadFavicon().
108 void OnDidDownloadFavicon(
110 const GURL
& image_url
,
111 const std::vector
<SkBitmap
>& bitmaps
,
112 const std::vector
<gfx::Size
>& original_bitmap_sizes
);
115 const std::deque
<content::FaviconURL
>& image_urls() const {
120 // These virtual methods make FaviconHandler testable and are overridden by
121 // TestFaviconHandler.
123 // Return the NavigationEntry for the active entry, or NULL if the active
124 // entries URL does not match that of the URL last passed to FetchFavicon.
125 virtual content::NavigationEntry
* GetEntry();
127 // Asks the render to download favicon, returns the request id.
128 virtual int DownloadFavicon(const GURL
& image_url
, int max_bitmap_size
);
130 // Ask the favicon from history
131 virtual void UpdateFaviconMappingAndFetch(
132 const GURL
& page_url
,
133 const GURL
& icon_url
,
134 chrome::IconType icon_type
,
135 const FaviconService::FaviconResultsCallback
& callback
,
136 CancelableTaskTracker
* tracker
);
138 virtual void GetFavicon(
139 const GURL
& icon_url
,
140 chrome::IconType icon_type
,
141 const FaviconService::FaviconResultsCallback
& callback
,
142 CancelableTaskTracker
* tracker
);
144 virtual void GetFaviconForURL(
145 const GURL
& page_url
,
147 const FaviconService::FaviconResultsCallback
& callback
,
148 CancelableTaskTracker
* tracker
);
150 virtual void SetHistoryFavicons(const GURL
& page_url
,
151 const GURL
& icon_url
,
152 chrome::IconType icon_type
,
153 const gfx::Image
& image
);
155 virtual FaviconService
* GetFaviconService();
157 // Returns true if the favicon should be saved.
158 virtual bool ShouldSaveFavicon(const GURL
& url
);
160 // Notifies the delegate that the favicon for the active entry was updated.
161 // |icon_url_changed| is true if a favicon with a different icon URL has been
162 // selected since the previous call to NotifyFaviconUpdated().
163 virtual void NotifyFaviconUpdated(bool icon_url_changed
);
166 friend class TestFaviconHandler
; // For testing
168 struct DownloadRequest
{
172 DownloadRequest(const GURL
& url
,
173 const GURL
& image_url
,
174 chrome::IconType icon_type
);
178 chrome::IconType icon_type
;
181 struct FaviconCandidate
{
185 FaviconCandidate(const GURL
& url
,
186 const GURL
& image_url
,
187 const gfx::Image
& image
,
189 chrome::IconType icon_type
);
195 chrome::IconType icon_type
;
198 // See description above class for details.
199 void OnFaviconDataForInitialURL(
200 const std::vector
<chrome::FaviconBitmapResult
>& favicon_bitmap_results
);
202 // If the favicon has expired, asks the renderer to download the favicon.
203 // Otherwise asks history to update the mapping between page url and icon
204 // url with a callback to OnFaviconData when done.
205 void DownloadFaviconOrAskHistory(const GURL
& page_url
,
206 const GURL
& icon_url
,
207 chrome::IconType icon_type
);
209 // See description above class for details.
211 const std::vector
<chrome::FaviconBitmapResult
>& favicon_bitmap_results
);
213 // Schedules a download for the specified entry. This adds the request to
214 // download_requests_.
215 int ScheduleDownload(const GURL
& url
,
216 const GURL
& image_url
,
217 chrome::IconType icon_type
);
219 // Updates |favicon_candidate_| and returns true if it is an exact match.
220 bool UpdateFaviconCandidate(const GURL
& url
,
221 const GURL
& image_url
,
222 const gfx::Image
& image
,
224 chrome::IconType icon_type
);
226 // Sets the image data for the favicon.
227 void SetFavicon(const GURL
& url
,
228 const GURL
& icon_url
,
229 const gfx::Image
& image
,
230 chrome::IconType icon_type
);
232 // Sets the favicon's data on the NavigationEntry.
233 // If the WebContents has a delegate, it is invalidated (INVALIDATE_TYPE_TAB).
234 void UpdateFavicon(content::NavigationEntry
* entry
,
235 const std::vector
<chrome::FaviconBitmapResult
>& favicon_bitmap_results
);
236 void UpdateFavicon(content::NavigationEntry
* entry
,
237 const GURL
& icon_url
,
238 const gfx::Image
& image
);
240 // Return the current candidate if any.
241 content::FaviconURL
* current_candidate() {
242 return (image_urls_
.size() > 0) ? &image_urls_
[0] : NULL
;
245 // Returns the preferred_icon_size according icon_types_, 0 means no
247 int preferred_icon_size() {
248 #if defined(OS_ANDROID)
251 return icon_types_
== chrome::FAVICON
? gfx::kFaviconSize
: 0;
255 // Used for FaviconService requests.
256 CancelableTaskTracker cancelable_task_tracker_
;
258 // URL of the page we're requesting the favicon for.
261 // Whether we got the initial response for the favicon back from the renderer.
262 bool got_favicon_from_history_
;
264 // Whether the favicon is out of date or the favicon data in
265 // |history_results_| is known to be incomplete. If true, it means history
266 // knows about the favicon, but we need to download the favicon because the
267 // icon has expired or the data in the database is incomplete.
268 bool favicon_expired_or_incomplete_
;
270 // Requests to the renderer to download favicons.
271 typedef std::map
<int, DownloadRequest
> DownloadRequests
;
272 DownloadRequests download_requests_
;
274 // The combination of the supported icon types.
275 const int icon_types_
;
277 // The prioritized favicon candidates from the page back from the renderer.
278 std::deque
<content::FaviconURL
> image_urls_
;
280 // The FaviconBitmapResults from history.
281 std::vector
<chrome::FaviconBitmapResult
> history_results_
;
283 // The Profile associated with this handler.
286 // This handler's delegate.
287 FaviconHandlerDelegate
* delegate_
; // weak
289 // Current favicon candidate.
290 FaviconCandidate favicon_candidate_
;
292 DISALLOW_COPY_AND_ASSIGN(FaviconHandler
);
295 #endif // CHROME_BROWSER_FAVICON_FAVICON_HANDLER_H_