• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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_HELPER_H__
6 #define CHROME_BROWSER_FAVICON_HELPER_H__
7 #pragma once
8 
9 #include <map>
10 
11 #include "base/basictypes.h"
12 #include "base/callback.h"
13 #include "base/memory/ref_counted.h"
14 #include "chrome/browser/favicon_service.h"
15 #include "chrome/common/favicon_url.h"
16 #include "chrome/common/ref_counted_util.h"
17 #include "content/browser/cancelable_request.h"
18 #include "content/browser/tab_contents/tab_contents_observer.h"
19 #include "googleurl/src/gurl.h"
20 #include "ui/gfx/favicon_size.h"
21 
22 class NavigationEntry;
23 class Profile;
24 class RefCountedMemory;
25 class SkBitmap;
26 class TabContents;
27 
28 // FaviconHelper is used to fetch the favicon for TabContents.
29 //
30 // FetchFavicon requests the favicon from the favicon service which in turn
31 // requests the favicon from the history database. At this point
32 // we only know the URL of the page, and not necessarily the url of the
33 // favicon. To ensure we handle reloading stale favicons as well as
34 // reloading a favicon on page reload we always request the favicon from
35 // history regardless of whether the NavigationEntry has a favicon.
36 //
37 // After the navigation two types of events are delivered (which is
38 // first depends upon who is faster): notification from the history
39 // db on our request for the favicon (OnFaviconDataForInitialURL),
40 // or a message from the renderer giving us the URL of the favicon for
41 // the page (SetFaviconURL).
42 // . If the history db has a valid up to date favicon for the page, we update
43 //   the NavigationEntry and use the favicon.
44 // . When we receive the favicon url if it matches that of the NavigationEntry
45 //   and the NavigationEntry's favicon is set, we do nothing (everything is
46 //   ok).
47 // . On the other hand if the database does not know the favicon for url, or
48 //   the favicon is out date, or the URL from the renderer does not match that
49 //   NavigationEntry we proceed to DownloadFaviconOrAskHistory. Before we
50 //   invoke DownloadFaviconOrAskHistory we wait until we've received both
51 //   the favicon url and the callback from history. We wait to ensure we
52 //   truly know both the favicon url and the state of the database.
53 //
54 // DownloadFaviconOrAskHistory does the following:
55 // . If we have a valid favicon, but it is expired we ask the renderer to
56 //   download the favicon.
57 // . Otherwise we ask the history database to update the mapping from
58 //   page url to favicon url and call us back with the favicon. Remember, it is
59 //   possible for the db to already have the favicon, just not the mapping
60 //   between page to favicon url. The callback for this is OnFaviconData.
61 //
62 // OnFaviconData either updates the favicon of the NavigationEntry (if the
63 // db knew about the favicon), or requests the renderer to download the
64 // favicon.
65 //
66 // When the renderer downloads the favicon SetFaviconImageData is invoked,
67 // at which point we update the favicon of the NavigationEntry and notify
68 // the database to save the favicon.
69 
70 class FaviconHelper : public TabContentsObserver {
71  public:
72   enum Type {
73     FAVICON,
74     TOUCH,
75   };
76 
77   FaviconHelper(TabContents* tab_contents, Type icon_type);
78   virtual ~FaviconHelper();
79 
80   // Initiates loading the favicon for the specified url.
81   void FetchFavicon(const GURL& url);
82 
83   // Initiates loading an image from given |image_url|. Returns a download id
84   // for caller to track the request. When download completes, |callback| is
85   // called with the three params: the download_id, a boolean flag to indicate
86   // whether the download succeeds and a SkBitmap as the downloaded image.
87   // Note that |image_size| is a hint for images with multiple sizes. The
88   // downloaded image is not resized to the given image_size. If 0 is passed,
89   // the first frame of the image is returned.
90   typedef Callback3<int, bool, const SkBitmap&>::Type ImageDownloadCallback;
91   int DownloadImage(const GURL& image_url,
92                     int image_size,
93                     history::IconType icon_type,
94                     ImageDownloadCallback* callback);
95 
96   // Message Handler.  Must be public, because also called from
97   // PrerenderContents.
98   void OnUpdateFaviconURL(int32 page_id,
99                           const std::vector<FaviconURL>& candidates);
100 
101  protected:
102   // These virtual methods make FaviconHelper testable and are overridden by
103   // TestFaviconHelper
104   //
105   // Return the NavigationEntry for the active entry, or NULL if the active
106   // entries URL does not match that of the URL last passed to FetchFavicon.
107   virtual NavigationEntry* GetEntry();
108 
109   // Asks the render to download favicon, returns the request id.
110   virtual int DownloadFavicon(const GURL& image_url, int image_size);
111 
112   // Ask the favicon from history
113   virtual void UpdateFaviconMappingAndFetch(
114       const GURL& page_url,
115       const GURL& icon_url,
116       history::IconType icon_type,
117       CancelableRequestConsumerBase* consumer,
118       FaviconService::FaviconDataCallback* callback);
119 
120   virtual void GetFavicon(
121       const GURL& icon_url,
122       history::IconType icon_type,
123       CancelableRequestConsumerBase* consumer,
124       FaviconService::FaviconDataCallback* callback);
125 
126   virtual void GetFaviconForURL(
127       const GURL& page_url,
128       int icon_types,
129       CancelableRequestConsumerBase* consumer,
130       FaviconService::FaviconDataCallback* callback);
131 
132   virtual void SetHistoryFavicon(const GURL& page_url,
133                                  const GURL& icon_url,
134                                  const std::vector<unsigned char>& image_data,
135                                  history::IconType icon_type);
136 
137   virtual FaviconService* GetFaviconService();
138 
139   // Returns true if the favicon should be saved.
140   virtual bool ShouldSaveFavicon(const GURL& url);
141 
142  private:
143   friend class TestFaviconHelper; // For testing
144 
145   struct DownloadRequest {
146     DownloadRequest();
147 
148     DownloadRequest(const GURL& url,
149                     const GURL& image_url,
150                     ImageDownloadCallback* callback,
151                     history::IconType icon_type);
152 
153     GURL url;
154     GURL image_url;
155     ImageDownloadCallback* callback;
156     history::IconType icon_type;
157   };
158 
159   // TabContentsObserver overrides.
160   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
161 
162   void OnDidDownloadFavicon(int id,
163                             const GURL& image_url,
164                             bool errored,
165                             const SkBitmap& image);
166 
167   // See description above class for details.
168   void OnFaviconDataForInitialURL(FaviconService::Handle handle,
169                                   history::FaviconData favicon);
170 
171   // If the favicon has expired, asks the renderer to download the favicon.
172   // Otherwise asks history to update the mapping between page url and icon
173   // url with a callback to OnFaviconData when done.
174   void DownloadFaviconOrAskHistory(const GURL& page_url,
175                                    const GURL& icon_url,
176                                    history::IconType icon_type);
177 
178   // See description above class for details.
179   void OnFaviconData(FaviconService::Handle handle,
180                      history::FaviconData favicon);
181 
182   // Schedules a download for the specified entry. This adds the request to
183   // download_requests_.
184   int ScheduleDownload(const GURL& url,
185                        const GURL& image_url,
186                        int image_size,
187                        history::IconType icon_type,
188                        ImageDownloadCallback* callback);
189 
190   // Sets the image data for the favicon. This is invoked asynchronously after
191   // we request the TabContents to download the favicon.
192   void SetFavicon(const GURL& url,
193                   const GURL& icon_url,
194                   const SkBitmap& image,
195                   history::IconType icon_type);
196 
197   // Converts the FAVICON's image data to an SkBitmap and sets it on the
198   // NavigationEntry.
199   // If the TabContents has a delegate, it is notified of the new favicon
200   // (INVALIDATE_FAVICON).
201   void UpdateFavicon(NavigationEntry* entry,
202                      scoped_refptr<RefCountedMemory> data);
203   void UpdateFavicon(NavigationEntry* entry, const SkBitmap& image);
204 
205   // Scales the image such that either the width and/or height is 16 pixels
206   // wide. Does nothing if the image is empty.
207   SkBitmap ConvertToFaviconSize(const SkBitmap& image);
208 
209   void FetchFaviconInternal();
210 
211   // Return the current candidate if any.
current_candidate()212   FaviconURL* current_candidate() {
213     return (urls_.size() > current_url_index_) ?
214         &urls_[current_url_index_] : NULL;
215   }
216 
217   // Returns the preferred_icon_size according icon_types_, 0 means no
218   // preference.
preferred_icon_size()219   int preferred_icon_size() {
220     return icon_types_ == history::FAVICON ? kFaviconSize : 0;
221   }
222 
223   // Used for history requests.
224   CancelableRequestConsumer cancelable_consumer_;
225 
226   // URL of the page we're requesting the favicon for.
227   GURL url_;
228 
229   // Whether we got the initial response for the favicon back from the renderer.
230   // See "Favicon Details" in tab_contents.cc for more details.
231   bool got_favicon_from_history_;
232 
233   // Whether the favicon is out of date. If true, it means history knows about
234   // the favicon, but we need to download the favicon because the icon has
235   // expired.
236   // See "Favicon Details" in tab_contents.cc for more details.
237   bool favicon_expired_;
238 
239   // Requests to the renderer to download favicons.
240   typedef std::map<int, DownloadRequest> DownloadRequests;
241   DownloadRequests download_requests_;
242 
243   // The combination of the supported icon types.
244   const int icon_types_;
245 
246   // The prioritized favicon candidates from the page back from the renderer.
247   std::vector<FaviconURL> urls_;
248 
249   // The current candidate's index in urls_.
250   size_t current_url_index_;
251 
252   // The FaviconData from history.
253   history::FaviconData history_icon_;
254 
255   DISALLOW_COPY_AND_ASSIGN(FaviconHelper);
256 };
257 
258 #endif  // CHROME_BROWSER_FAVICON_HELPER_H__
259