Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2013 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_SYNC_GLUE_FAVICON_CACHE_H_
      6 #define CHROME_BROWSER_SYNC_GLUE_FAVICON_CACHE_H_
      7 
      8 #include <map>
      9 #include <string>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/memory/linked_ptr.h"
     14 #include "base/memory/ref_counted.h"
     15 #include "base/memory/ref_counted_memory.h"
     16 #include "base/memory/scoped_ptr.h"
     17 #include "base/memory/weak_ptr.h"
     18 #include "chrome/browser/history/history_types.h"
     19 #include "chrome/browser/sessions/session_id.h"
     20 #include "chrome/common/cancelable_task_tracker.h"
     21 #include "content/public/browser/notification_observer.h"
     22 #include "content/public/browser/notification_registrar.h"
     23 #include "sync/api/sync_change.h"
     24 #include "sync/api/sync_error_factory.h"
     25 #include "sync/api/syncable_service.h"
     26 #include "url/gurl.h"
     27 
     28 class Profile;
     29 
     30 namespace chrome {
     31 struct FaviconBitmapResult;
     32 }
     33 
     34 namespace browser_sync {
     35 
     36 enum IconSize {
     37   SIZE_INVALID,
     38   SIZE_16,
     39   SIZE_32,
     40   SIZE_64,
     41   NUM_SIZES
     42 };
     43 
     44 struct SyncedFaviconInfo;
     45 
     46 // Encapsulates the logic for loading and storing synced favicons.
     47 // TODO(zea): make this a BrowserContextKeyedService.
     48 class FaviconCache : public syncer::SyncableService,
     49                      public content::NotificationObserver {
     50  public:
     51   FaviconCache(Profile* profile, int max_sync_favicon_limit);
     52   virtual ~FaviconCache();
     53 
     54   // SyncableService implementation.
     55   virtual syncer::SyncMergeResult MergeDataAndStartSyncing(
     56       syncer::ModelType type,
     57       const syncer::SyncDataList& initial_sync_data,
     58       scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
     59       scoped_ptr<syncer::SyncErrorFactory> error_handler) OVERRIDE;
     60   virtual void StopSyncing(syncer::ModelType type) OVERRIDE;
     61   virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type)
     62       const OVERRIDE;
     63   virtual syncer::SyncError ProcessSyncChanges(
     64       const tracked_objects::Location& from_here,
     65       const syncer::SyncChangeList& change_list) OVERRIDE;
     66 
     67   // If a valid favicon for the icon at |favicon_url| is found, fills
     68   // |favicon_png| with the png-encoded image and returns true. Else, returns
     69   // false.
     70   bool GetSyncedFaviconForFaviconURL(
     71       const GURL& favicon_url,
     72       scoped_refptr<base::RefCountedMemory>* favicon_png) const;
     73 
     74   // If a valid favicon for the icon associated with |page_url| is found, fills
     75   // |favicon_png| with the png-encoded image and returns true. Else, returns
     76   // false.
     77   bool GetSyncedFaviconForPageURL(
     78       const GURL& page_url,
     79       scoped_refptr<base::RefCountedMemory>* favicon_png) const;
     80 
     81   // Load the favicon for |page_url|. Will create a new sync node or update
     82   // an existing one as necessary, and set the last visit time to the current
     83   // time. Only those favicon types defined in SupportedFaviconTypes will be
     84   // synced.
     85   void OnPageFaviconUpdated(const GURL& page_url);
     86 
     87   // Update the visit count for the favicon associated with |favicon_url|.
     88   // If no favicon exists associated with |favicon_url|, triggers a load
     89   // for the favicon associated with |page_url|.
     90   void OnFaviconVisited(const GURL& page_url, const GURL& favicon_url);
     91 
     92   // Consume Session sync favicon data. Will not overwrite existing favicons.
     93   // If |icon_bytes| is empty, only updates the page->favicon url mapping.
     94   // Safe to call within a transaction.
     95   void OnReceivedSyncFavicon(const GURL& page_url,
     96                              const GURL& icon_url,
     97                              const std::string& icon_bytes,
     98                              int64 visit_time_ms);
     99 
    100   // NotificationObserver implementation.
    101   virtual void Observe(int type,
    102                        const content::NotificationSource& source,
    103                        const content::NotificationDetails& details) OVERRIDE;
    104 
    105  private:
    106   friend class SyncFaviconCacheTest;
    107 
    108   // Functor for ordering SyncedFaviconInfo objects by recency;
    109   struct FaviconRecencyFunctor {
    110     bool operator()(const linked_ptr<SyncedFaviconInfo>& lhs,
    111                     const linked_ptr<SyncedFaviconInfo>& rhs) const;
    112   };
    113 
    114 
    115   // Map of favicon url to favicon image.
    116   typedef std::map<GURL, linked_ptr<SyncedFaviconInfo> > FaviconMap;
    117   typedef std::set<linked_ptr<SyncedFaviconInfo>,
    118                    FaviconRecencyFunctor> RecencySet;
    119   // Map of page url to task id (for favicon loading).
    120   typedef std::map<GURL, CancelableTaskTracker::TaskId> PageTaskMap;
    121   // Map of page url to favicon url.
    122   typedef std::map<GURL, GURL> PageFaviconMap;
    123 
    124   // Helper method to perform OnReceivedSyncFavicon work without worrying about
    125   // whether caller holds a sync transaction.
    126   void OnReceivedSyncFaviconImpl(const GURL& icon_url,
    127                                  const std::string& icon_bytes,
    128                                  int64 visit_time_ms);
    129 
    130   // Callback method to store a tab's favicon into its sync node once it becomes
    131   // available. Does nothing if no favicon data was available.
    132   void OnFaviconDataAvailable(
    133       const GURL& page_url,
    134       const std::vector<chrome::FaviconBitmapResult>& bitmap_result);
    135 
    136   // Helper method to update the sync state of the favicon at |icon_url|. If
    137   // either |image_change_type| or |tracking_change_type| is ACTION_INVALID,
    138   // the corresponding datatype won't be updated.
    139   // Note: should only be called after both FAVICON_IMAGES and FAVICON_TRACKING
    140   // have been successfully set up.
    141   void UpdateSyncState(const GURL& icon_url,
    142                        syncer::SyncChange::SyncChangeType image_change_type,
    143                        syncer::SyncChange::SyncChangeType tracking_change_type);
    144 
    145   // Helper method to get favicon info from |synced_favicons_|. If no info
    146   // exists for |icon_url|, creates a new SyncedFaviconInfo in both
    147   // |synced_favicons_| and |recent_favicons_| and returns it.
    148   SyncedFaviconInfo* GetFaviconInfo(const GURL& icon_url);
    149 
    150   // Updates the last visit time for the favicon at |icon_url| to |time| (and
    151   // correspondly updates position in |recent_favicons_|.
    152   void UpdateFaviconVisitTime(const GURL& icon_url, base::Time time);
    153 
    154   // Expiration method. Looks through |recent_favicons_| to find any favicons
    155   // that should be expired in order to maintain the sync favicon limit,
    156   // appending deletions to |image_changes| and |tracking_changes| as necessary.
    157   void ExpireFaviconsIfNecessary(syncer::SyncChangeList* image_changes,
    158                                  syncer::SyncChangeList* tracking_changes);
    159 
    160   // Returns the local favicon url associated with |sync_favicon| if one exists
    161   // in |synced_favicons_|, else returns an invalid GURL.
    162   GURL GetLocalFaviconFromSyncedData(
    163       const syncer::SyncData& sync_favicon) const;
    164 
    165   // Merges |sync_favicon| into |synced_favicons_|, updating |local_changes|
    166   // with any changes that should be pushed to the sync processor.
    167   void MergeSyncFavicon(const syncer::SyncData& sync_favicon,
    168                         syncer::SyncChangeList* sync_changes);
    169 
    170   // Updates |synced_favicons_| with the favicon data from |sync_favicon|.
    171   void AddLocalFaviconFromSyncedData(const syncer::SyncData& sync_favicon);
    172 
    173   // Creates a SyncData object from the |type| data of |favicon_url|
    174   // from within |synced_favicons_|.
    175   syncer::SyncData CreateSyncDataFromLocalFavicon(
    176       syncer::ModelType type,
    177       const GURL& favicon_url) const;
    178 
    179   // Deletes all synced favicons corresponding with |favicon_urls| and pushes
    180   // the deletions to sync.
    181   void DeleteSyncedFavicons(const std::set<GURL>& favicon_urls);
    182 
    183   // Deletes the favicon pointed to by |favicon_iter| and appends the necessary
    184   // sync deletions to |image_changes| and |tracking_changes|.
    185   void DeleteSyncedFavicon(FaviconMap::iterator favicon_iter,
    186                            syncer::SyncChangeList* image_changes,
    187                            syncer::SyncChangeList* tracking_changes);
    188 
    189   // Locally drops the favicon pointed to by |favicon_iter|.
    190   void DropSyncedFavicon(FaviconMap::iterator favicon_iter);
    191 
    192   // For testing only.
    193   size_t NumFaviconsForTest() const;
    194   size_t NumTasksForTest() const;
    195 
    196   // Trask tracker for loading favicons.
    197   CancelableTaskTracker cancelable_task_tracker_;
    198 
    199   // Our actual cached favicon data.
    200   FaviconMap synced_favicons_;
    201 
    202   // An LRU ordering of the favicons comprising |synced_favicons_| (oldest to
    203   // newest).
    204   RecencySet recent_favicons_;
    205 
    206   // Our set of pending favicon loads, indexed by page url.
    207   PageTaskMap page_task_map_;
    208 
    209   // Map of page and associated favicon urls.
    210   PageFaviconMap page_favicon_map_;
    211 
    212   Profile* profile_;
    213 
    214   // TODO(zea): consider creating a favicon handler here for fetching unsynced
    215   // favicons from the web.
    216 
    217   // Weak pointer factory for favicon loads.
    218   base::WeakPtrFactory<FaviconCache> weak_ptr_factory_;
    219 
    220   scoped_ptr<syncer::SyncChangeProcessor> favicon_images_sync_processor_;
    221   scoped_ptr<syncer::SyncChangeProcessor> favicon_tracking_sync_processor_;
    222 
    223   // For listening to history deletions.
    224   content::NotificationRegistrar notification_registrar_;
    225 
    226   // Maximum number of favicons to sync. 0 means no limit.
    227   const size_t max_sync_favicon_limit_;
    228 
    229   DISALLOW_COPY_AND_ASSIGN(FaviconCache);
    230 };
    231 
    232 }  // namespace browser_sync
    233 
    234 #endif  // CHROME_BROWSER_SYNC_GLUE_FAVICON_CACHE_H_
    235