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.
5 #ifndef COMPONENTS_SYNC_DRIVER_FAVICON_CACHE_H_
6 #define COMPONENTS_SYNC_DRIVER_FAVICON_CACHE_H_
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 "base/scoped_observer.h"
19 #include "base/task/cancelable_task_tracker.h"
20 #include "components/history/core/browser/history_service_observer.h"
21 #include "components/history/core/browser/history_types.h"
22 #include "components/sessions/session_id.h"
23 #include "sync/api/sync_change.h"
24 #include "sync/api/sync_error_factory.h"
25 #include "sync/api/syncable_service.h"
29 struct FaviconRawBitmapResult
;
40 namespace browser_sync
{
50 struct SyncedFaviconInfo
;
52 // Encapsulates the logic for loading and storing synced favicons.
53 // TODO(zea): make this a KeyedService.
54 class FaviconCache
: public syncer::SyncableService
,
55 public history::HistoryServiceObserver
{
57 FaviconCache(favicon::FaviconService
* favicon_service
,
58 history::HistoryService
* history_service
,
59 int max_sync_favicon_limit
);
60 ~FaviconCache() override
;
62 // SyncableService implementation.
63 syncer::SyncMergeResult
MergeDataAndStartSyncing(
64 syncer::ModelType type
,
65 const syncer::SyncDataList
& initial_sync_data
,
66 scoped_ptr
<syncer::SyncChangeProcessor
> sync_processor
,
67 scoped_ptr
<syncer::SyncErrorFactory
> error_handler
) override
;
68 void StopSyncing(syncer::ModelType type
) override
;
69 syncer::SyncDataList
GetAllSyncData(syncer::ModelType type
) const override
;
70 syncer::SyncError
ProcessSyncChanges(
71 const tracked_objects::Location
& from_here
,
72 const syncer::SyncChangeList
& change_list
) override
;
74 // If a valid favicon for the icon at |favicon_url| is found, fills
75 // |favicon_png| with the png-encoded image and returns true. Else, returns
77 bool GetSyncedFaviconForFaviconURL(
78 const GURL
& favicon_url
,
79 scoped_refptr
<base::RefCountedMemory
>* favicon_png
) const;
81 // If a valid favicon for the icon associated with |page_url| is found, fills
82 // |favicon_png| with the png-encoded image and returns true. Else, returns
84 bool GetSyncedFaviconForPageURL(
86 scoped_refptr
<base::RefCountedMemory
>* favicon_png
) const;
88 // Load the favicon for |page_url|. Will create a new sync node or update
89 // an existing one as necessary, and set the last visit time to the current
90 // time. Only those favicon types defined in SupportedFaviconTypes will be
92 void OnPageFaviconUpdated(const GURL
& page_url
);
94 // Update the visit count for the favicon associated with |favicon_url|.
95 // If no favicon exists associated with |favicon_url|, triggers a load
96 // for the favicon associated with |page_url|.
97 void OnFaviconVisited(const GURL
& page_url
, const GURL
& favicon_url
);
99 // Consume Session sync favicon data. Will not overwrite existing favicons.
100 // If |icon_bytes| is empty, only updates the page->favicon url mapping.
101 // Safe to call within a transaction.
102 void OnReceivedSyncFavicon(const GURL
& page_url
,
103 const GURL
& icon_url
,
104 const std::string
& icon_bytes
,
105 int64 visit_time_ms
);
108 friend class SyncFaviconCacheTest
;
109 FRIEND_TEST_ALL_PREFIXES(SyncFaviconCacheTest
, HistoryFullClear
);
110 FRIEND_TEST_ALL_PREFIXES(SyncFaviconCacheTest
, HistorySubsetClear
);
112 // Functor for ordering SyncedFaviconInfo objects by recency;
113 struct FaviconRecencyFunctor
{
114 bool operator()(const linked_ptr
<SyncedFaviconInfo
>& lhs
,
115 const linked_ptr
<SyncedFaviconInfo
>& rhs
) const;
119 // Map of favicon url to favicon image.
120 typedef std::map
<GURL
, linked_ptr
<SyncedFaviconInfo
> > FaviconMap
;
121 typedef std::set
<linked_ptr
<SyncedFaviconInfo
>,
122 FaviconRecencyFunctor
> RecencySet
;
123 // Map of page url to task id (for favicon loading).
124 typedef std::map
<GURL
, base::CancelableTaskTracker::TaskId
> PageTaskMap
;
125 // Map of page url to favicon url.
126 typedef std::map
<GURL
, GURL
> PageFaviconMap
;
128 // Helper method to perform OnReceivedSyncFavicon work without worrying about
129 // whether caller holds a sync transaction.
130 void OnReceivedSyncFaviconImpl(const GURL
& icon_url
,
131 const std::string
& icon_bytes
,
132 int64 visit_time_ms
);
134 // Callback method to store a tab's favicon into its sync node once it becomes
135 // available. Does nothing if no favicon data was available.
136 void OnFaviconDataAvailable(
137 const GURL
& page_url
,
138 const std::vector
<favicon_base::FaviconRawBitmapResult
>& bitmap_result
);
140 // Helper method to update the sync state of the favicon at |icon_url|. If
141 // either |image_change_type| or |tracking_change_type| is ACTION_INVALID,
142 // the corresponding datatype won't be updated.
143 // Note: should only be called after both FAVICON_IMAGES and FAVICON_TRACKING
144 // have been successfully set up.
145 void UpdateSyncState(const GURL
& icon_url
,
146 syncer::SyncChange::SyncChangeType image_change_type
,
147 syncer::SyncChange::SyncChangeType tracking_change_type
);
149 // Helper method to get favicon info from |synced_favicons_|. If no info
150 // exists for |icon_url|, creates a new SyncedFaviconInfo in both
151 // |synced_favicons_| and |recent_favicons_| and returns it.
152 SyncedFaviconInfo
* GetFaviconInfo(const GURL
& icon_url
);
154 // Updates the last visit time for the favicon at |icon_url| to |time| (and
155 // correspondly updates position in |recent_favicons_|.
156 void UpdateFaviconVisitTime(const GURL
& icon_url
, base::Time time
);
158 // Expiration method. Looks through |recent_favicons_| to find any favicons
159 // that should be expired in order to maintain the sync favicon limit,
160 // appending deletions to |image_changes| and |tracking_changes| as necessary.
161 void ExpireFaviconsIfNecessary(syncer::SyncChangeList
* image_changes
,
162 syncer::SyncChangeList
* tracking_changes
);
164 // Returns the local favicon url associated with |sync_favicon| if one exists
165 // in |synced_favicons_|, else returns an invalid GURL.
166 GURL
GetLocalFaviconFromSyncedData(
167 const syncer::SyncData
& sync_favicon
) const;
169 // Merges |sync_favicon| into |synced_favicons_|, updating |local_changes|
170 // with any changes that should be pushed to the sync processor.
171 void MergeSyncFavicon(const syncer::SyncData
& sync_favicon
,
172 syncer::SyncChangeList
* sync_changes
);
174 // Updates |synced_favicons_| with the favicon data from |sync_favicon|.
175 void AddLocalFaviconFromSyncedData(const syncer::SyncData
& sync_favicon
);
177 // Creates a SyncData object from the |type| data of |favicon_url|
178 // from within |synced_favicons_|.
179 syncer::SyncData
CreateSyncDataFromLocalFavicon(
180 syncer::ModelType type
,
181 const GURL
& favicon_url
) const;
183 // Deletes all synced favicons corresponding with |favicon_urls| and pushes
184 // the deletions to sync.
185 void DeleteSyncedFavicons(const std::set
<GURL
>& favicon_urls
);
187 // Deletes the favicon pointed to by |favicon_iter| and appends the necessary
188 // sync deletions to |image_changes| and |tracking_changes|.
189 void DeleteSyncedFavicon(FaviconMap::iterator favicon_iter
,
190 syncer::SyncChangeList
* image_changes
,
191 syncer::SyncChangeList
* tracking_changes
);
193 // Locally drops the favicon pointed to by |favicon_iter|.
194 void DropSyncedFavicon(FaviconMap::iterator favicon_iter
);
196 // Only drops the data associated with |type| of |favicon_iter|.
197 void DropPartialFavicon(FaviconMap::iterator favicon_iter
,
198 syncer::ModelType type
);
201 size_t NumFaviconsForTest() const;
202 size_t NumTasksForTest() const;
204 // history::HistoryServiceObserver:
205 void OnURLsDeleted(history::HistoryService
* history_service
,
208 const history::URLRows
& deleted_rows
,
209 const std::set
<GURL
>& favicon_urls
) override
;
211 favicon::FaviconService
* favicon_service_
;
213 // Trask tracker for loading favicons.
214 base::CancelableTaskTracker cancelable_task_tracker_
;
216 // Our actual cached favicon data.
217 FaviconMap synced_favicons_
;
219 // An LRU ordering of the favicons comprising |synced_favicons_| (oldest to
221 RecencySet recent_favicons_
;
223 // Our set of pending favicon loads, indexed by page url.
224 PageTaskMap page_task_map_
;
226 // Map of page and associated favicon urls.
227 PageFaviconMap page_favicon_map_
;
229 // TODO(zea): consider creating a favicon handler here for fetching unsynced
230 // favicons from the web.
232 scoped_ptr
<syncer::SyncChangeProcessor
> favicon_images_sync_processor_
;
233 scoped_ptr
<syncer::SyncChangeProcessor
> favicon_tracking_sync_processor_
;
235 // Maximum number of favicons to sync. 0 means no limit.
236 const size_t max_sync_favicon_limit_
;
238 ScopedObserver
<history::HistoryService
, history::HistoryServiceObserver
>
239 history_service_observer_
;
241 // Weak pointer factory for favicon loads.
242 base::WeakPtrFactory
<FaviconCache
> weak_ptr_factory_
;
244 DISALLOW_COPY_AND_ASSIGN(FaviconCache
);
247 } // namespace browser_sync
249 #endif // COMPONENTS_SYNC_DRIVER_FAVICON_CACHE_H_