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_HANDLER_H_ 6 #define CHROME_BROWSER_FAVICON_FAVICON_HANDLER_H_ 7 8 #include <map> 9 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" 20 #include "url/gurl.h" 21 22 class FaviconHandlerDelegate; 23 class Profile; 24 class SkBitmap; 25 26 namespace base { 27 class RefCountedMemory; 28 } 29 30 namespace content { 31 class NavigationEntry; 32 } 33 34 // FaviconHandler works with FaviconTabHelper to fetch the specific type of 35 // favicon. 36 // 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. 43 // 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 53 // ok). 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. 60 // 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. 68 // 69 // OnFaviconData either updates the favicon of the NavigationEntry (if the 70 // db knew about the favicon), or requests the renderer to download the 71 // favicon. 72 // 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. 78 79 class FaviconHandler { 80 public: 81 enum Type { 82 FAVICON, 83 TOUCH, 84 }; 85 86 FaviconHandler(Profile* profile, 87 FaviconHandlerDelegate* delegate, 88 Type icon_type); 89 virtual ~FaviconHandler(); 90 91 // Initiates loading the favicon for the specified url. 92 void FetchFavicon(const GURL& url); 93 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); 98 99 // Processes the current image_irls_ entry, requesting the image from the 100 // history / download service. 101 void ProcessCurrentUrl(); 102 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 void OnDidDownloadFavicon(int id, 107 const GURL& image_url, 108 int requested_size, 109 const std::vector<SkBitmap>& bitmaps); 110 111 // For testing. 112 const std::deque<content::FaviconURL>& image_urls() const { 113 return image_urls_; 114 } 115 116 protected: 117 // These virtual methods make FaviconHandler testable and are overridden by 118 // TestFaviconHandler. 119 120 // Return the NavigationEntry for the active entry, or NULL if the active 121 // entries URL does not match that of the URL last passed to FetchFavicon. 122 virtual content::NavigationEntry* GetEntry(); 123 124 // Asks the render to download favicon, returns the request id. 125 virtual int DownloadFavicon(const GURL& image_url, 126 int image_size, 127 chrome::IconType icon_type); 128 129 // Ask the favicon from history 130 virtual void UpdateFaviconMappingAndFetch( 131 const GURL& page_url, 132 const GURL& icon_url, 133 chrome::IconType icon_type, 134 const FaviconService::FaviconResultsCallback& callback, 135 CancelableTaskTracker* tracker); 136 137 virtual void GetFavicon( 138 const GURL& icon_url, 139 chrome::IconType icon_type, 140 const FaviconService::FaviconResultsCallback& callback, 141 CancelableTaskTracker* tracker); 142 143 virtual void GetFaviconForURL( 144 const GURL& page_url, 145 int icon_types, 146 const FaviconService::FaviconResultsCallback& callback, 147 CancelableTaskTracker* tracker); 148 149 virtual void SetHistoryFavicons(const GURL& page_url, 150 const GURL& icon_url, 151 chrome::IconType icon_type, 152 const gfx::Image& image); 153 154 virtual FaviconService* GetFaviconService(); 155 156 // Returns true if the favicon should be saved. 157 virtual bool ShouldSaveFavicon(const GURL& url); 158 159 private: 160 friend class TestFaviconHandler; // For testing 161 162 struct DownloadRequest { 163 DownloadRequest(); 164 ~DownloadRequest(); 165 166 DownloadRequest(const GURL& url, 167 const GURL& image_url, 168 chrome::IconType icon_type); 169 170 GURL url; 171 GURL image_url; 172 chrome::IconType icon_type; 173 }; 174 175 struct FaviconCandidate { 176 FaviconCandidate(); 177 ~FaviconCandidate(); 178 179 FaviconCandidate(const GURL& url, 180 const GURL& image_url, 181 const gfx::Image& image, 182 float score, 183 chrome::IconType icon_type); 184 185 GURL url; 186 GURL image_url; 187 gfx::Image image; 188 float score; 189 chrome::IconType icon_type; 190 }; 191 192 // See description above class for details. 193 void OnFaviconDataForInitialURL( 194 const std::vector<chrome::FaviconBitmapResult>& favicon_bitmap_results); 195 196 // If the favicon has expired, asks the renderer to download the favicon. 197 // Otherwise asks history to update the mapping between page url and icon 198 // url with a callback to OnFaviconData when done. 199 void DownloadFaviconOrAskHistory(const GURL& page_url, 200 const GURL& icon_url, 201 chrome::IconType icon_type); 202 203 // See description above class for details. 204 void OnFaviconData( 205 const std::vector<chrome::FaviconBitmapResult>& favicon_bitmap_results); 206 207 // Schedules a download for the specified entry. This adds the request to 208 // download_requests_. 209 int ScheduleDownload(const GURL& url, 210 const GURL& image_url, 211 int image_size, 212 chrome::IconType icon_type); 213 214 // Updates |favicon_candidate_| and returns true if it is an exact match. 215 bool UpdateFaviconCandidate(const GURL& url, 216 const GURL& image_url, 217 const gfx::Image& image, 218 float score, 219 chrome::IconType icon_type); 220 221 // Sets the image data for the favicon. 222 void SetFavicon(const GURL& url, 223 const GURL& icon_url, 224 const gfx::Image& image, 225 chrome::IconType icon_type); 226 227 // Sets the favicon's data on the NavigationEntry. 228 // If the WebContents has a delegate, it is invalidated (INVALIDATE_TYPE_TAB). 229 void UpdateFavicon(content::NavigationEntry* entry, 230 const std::vector<chrome::FaviconBitmapResult>& favicon_bitmap_results); 231 void UpdateFavicon(content::NavigationEntry* entry, 232 const GURL& icon_url, 233 const gfx::Image& image); 234 235 // Return the current candidate if any. 236 content::FaviconURL* current_candidate() { 237 return (image_urls_.size() > 0) ? &image_urls_[0] : NULL; 238 } 239 240 // Returns the preferred_icon_size according icon_types_, 0 means no 241 // preference. 242 int preferred_icon_size() { 243 return icon_types_ == chrome::FAVICON ? gfx::kFaviconSize : 0; 244 } 245 246 // Used for FaviconService requests. 247 CancelableTaskTracker cancelable_task_tracker_; 248 249 // URL of the page we're requesting the favicon for. 250 GURL url_; 251 252 // Whether we got the initial response for the favicon back from the renderer. 253 bool got_favicon_from_history_; 254 255 // Whether the favicon is out of date or the favicon data in 256 // |history_results_| is known to be incomplete. If true, it means history 257 // knows about the favicon, but we need to download the favicon because the 258 // icon has expired or the data in the database is incomplete. 259 bool favicon_expired_or_incomplete_; 260 261 // Requests to the renderer to download favicons. 262 typedef std::map<int, DownloadRequest> DownloadRequests; 263 DownloadRequests download_requests_; 264 265 // The combination of the supported icon types. 266 const int icon_types_; 267 268 // The prioritized favicon candidates from the page back from the renderer. 269 std::deque<content::FaviconURL> image_urls_; 270 271 // The FaviconBitmapResults from history. 272 std::vector<chrome::FaviconBitmapResult> history_results_; 273 274 // The Profile associated with this handler. 275 Profile* profile_; 276 277 // This handler's delegate. 278 FaviconHandlerDelegate* delegate_; // weak 279 280 // Current favicon candidate. 281 FaviconCandidate favicon_candidate_; 282 283 DISALLOW_COPY_AND_ASSIGN(FaviconHandler); 284 }; 285 286 #endif // CHROME_BROWSER_FAVICON_FAVICON_HANDLER_H_ 287