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 <deque> 9 #include <map> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/callback_forward.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/task/cancelable_task_tracker.h" 16 #include "components/favicon/core/favicon_url.h" 17 #include "components/favicon_base/favicon_callback.h" 18 #include "ui/gfx/favicon_size.h" 19 #include "ui/gfx/image/image.h" 20 #include "url/gurl.h" 21 22 class FaviconClient; 23 class FaviconDriver; 24 class SkBitmap; 25 26 namespace base { 27 class RefCountedMemory; 28 } 29 30 // FaviconHandler works with FaviconDriver to fetch the specific type of 31 // favicon. 32 // 33 // FetchFavicon requests the favicon from the favicon service which in turn 34 // requests the favicon from the history database. At this point 35 // we only know the URL of the page, and not necessarily the url of the 36 // favicon. To ensure we handle reloading stale favicons as well as 37 // reloading a favicon on page reload we always request the favicon from 38 // history regardless of whether the active favicon is valid. 39 // 40 // After the navigation two types of events are delivered (which is 41 // first depends upon who is faster): notification from the history 42 // db on our request for the favicon 43 // (OnFaviconDataForInitialURLFromFaviconService), or a message from the 44 // renderer giving us the URL of the favicon for the page (SetFaviconURL). 45 // . If the history db has a valid up to date favicon for the page, we update 46 // the current page and use the favicon. 47 // . When we receive the favicon url if it matches that of the current page 48 // and the current page's favicon is set, we do nothing (everything is 49 // ok). 50 // . On the other hand if the database does not know the favicon for url, or 51 // the favicon is out date, or the URL from the renderer does not match that 52 // of the current page we proceed to DownloadFaviconOrAskHistory. Before we 53 // invoke DownloadFaviconOrAskHistory we wait until we've received both 54 // the favicon url and the callback from history. We wait to ensure we 55 // truly know both the favicon url and the state of the database. 56 // 57 // DownloadFaviconOrAskHistory does the following: 58 // . If we have a valid favicon, but it is expired we ask the renderer to 59 // download the favicon. 60 // . Otherwise we ask the history database to update the mapping from 61 // page url to favicon url and call us back with the favicon. Remember, it is 62 // possible for the db to already have the favicon, just not the mapping 63 // between page to favicon url. The callback for this is OnFaviconData. 64 // 65 // OnFaviconData either updates the favicon of the current page (if the 66 // db knew about the favicon), or requests the renderer to download the 67 // favicon. 68 // 69 // When the renderer downloads favicons, it considers the entire list of 70 // favicon candidates, if |download_largest_favicon_| is true, the largest 71 // favicon will be used, otherwise the one that best matches the preferred size 72 // is chosen (or the first one if there is no preferred size). Once the 73 // matching favicon has been determined, SetFavicon is called which updates 74 // the page's favicon and notifies the database to save the favicon. 75 76 class FaviconHandler { 77 public: 78 enum Type { 79 FAVICON, 80 TOUCH, 81 }; 82 83 FaviconHandler(FaviconClient* client, 84 FaviconDriver* driver, 85 Type icon_type, 86 bool download_largest_icon); 87 virtual ~FaviconHandler(); 88 89 // Initiates loading the favicon for the specified url. 90 void FetchFavicon(const GURL& url); 91 92 // Message Handler. Must be public, because also called from 93 // PrerenderContents. Collects the |image_urls| list. 94 void OnUpdateFaviconURL(const std::vector<favicon::FaviconURL>& candidates); 95 96 // Processes the current image_irls_ entry, requesting the image from the 97 // history / download service. 98 void ProcessCurrentUrl(); 99 100 // Message handler for ImageHostMsg_DidDownloadImage. Called when the image 101 // at |image_url| has been downloaded. 102 // |bitmaps| is a list of all the frames of the image at |image_url|. 103 // |original_bitmap_sizes| are the sizes of |bitmaps| before they were resized 104 // to the maximum bitmap size passed to DownloadFavicon(). 105 void OnDidDownloadFavicon( 106 int id, 107 const GURL& image_url, 108 const std::vector<SkBitmap>& bitmaps, 109 const std::vector<gfx::Size>& original_bitmap_sizes); 110 111 // For testing. image_urls()112 const std::vector<favicon::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 // Asks the render to download favicon, returns the request id. 121 virtual int DownloadFavicon(const GURL& image_url, int max_bitmap_size); 122 123 // Ask the favicon from history 124 virtual void UpdateFaviconMappingAndFetch( 125 const GURL& page_url, 126 const GURL& icon_url, 127 favicon_base::IconType icon_type, 128 const favicon_base::FaviconResultsCallback& callback, 129 base::CancelableTaskTracker* tracker); 130 131 virtual void GetFaviconFromFaviconService( 132 const GURL& icon_url, 133 favicon_base::IconType icon_type, 134 const favicon_base::FaviconResultsCallback& callback, 135 base::CancelableTaskTracker* tracker); 136 137 virtual void GetFaviconForURLFromFaviconService( 138 const GURL& page_url, 139 int icon_types, 140 const favicon_base::FaviconResultsCallback& callback, 141 base::CancelableTaskTracker* tracker); 142 143 virtual void SetHistoryFavicons(const GURL& page_url, 144 const GURL& icon_url, 145 favicon_base::IconType icon_type, 146 const gfx::Image& image); 147 148 // Returns true if the favicon should be saved. 149 virtual bool ShouldSaveFavicon(const GURL& url); 150 151 // Notifies the driver that the favicon for the active entry was updated. 152 // |icon_url_changed| is true if a favicon with a different icon URL has been 153 // selected since the previous call to NotifyFaviconUpdated(). 154 virtual void NotifyFaviconUpdated(bool icon_url_changed); 155 156 private: 157 friend class TestFaviconHandler; // For testing 158 159 // Represents an in progress download of an image from the renderer. 160 struct DownloadRequest { 161 DownloadRequest(); 162 ~DownloadRequest(); 163 164 DownloadRequest(const GURL& url, 165 const GURL& image_url, 166 favicon_base::IconType icon_type); 167 168 GURL url; 169 GURL image_url; 170 favicon_base::IconType icon_type; 171 }; 172 173 // Used to track a candidate for the favicon. 174 struct FaviconCandidate { 175 FaviconCandidate(); 176 ~FaviconCandidate(); 177 178 FaviconCandidate(const GURL& url, 179 const GURL& image_url, 180 const gfx::Image& image, 181 float score, 182 favicon_base::IconType icon_type); 183 184 GURL url; 185 GURL image_url; 186 gfx::Image image; 187 float score; 188 favicon_base::IconType icon_type; 189 }; 190 191 // See description above class for details. 192 void OnFaviconDataForInitialURLFromFaviconService(const std::vector< 193 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results); 194 195 // If the favicon has expired, asks the renderer to download the favicon. 196 // Otherwise asks history to update the mapping between page url and icon 197 // url with a callback to OnFaviconData when done. 198 void DownloadFaviconOrAskFaviconService(const GURL& page_url, 199 const GURL& icon_url, 200 favicon_base::IconType icon_type); 201 202 // See description above class for details. 203 void OnFaviconData(const std::vector<favicon_base::FaviconRawBitmapResult>& 204 favicon_bitmap_results); 205 206 // Schedules a download for the specified entry. This adds the request to 207 // download_requests_. 208 int ScheduleDownload(const GURL& url, 209 const GURL& image_url, 210 favicon_base::IconType icon_type); 211 212 // Updates |favicon_candidate_| and returns true if it is an exact match. 213 bool UpdateFaviconCandidate(const GURL& url, 214 const GURL& image_url, 215 const gfx::Image& image, 216 float score, 217 favicon_base::IconType icon_type); 218 219 // Sets the image data for the favicon. 220 void SetFavicon(const GURL& url, 221 const GURL& icon_url, 222 const gfx::Image& image, 223 favicon_base::IconType icon_type); 224 225 // Sets the favicon's data. 226 void SetFaviconOnActivePage(const std::vector< 227 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results); 228 void SetFaviconOnActivePage(const GURL& icon_url, const gfx::Image& image); 229 230 // Return the current candidate if any. current_candidate()231 favicon::FaviconURL* current_candidate() { 232 return (!image_urls_.empty()) ? &image_urls_.front() : NULL; 233 } 234 235 // Returns whether the page's url changed since the favicon was requested. 236 bool PageChangedSinceFaviconWasRequested(); 237 238 // Returns the preferred size of the image. 0 means no preference (any size 239 // will do). preferred_icon_size()240 int preferred_icon_size() const { 241 if (download_largest_icon_) 242 return 0; 243 return icon_types_ == favicon_base::FAVICON ? gfx::kFaviconSize : 0; 244 } 245 246 // Sorts the entries in |image_urls_| by icon size in descending order. 247 // Additionally removes any entries whose sizes are all greater than the max 248 // allowed size. 249 void SortAndPruneImageUrls(); 250 251 // Used for FaviconService requests. 252 base::CancelableTaskTracker cancelable_task_tracker_; 253 254 // URL of the page we're requesting the favicon for. 255 GURL url_; 256 257 // Whether we got the initial response for the favicon back from the renderer. 258 bool got_favicon_from_history_; 259 260 // Whether the favicon is out of date or the favicon data in 261 // |history_results_| is known to be incomplete. If true, it means history 262 // knows about the favicon, but we need to download the favicon because the 263 // icon has expired or the data in the database is incomplete. 264 bool favicon_expired_or_incomplete_; 265 266 // Requests to the renderer to download favicons. 267 typedef std::map<int, DownloadRequest> DownloadRequests; 268 DownloadRequests download_requests_; 269 270 // The combination of the supported icon types. 271 const int icon_types_; 272 273 // Whether the largest icon should be downloaded. 274 const bool download_largest_icon_; 275 276 // The prioritized favicon candidates from the page back from the renderer. 277 std::vector<favicon::FaviconURL> image_urls_; 278 279 // The FaviconRawBitmapResults from history. 280 std::vector<favicon_base::FaviconRawBitmapResult> history_results_; 281 282 // The client which implements embedder-specific Favicon operations. 283 FaviconClient* client_; // weak 284 285 // This handler's driver. 286 FaviconDriver* driver_; // weak 287 288 // Best image we've seen so far. As images are downloaded from the page they 289 // are stored here. When there is an exact match, or no more images are 290 // available the favicon service and the current page are updated (assuming 291 // the image is for a favicon). 292 FaviconCandidate best_favicon_candidate_; 293 294 DISALLOW_COPY_AND_ASSIGN(FaviconHandler); 295 }; 296 297 #endif // CHROME_BROWSER_FAVICON_FAVICON_HANDLER_H_ 298