Chromium Code Reviews| Index: chrome/browser/sync/glue/favicon_cache.cc |
| diff --git a/chrome/browser/sync/glue/favicon_cache.cc b/chrome/browser/sync/glue/favicon_cache.cc |
| index a9b3fa042604f6c9eb91a6c9bbe1a3ae1d476392..72b599af9610d74791829f5dac9155ee3e4cafa8 100644 |
| --- a/chrome/browser/sync/glue/favicon_cache.cc |
| +++ b/chrome/browser/sync/glue/favicon_cache.cc |
| @@ -52,6 +52,21 @@ struct SyncedFaviconInfo { |
| DISALLOW_COPY_AND_ASSIGN(SyncedFaviconInfo); |
| }; |
| +// Information for handling local favicon updates. Used in |
| +// OnFaviconDataAvailable. |
| +struct LocalFaviconUpdateInfo { |
| + LocalFaviconUpdateInfo() |
| + : new_image(false), |
| + new_tracking(false), |
| + image_needs_rewrite(false), |
| + favicon_info(NULL) {} |
| + |
| + bool new_image; |
| + bool new_tracking; |
| + bool image_needs_rewrite; |
| + SyncedFaviconInfo* favicon_info; |
| +}; |
| + |
| namespace { |
| // Maximum number of favicons to keep in memory (0 means no limit). |
| @@ -187,6 +202,16 @@ bool UpdateFaviconFromBitmapResult( |
| } |
| } |
| +bool FaviconInfoHasImages(const SyncedFaviconInfo& favicon_info) { |
| + return favicon_info.bitmap_data[SIZE_16].bitmap_data.get() || |
| + favicon_info.bitmap_data[SIZE_32].bitmap_data.get() || |
| + favicon_info.bitmap_data[SIZE_64].bitmap_data.get(); |
| +} |
| + |
| +bool FaviconInfoHasTracking(const SyncedFaviconInfo& favicon_info) { |
| + return !favicon_info.last_visit_time.is_null(); |
| +} |
| + |
| } // namespace |
| FaviconCacheObserver::~FaviconCacheObserver() {} |
| @@ -325,11 +350,6 @@ syncer::SyncError FaviconCache::ProcessSyncChanges( |
| } else { |
| DVLOG(1) << "Deleting favicon at " << favicon_url.spec(); |
| DropSyncedFavicon(favicon_iter); |
| - // TODO(zea): it's possible that we'll receive a deletion for an image, |
| - // but not a tracking data, or vice versa, resulting in an orphan |
| - // favicon node in one of the types. We should track how often this |
| - // happens, and if it becomes a problem delete each part individually |
| - // from the local model. |
| } |
| } else if (iter->change_type() == syncer::SyncChange::ACTION_UPDATE || |
| iter->change_type() == syncer::SyncChange::ACTION_ADD) { |
| @@ -387,7 +407,7 @@ void FaviconCache::OnPageFaviconUpdated(const GURL& page_url) { |
| << ": " << icon_iter->second->favicon_url.spec(); |
| UpdateFaviconVisitTime(icon_iter->second->favicon_url, base::Time::Now()); |
| UpdateSyncState(icon_iter->second->favicon_url, |
| - SYNC_TRACKING, |
| + syncer::SyncChange::ACTION_INVALID, |
| syncer::SyncChange::ACTION_UPDATE); |
| return; |
| } |
| @@ -431,8 +451,11 @@ void FaviconCache::OnFaviconVisited(const GURL& page_url, |
| page_favicon_map_[page_url] = favicon_url; |
| UpdateFaviconVisitTime(favicon_url, base::Time::Now()); |
| UpdateSyncState(favicon_url, |
| - SYNC_TRACKING, |
| - syncer::SyncChange::ACTION_UPDATE); |
| + syncer::SyncChange::ACTION_INVALID, |
| + (FaviconInfoHasTracking( |
| + *synced_favicons_.find(favicon_url)->second) ? |
| + syncer::SyncChange::ACTION_UPDATE : |
| + syncer::SyncChange::ACTION_ADD)); |
| } |
| bool FaviconCache::GetSyncedFaviconForFaviconURL( |
| @@ -517,11 +540,15 @@ void FaviconCache::OnReceivedSyncFaviconImpl( |
| // We assume legacy favicons are 16x16. |
| favicon_info->bitmap_data[SIZE_16].pixel_size.set_width(16); |
| favicon_info->bitmap_data[SIZE_16].pixel_size.set_height(16); |
| - UpdateFaviconVisitTime(icon_url, syncer::ProtoTimeToTime(visit_time_ms)); |
| + bool added_tracking = !FaviconInfoHasTracking(*favicon_info); |
| + UpdateFaviconVisitTime(icon_url, |
| + syncer::ProtoTimeToTime(visit_time_ms)); |
| UpdateSyncState(icon_url, |
| - SYNC_BOTH, |
| - syncer::SyncChange::ACTION_ADD); |
| + syncer::SyncChange::ACTION_ADD, |
| + (added_tracking ? |
| + syncer::SyncChange::ACTION_ADD : |
| + syncer::SyncChange::ACTION_UPDATE)); |
| } |
| void FaviconCache::SetLegacyDelegate(FaviconCacheObserver* observer) { |
| @@ -594,7 +621,7 @@ void FaviconCache::OnFaviconDataAvailable( |
| } |
| base::Time now = base::Time::Now(); |
| - std::set<SyncedFaviconInfo*> favicon_updates; |
| + std::map<GURL, LocalFaviconUpdateInfo> favicon_updates; |
| for (size_t i = 0; i < bitmap_results.size(); ++i) { |
| const history::FaviconBitmapResult& bitmap_result = bitmap_results[i]; |
| GURL favicon_url = bitmap_result.icon_url; |
| @@ -605,15 +632,19 @@ void FaviconCache::OnFaviconDataAvailable( |
| if (!favicon_info) |
| return; // We reached the in-memory limit. |
| - if (!UpdateFaviconFromBitmapResult(bitmap_result, favicon_info)) |
| - continue; // Invalid favicon or no change. |
| - |
| - favicon_updates.insert(favicon_info); |
| + favicon_updates[favicon_url].new_image |= |
| + !FaviconInfoHasImages(*favicon_info); |
| + favicon_updates[favicon_url].new_tracking |= |
| + !FaviconInfoHasTracking(*favicon_info); |
| + favicon_updates[favicon_url].image_needs_rewrite |= |
| + UpdateFaviconFromBitmapResult(bitmap_result, favicon_info); |
| + favicon_updates[favicon_url].favicon_info = favicon_info; |
| } |
| - for (std::set<SyncedFaviconInfo*>::iterator iter = favicon_updates.begin(); |
| - iter != favicon_updates.end(); ++iter) { |
| - SyncedFaviconInfo* favicon_info = *iter; |
| + for (std::map<GURL, LocalFaviconUpdateInfo>::const_iterator |
| + iter = favicon_updates.begin(); iter != favicon_updates.end(); |
| + ++iter) { |
| + SyncedFaviconInfo* favicon_info = iter->second.favicon_info; |
| const GURL& favicon_url = favicon_info->favicon_url; |
| if (!favicon_info->last_visit_time.is_null()) { |
| UMA_HISTOGRAM_COUNTS_10000( |
| @@ -621,11 +652,14 @@ void FaviconCache::OnFaviconDataAvailable( |
| (now - favicon_info->last_visit_time).InHours()); |
| } |
| favicon_info->received_local_update = true; |
| - bool added_favicon = favicon_info->last_visit_time.is_null(); |
| UpdateFaviconVisitTime(favicon_url, now); |
| UpdateSyncState(favicon_url, |
|
rlarocque
2013/04/04 23:29:07
I dislike ternary operators, and wouldn't use them
Nicolas Zea
2013/04/04 23:42:29
Haha, ok, done.
|
| - SYNC_BOTH, |
| - (added_favicon ? |
| + (iter->second.new_image ? |
| + syncer::SyncChange::ACTION_ADD : |
| + (iter->second.image_needs_rewrite ? |
| + syncer::SyncChange::ACTION_UPDATE : |
| + syncer::SyncChange::ACTION_INVALID)), |
| + (iter->second.new_tracking ? |
| syncer::SyncChange::ACTION_ADD : |
| syncer::SyncChange::ACTION_UPDATE)); |
| if (legacy_delegate_) |
| @@ -638,8 +672,8 @@ void FaviconCache::OnFaviconDataAvailable( |
| void FaviconCache::UpdateSyncState( |
| const GURL& icon_url, |
| - SyncState state_to_update, |
| - syncer::SyncChange::SyncChangeType change_type) { |
| + syncer::SyncChange::SyncChangeType image_change_type, |
| + syncer::SyncChange::SyncChangeType tracking_change_type) { |
| DCHECK(icon_url.is_valid()); |
| // It's possible that we'll receive a favicon update before both types |
| // have finished setting up. In that case ignore the update. |
| @@ -654,7 +688,7 @@ void FaviconCache::UpdateSyncState( |
| syncer::SyncChangeList image_changes; |
| syncer::SyncChangeList tracking_changes; |
| - if (state_to_update == SYNC_IMAGE || state_to_update == SYNC_BOTH) { |
| + if (image_change_type != syncer::SyncChange::ACTION_INVALID) { |
| sync_pb::EntitySpecifics new_specifics; |
| sync_pb::FaviconImageSpecifics* image_specifics = |
| new_specifics.mutable_favicon_image(); |
| @@ -662,13 +696,13 @@ void FaviconCache::UpdateSyncState( |
| image_changes.push_back( |
| syncer::SyncChange(FROM_HERE, |
| - change_type, |
| + image_change_type, |
| syncer::SyncData::CreateLocalData( |
| icon_url.spec(), |
| icon_url.spec(), |
| new_specifics))); |
| } |
| - if (state_to_update == SYNC_TRACKING || state_to_update == SYNC_BOTH) { |
| + if (tracking_change_type != syncer::SyncChange::ACTION_INVALID) { |
| sync_pb::EntitySpecifics new_specifics; |
| sync_pb::FaviconTrackingSpecifics* tracking_specifics = |
| new_specifics.mutable_favicon_tracking(); |
| @@ -676,7 +710,7 @@ void FaviconCache::UpdateSyncState( |
| tracking_changes.push_back( |
| syncer::SyncChange(FROM_HERE, |
| - change_type, |
| + tracking_change_type, |
| syncer::SyncData::CreateLocalData( |
| icon_url.spec(), |
| icon_url.spec(), |