// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_SYNC_SESSIONS_FAVICON_CACHE_H_ #define COMPONENTS_SYNC_SESSIONS_FAVICON_CACHE_H_ #include #include #include #include #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" #include "base/task/cancelable_task_tracker.h" #include "components/history/core/browser/history_service_observer.h" #include "components/history/core/browser/history_types.h" #include "components/sessions/core/session_id.h" #include "sync/api/sync_change.h" #include "sync/api/sync_error_factory.h" #include "sync/api/syncable_service.h" #include "url/gurl.h" namespace chrome { struct FaviconRawBitmapResult; } namespace favicon { class FaviconService; } namespace history { class HistoryService; } namespace browser_sync { enum IconSize { SIZE_INVALID, SIZE_16, SIZE_32, SIZE_64, NUM_SIZES }; struct SyncedFaviconInfo; // Encapsulates the logic for loading and storing synced favicons. // TODO(zea): make this a KeyedService. class FaviconCache : public syncer::SyncableService, public history::HistoryServiceObserver { public: FaviconCache(favicon::FaviconService* favicon_service, history::HistoryService* history_service, int max_sync_favicon_limit); ~FaviconCache() override; // SyncableService implementation. syncer::SyncMergeResult MergeDataAndStartSyncing( syncer::ModelType type, const syncer::SyncDataList& initial_sync_data, scoped_ptr sync_processor, scoped_ptr error_handler) override; void StopSyncing(syncer::ModelType type) override; syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override; syncer::SyncError ProcessSyncChanges( const tracked_objects::Location& from_here, const syncer::SyncChangeList& change_list) override; // If a valid favicon for the icon at |favicon_url| is found, fills // |favicon_png| with the png-encoded image and returns true. Else, returns // false. bool GetSyncedFaviconForFaviconURL( const GURL& favicon_url, scoped_refptr* favicon_png) const; // If a valid favicon for the icon associated with |page_url| is found, fills // |favicon_png| with the png-encoded image and returns true. Else, returns // false. bool GetSyncedFaviconForPageURL( const GURL& page_url, scoped_refptr* favicon_png) const; // Load the favicon for |page_url|. Will create a new sync node or update // an existing one as necessary, and set the last visit time to the current // time. Only those favicon types defined in SupportedFaviconTypes will be // synced. void OnPageFaviconUpdated(const GURL& page_url); // Update the visit count for the favicon associated with |favicon_url|. // If no favicon exists associated with |favicon_url|, triggers a load // for the favicon associated with |page_url|. void OnFaviconVisited(const GURL& page_url, const GURL& favicon_url); // Consume Session sync favicon data. Will not overwrite existing favicons. // If |icon_bytes| is empty, only updates the page->favicon url mapping. // Safe to call within a transaction. void OnReceivedSyncFavicon(const GURL& page_url, const GURL& icon_url, const std::string& icon_bytes, int64 visit_time_ms); private: friend class SyncFaviconCacheTest; FRIEND_TEST_ALL_PREFIXES(SyncFaviconCacheTest, HistoryFullClear); FRIEND_TEST_ALL_PREFIXES(SyncFaviconCacheTest, HistorySubsetClear); // Functor for ordering SyncedFaviconInfo objects by recency; struct FaviconRecencyFunctor { bool operator()(const linked_ptr& lhs, const linked_ptr& rhs) const; }; // Map of favicon url to favicon image. typedef std::map > FaviconMap; typedef std::set, FaviconRecencyFunctor> RecencySet; // Map of page url to task id (for favicon loading). typedef std::map PageTaskMap; // Map of page url to favicon url. typedef std::map PageFaviconMap; // Helper method to perform OnReceivedSyncFavicon work without worrying about // whether caller holds a sync transaction. void OnReceivedSyncFaviconImpl(const GURL& icon_url, const std::string& icon_bytes, int64 visit_time_ms); // Callback method to store a tab's favicon into its sync node once it becomes // available. Does nothing if no favicon data was available. void OnFaviconDataAvailable( const GURL& page_url, const std::vector& bitmap_result); // Helper method to update the sync state of the favicon at |icon_url|. If // either |image_change_type| or |tracking_change_type| is ACTION_INVALID, // the corresponding datatype won't be updated. // Note: should only be called after both FAVICON_IMAGES and FAVICON_TRACKING // have been successfully set up. void UpdateSyncState(const GURL& icon_url, syncer::SyncChange::SyncChangeType image_change_type, syncer::SyncChange::SyncChangeType tracking_change_type); // Helper method to get favicon info from |synced_favicons_|. If no info // exists for |icon_url|, creates a new SyncedFaviconInfo in both // |synced_favicons_| and |recent_favicons_| and returns it. SyncedFaviconInfo* GetFaviconInfo(const GURL& icon_url); // Updates the last visit time for the favicon at |icon_url| to |time| (and // correspondly updates position in |recent_favicons_|. void UpdateFaviconVisitTime(const GURL& icon_url, base::Time time); // Expiration method. Looks through |recent_favicons_| to find any favicons // that should be expired in order to maintain the sync favicon limit, // appending deletions to |image_changes| and |tracking_changes| as necessary. void ExpireFaviconsIfNecessary(syncer::SyncChangeList* image_changes, syncer::SyncChangeList* tracking_changes); // Returns the local favicon url associated with |sync_favicon| if one exists // in |synced_favicons_|, else returns an invalid GURL. GURL GetLocalFaviconFromSyncedData( const syncer::SyncData& sync_favicon) const; // Merges |sync_favicon| into |synced_favicons_|, updating |local_changes| // with any changes that should be pushed to the sync processor. void MergeSyncFavicon(const syncer::SyncData& sync_favicon, syncer::SyncChangeList* sync_changes); // Updates |synced_favicons_| with the favicon data from |sync_favicon|. void AddLocalFaviconFromSyncedData(const syncer::SyncData& sync_favicon); // Creates a SyncData object from the |type| data of |favicon_url| // from within |synced_favicons_|. syncer::SyncData CreateSyncDataFromLocalFavicon( syncer::ModelType type, const GURL& favicon_url) const; // Deletes all synced favicons corresponding with |favicon_urls| and pushes // the deletions to sync. void DeleteSyncedFavicons(const std::set& favicon_urls); // Deletes the favicon pointed to by |favicon_iter| and appends the necessary // sync deletions to |image_changes| and |tracking_changes|. void DeleteSyncedFavicon(FaviconMap::iterator favicon_iter, syncer::SyncChangeList* image_changes, syncer::SyncChangeList* tracking_changes); // Locally drops the favicon pointed to by |favicon_iter|. void DropSyncedFavicon(FaviconMap::iterator favicon_iter); // Only drops the data associated with |type| of |favicon_iter|. void DropPartialFavicon(FaviconMap::iterator favicon_iter, syncer::ModelType type); // For testing only. size_t NumFaviconsForTest() const; size_t NumTasksForTest() const; // history::HistoryServiceObserver: void OnURLsDeleted(history::HistoryService* history_service, bool all_history, bool expired, const history::URLRows& deleted_rows, const std::set& favicon_urls) override; favicon::FaviconService* favicon_service_; // Trask tracker for loading favicons. base::CancelableTaskTracker cancelable_task_tracker_; // Our actual cached favicon data. FaviconMap synced_favicons_; // An LRU ordering of the favicons comprising |synced_favicons_| (oldest to // newest). RecencySet recent_favicons_; // Our set of pending favicon loads, indexed by page url. PageTaskMap page_task_map_; // Map of page and associated favicon urls. PageFaviconMap page_favicon_map_; // TODO(zea): consider creating a favicon handler here for fetching unsynced // favicons from the web. scoped_ptr favicon_images_sync_processor_; scoped_ptr favicon_tracking_sync_processor_; // Maximum number of favicons to sync. 0 means no limit. const size_t max_sync_favicon_limit_; ScopedObserver history_service_observer_; // Weak pointer factory for favicon loads. base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(FaviconCache); }; } // namespace browser_sync #endif // COMPONENTS_SYNC_SESSIONS_FAVICON_CACHE_H_