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 // |original_bitmap_sizes| are the sizes of |bitmaps| before they were resized 107 // to the maximum bitmap size passed to DownloadFavicon(). 108 void OnDidDownloadFavicon( 109 int id, 110 const GURL& image_url, 111 const std::vector<SkBitmap>& bitmaps, 112 const std::vector<gfx::Size>& original_bitmap_sizes); 113 114 // For testing. 115 const std::deque<content::FaviconURL>& image_urls() const { 116 return image_urls_; 117 } 118 119 protected: 120 // These virtual methods make FaviconHandler testable and are overridden by 121 // TestFaviconHandler. 122 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(); 126 127 // Asks the render to download favicon, returns the request id. 128 virtual int DownloadFavicon(const GURL& image_url, int max_bitmap_size); 129 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); 137 138 virtual void GetFavicon( 139 const GURL& icon_url, 140 chrome::IconType icon_type, 141 const FaviconService::FaviconResultsCallback& callback, 142 CancelableTaskTracker* tracker); 143 144 virtual void GetFaviconForURL( 145 const GURL& page_url, 146 int icon_types, 147 const FaviconService::FaviconResultsCallback& callback, 148 CancelableTaskTracker* tracker); 149 150 virtual void SetHistoryFavicons(const GURL& page_url, 151 const GURL& icon_url, 152 chrome::IconType icon_type, 153 const gfx::Image& image); 154 155 virtual FaviconService* GetFaviconService(); 156 157 // Returns true if the favicon should be saved. 158 virtual bool ShouldSaveFavicon(const GURL& url); 159 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); 164 165 private: 166 friend class TestFaviconHandler; // For testing 167 168 struct DownloadRequest { 169 DownloadRequest(); 170 ~DownloadRequest(); 171 172 DownloadRequest(const GURL& url, 173 const GURL& image_url, 174 chrome::IconType icon_type); 175 176 GURL url; 177 GURL image_url; 178 chrome::IconType icon_type; 179 }; 180 181 struct FaviconCandidate { 182 FaviconCandidate(); 183 ~FaviconCandidate(); 184 185 FaviconCandidate(const GURL& url, 186 const GURL& image_url, 187 const gfx::Image& image, 188 float score, 189 chrome::IconType icon_type); 190 191 GURL url; 192 GURL image_url; 193 gfx::Image image; 194 float score; 195 chrome::IconType icon_type; 196 }; 197 198 // See description above class for details. 199 void OnFaviconDataForInitialURL( 200 const std::vector<chrome::FaviconBitmapResult>& favicon_bitmap_results); 201 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); 208 209 // See description above class for details. 210 void OnFaviconData( 211 const std::vector<chrome::FaviconBitmapResult>& favicon_bitmap_results); 212 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); 218 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, 223 float score, 224 chrome::IconType icon_type); 225 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); 231 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); 239 240 // Return the current candidate if any. 241 content::FaviconURL* current_candidate() { 242 return (image_urls_.size() > 0) ? &image_urls_[0] : NULL; 243 } 244 245 // Returns the preferred_icon_size according icon_types_, 0 means no 246 // preference. 247 int preferred_icon_size() { 248 #if defined(OS_ANDROID) 249 return 0; 250 #else 251 return icon_types_ == chrome::FAVICON ? gfx::kFaviconSize : 0; 252 #endif 253 } 254 255 // Used for FaviconService requests. 256 CancelableTaskTracker cancelable_task_tracker_; 257 258 // URL of the page we're requesting the favicon for. 259 GURL url_; 260 261 // Whether we got the initial response for the favicon back from the renderer. 262 bool got_favicon_from_history_; 263 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_; 269 270 // Requests to the renderer to download favicons. 271 typedef std::map<int, DownloadRequest> DownloadRequests; 272 DownloadRequests download_requests_; 273 274 // The combination of the supported icon types. 275 const int icon_types_; 276 277 // The prioritized favicon candidates from the page back from the renderer. 278 std::deque<content::FaviconURL> image_urls_; 279 280 // The FaviconBitmapResults from history. 281 std::vector<chrome::FaviconBitmapResult> history_results_; 282 283 // The Profile associated with this handler. 284 Profile* profile_; 285 286 // This handler's delegate. 287 FaviconHandlerDelegate* delegate_; // weak 288 289 // Current favicon candidate. 290 FaviconCandidate favicon_candidate_; 291 292 DISALLOW_COPY_AND_ASSIGN(FaviconHandler); 293 }; 294 295 #endif // CHROME_BROWSER_FAVICON_FAVICON_HANDLER_H_ 296