Home | History | Annotate | Download | only in favicon
      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