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