Home | History | Annotate | Download | only in browser
      1 // Copyright (c) 2011 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_HELPER_H__
      6 #define CHROME_BROWSER_FAVICON_HELPER_H__
      7 #pragma once
      8 
      9 #include <map>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/callback.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "chrome/browser/favicon_service.h"
     15 #include "chrome/common/favicon_url.h"
     16 #include "chrome/common/ref_counted_util.h"
     17 #include "content/browser/cancelable_request.h"
     18 #include "content/browser/tab_contents/tab_contents_observer.h"
     19 #include "googleurl/src/gurl.h"
     20 #include "ui/gfx/favicon_size.h"
     21 
     22 class NavigationEntry;
     23 class Profile;
     24 class RefCountedMemory;
     25 class SkBitmap;
     26 class TabContents;
     27 
     28 // FaviconHelper is used to fetch the favicon for TabContents.
     29 //
     30 // FetchFavicon requests the favicon from the favicon service which in turn
     31 // requests the favicon from the history database. At this point
     32 // we only know the URL of the page, and not necessarily the url of the
     33 // favicon. To ensure we handle reloading stale favicons as well as
     34 // reloading a favicon on page reload we always request the favicon from
     35 // history regardless of whether the NavigationEntry has a favicon.
     36 //
     37 // After the navigation two types of events are delivered (which is
     38 // first depends upon who is faster): notification from the history
     39 // db on our request for the favicon (OnFaviconDataForInitialURL),
     40 // or a message from the renderer giving us the URL of the favicon for
     41 // the page (SetFaviconURL).
     42 // . If the history db has a valid up to date favicon for the page, we update
     43 //   the NavigationEntry and use the favicon.
     44 // . When we receive the favicon url if it matches that of the NavigationEntry
     45 //   and the NavigationEntry's favicon is set, we do nothing (everything is
     46 //   ok).
     47 // . On the other hand if the database does not know the favicon for url, or
     48 //   the favicon is out date, or the URL from the renderer does not match that
     49 //   NavigationEntry we proceed to DownloadFaviconOrAskHistory. Before we
     50 //   invoke DownloadFaviconOrAskHistory we wait until we've received both
     51 //   the favicon url and the callback from history. We wait to ensure we
     52 //   truly know both the favicon url and the state of the database.
     53 //
     54 // DownloadFaviconOrAskHistory does the following:
     55 // . If we have a valid favicon, but it is expired we ask the renderer to
     56 //   download the favicon.
     57 // . Otherwise we ask the history database to update the mapping from
     58 //   page url to favicon url and call us back with the favicon. Remember, it is
     59 //   possible for the db to already have the favicon, just not the mapping
     60 //   between page to favicon url. The callback for this is OnFaviconData.
     61 //
     62 // OnFaviconData either updates the favicon of the NavigationEntry (if the
     63 // db knew about the favicon), or requests the renderer to download the
     64 // favicon.
     65 //
     66 // When the renderer downloads the favicon SetFaviconImageData is invoked,
     67 // at which point we update the favicon of the NavigationEntry and notify
     68 // the database to save the favicon.
     69 
     70 class FaviconHelper : public TabContentsObserver {
     71  public:
     72   enum Type {
     73     FAVICON,
     74     TOUCH,
     75   };
     76 
     77   FaviconHelper(TabContents* tab_contents, Type icon_type);
     78   virtual ~FaviconHelper();
     79 
     80   // Initiates loading the favicon for the specified url.
     81   void FetchFavicon(const GURL& url);
     82 
     83   // Initiates loading an image from given |image_url|. Returns a download id
     84   // for caller to track the request. When download completes, |callback| is
     85   // called with the three params: the download_id, a boolean flag to indicate
     86   // whether the download succeeds and a SkBitmap as the downloaded image.
     87   // Note that |image_size| is a hint for images with multiple sizes. The
     88   // downloaded image is not resized to the given image_size. If 0 is passed,
     89   // the first frame of the image is returned.
     90   typedef Callback3<int, bool, const SkBitmap&>::Type ImageDownloadCallback;
     91   int DownloadImage(const GURL& image_url,
     92                     int image_size,
     93                     history::IconType icon_type,
     94                     ImageDownloadCallback* callback);
     95 
     96   // Message Handler.  Must be public, because also called from
     97   // PrerenderContents.
     98   void OnUpdateFaviconURL(int32 page_id,
     99                           const std::vector<FaviconURL>& candidates);
    100 
    101  protected:
    102   // These virtual methods make FaviconHelper testable and are overridden by
    103   // TestFaviconHelper
    104   //
    105   // Return the NavigationEntry for the active entry, or NULL if the active
    106   // entries URL does not match that of the URL last passed to FetchFavicon.
    107   virtual NavigationEntry* GetEntry();
    108 
    109   // Asks the render to download favicon, returns the request id.
    110   virtual int DownloadFavicon(const GURL& image_url, int image_size);
    111 
    112   // Ask the favicon from history
    113   virtual void UpdateFaviconMappingAndFetch(
    114       const GURL& page_url,
    115       const GURL& icon_url,
    116       history::IconType icon_type,
    117       CancelableRequestConsumerBase* consumer,
    118       FaviconService::FaviconDataCallback* callback);
    119 
    120   virtual void GetFavicon(
    121       const GURL& icon_url,
    122       history::IconType icon_type,
    123       CancelableRequestConsumerBase* consumer,
    124       FaviconService::FaviconDataCallback* callback);
    125 
    126   virtual void GetFaviconForURL(
    127       const GURL& page_url,
    128       int icon_types,
    129       CancelableRequestConsumerBase* consumer,
    130       FaviconService::FaviconDataCallback* callback);
    131 
    132   virtual void SetHistoryFavicon(const GURL& page_url,
    133                                  const GURL& icon_url,
    134                                  const std::vector<unsigned char>& image_data,
    135                                  history::IconType icon_type);
    136 
    137   virtual FaviconService* GetFaviconService();
    138 
    139   // Returns true if the favicon should be saved.
    140   virtual bool ShouldSaveFavicon(const GURL& url);
    141 
    142  private:
    143   friend class TestFaviconHelper; // For testing
    144 
    145   struct DownloadRequest {
    146     DownloadRequest();
    147 
    148     DownloadRequest(const GURL& url,
    149                     const GURL& image_url,
    150                     ImageDownloadCallback* callback,
    151                     history::IconType icon_type);
    152 
    153     GURL url;
    154     GURL image_url;
    155     ImageDownloadCallback* callback;
    156     history::IconType icon_type;
    157   };
    158 
    159   // TabContentsObserver overrides.
    160   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
    161 
    162   void OnDidDownloadFavicon(int id,
    163                             const GURL& image_url,
    164                             bool errored,
    165                             const SkBitmap& image);
    166 
    167   // See description above class for details.
    168   void OnFaviconDataForInitialURL(FaviconService::Handle handle,
    169                                   history::FaviconData favicon);
    170 
    171   // If the favicon has expired, asks the renderer to download the favicon.
    172   // Otherwise asks history to update the mapping between page url and icon
    173   // url with a callback to OnFaviconData when done.
    174   void DownloadFaviconOrAskHistory(const GURL& page_url,
    175                                    const GURL& icon_url,
    176                                    history::IconType icon_type);
    177 
    178   // See description above class for details.
    179   void OnFaviconData(FaviconService::Handle handle,
    180                      history::FaviconData favicon);
    181 
    182   // Schedules a download for the specified entry. This adds the request to
    183   // download_requests_.
    184   int ScheduleDownload(const GURL& url,
    185                        const GURL& image_url,
    186                        int image_size,
    187                        history::IconType icon_type,
    188                        ImageDownloadCallback* callback);
    189 
    190   // Sets the image data for the favicon. This is invoked asynchronously after
    191   // we request the TabContents to download the favicon.
    192   void SetFavicon(const GURL& url,
    193                   const GURL& icon_url,
    194                   const SkBitmap& image,
    195                   history::IconType icon_type);
    196 
    197   // Converts the FAVICON's image data to an SkBitmap and sets it on the
    198   // NavigationEntry.
    199   // If the TabContents has a delegate, it is notified of the new favicon
    200   // (INVALIDATE_FAVICON).
    201   void UpdateFavicon(NavigationEntry* entry,
    202                      scoped_refptr<RefCountedMemory> data);
    203   void UpdateFavicon(NavigationEntry* entry, const SkBitmap& image);
    204 
    205   // Scales the image such that either the width and/or height is 16 pixels
    206   // wide. Does nothing if the image is empty.
    207   SkBitmap ConvertToFaviconSize(const SkBitmap& image);
    208 
    209   void FetchFaviconInternal();
    210 
    211   // Return the current candidate if any.
    212   FaviconURL* current_candidate() {
    213     return (urls_.size() > current_url_index_) ?
    214         &urls_[current_url_index_] : NULL;
    215   }
    216 
    217   // Returns the preferred_icon_size according icon_types_, 0 means no
    218   // preference.
    219   int preferred_icon_size() {
    220     return icon_types_ == history::FAVICON ? kFaviconSize : 0;
    221   }
    222 
    223   // Used for history requests.
    224   CancelableRequestConsumer cancelable_consumer_;
    225 
    226   // URL of the page we're requesting the favicon for.
    227   GURL url_;
    228 
    229   // Whether we got the initial response for the favicon back from the renderer.
    230   // See "Favicon Details" in tab_contents.cc for more details.
    231   bool got_favicon_from_history_;
    232 
    233   // Whether the favicon is out of date. If true, it means history knows about
    234   // the favicon, but we need to download the favicon because the icon has
    235   // expired.
    236   // See "Favicon Details" in tab_contents.cc for more details.
    237   bool favicon_expired_;
    238 
    239   // Requests to the renderer to download favicons.
    240   typedef std::map<int, DownloadRequest> DownloadRequests;
    241   DownloadRequests download_requests_;
    242 
    243   // The combination of the supported icon types.
    244   const int icon_types_;
    245 
    246   // The prioritized favicon candidates from the page back from the renderer.
    247   std::vector<FaviconURL> urls_;
    248 
    249   // The current candidate's index in urls_.
    250   size_t current_url_index_;
    251 
    252   // The FaviconData from history.
    253   history::FaviconData history_icon_;
    254 
    255   DISALLOW_COPY_AND_ASSIGN(FaviconHelper);
    256 };
    257 
    258 #endif  // CHROME_BROWSER_FAVICON_HELPER_H__
    259