12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/glue/favicon_cache.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 79ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h" 97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_notifications.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_types.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_details.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_source.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/time.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/favicon_image_specifics.pb.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/favicon_tracking_specifics.pb.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/sync.pb.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/favicon_size.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace browser_sync { 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Synced favicon storage and tracking. 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Note: we don't use the favicon service for storing these because these 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// favicons are not necessarily associated with any local navigation, and 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// hence would not work with the current expiration logic. We have custom 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// expiration logic based on visit time/bookmark status/etc. 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// See crbug.com/122890. 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct SyncedFaviconInfo { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit SyncedFaviconInfo(const GURL& favicon_url) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : favicon_url(favicon_url), 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_bookmarked(false), 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) received_local_update(false) {} 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The actual favicon data. 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): don't keep around the actual data for locally sourced 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // favicons (UI can access those directly). 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconBitmapResult bitmap_data[NUM_SIZES]; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The URL this favicon was loaded from. 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL favicon_url; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Is the favicon for a bookmarked page? 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_bookmarked; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The last time a tab needed this favicon. 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note: Do not modify this directly! It should only be modified via 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // UpdateFaviconVisitTime(..). 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time last_visit_time; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Whether we've received a local update for this favicon since starting up. 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool received_local_update; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SyncedFaviconInfo); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Information for handling local favicon updates. Used in 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// OnFaviconDataAvailable. 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct LocalFaviconUpdateInfo { 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LocalFaviconUpdateInfo() 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : new_image(false), 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new_tracking(false), 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) image_needs_rewrite(false), 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_info(NULL) {} 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool new_image; 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool new_tracking; 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool image_needs_rewrite; 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SyncedFaviconInfo* favicon_info; 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum number of favicons to keep in memory (0 means no limit). 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kMaxFaviconsInMem = 0; 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum width/height resolution supported. 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaxFaviconResolution = 16; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns a mask of the supported favicon types. 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(zea): Supporting other favicons types will involve some work in the 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// favicon service and navigation controller. See crbug.com/181068. 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SupportedFaviconTypes() { 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return chrome::FAVICON; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the appropriate IconSize to use for a given gfx::Size pixel 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// dimensions. 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IconSize GetIconSizeBinFromBitmapResult(const gfx::Size& pixel_size) { 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int max_size = 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (pixel_size.width() > pixel_size.height() ? 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pixel_size.width() : pixel_size.height()); 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(zea): re-enable 64p and 32p resolutions once we support them. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (max_size > 64) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SIZE_INVALID; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else if (max_size > 32) 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return SIZE_INVALID; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else if (max_size > 16) 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return SIZE_INVALID; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SIZE_16; 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Helper for debug statements. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string IconSizeToString(IconSize icon_size) { 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (icon_size) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case SIZE_16: 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "16"; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case SIZE_32: 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "32"; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case SIZE_64: 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "64"; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "INVALID"; 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Extract the favicon url from either of the favicon types. 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GURL GetFaviconURLFromSpecifics(const sync_pb::EntitySpecifics& specifics) { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (specifics.has_favicon_tracking()) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GURL(specifics.favicon_tracking().favicon_url()); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GURL(specifics.favicon_image().favicon_url()); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Convert protobuf image data into a FaviconBitmapResult. 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)chrome::FaviconBitmapResult GetImageDataFromSpecifics( 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const sync_pb::FaviconData& favicon_data) { 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::RefCountedString* temp_string = 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new base::RefCountedString(); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) temp_string->data() = favicon_data.favicon(); 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconBitmapResult bitmap_result; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_result.bitmap_data = temp_string; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_result.pixel_size.set_height(favicon_data.height()); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_result.pixel_size.set_width(favicon_data.width()); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return bitmap_result; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Convert a FaviconBitmapResult into protobuf image data. 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FillSpecificsWithImageData( 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const chrome::FaviconBitmapResult& bitmap_result, 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconData* favicon_data) { 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!bitmap_result.bitmap_data.get()) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_data->set_height(bitmap_result.pixel_size.height()); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_data->set_width(bitmap_result.pixel_size.width()); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_data->set_favicon(bitmap_result.bitmap_data->front(), 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_result.bitmap_data->size()); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Build a FaviconImageSpecifics from a SyncedFaviconInfo. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BuildImageSpecifics( 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SyncedFaviconInfo* favicon_info, 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconImageSpecifics* image_specifics) { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_specifics->set_favicon_url(favicon_info->favicon_url.spec()); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FillSpecificsWithImageData(favicon_info->bitmap_data[SIZE_16], 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_specifics->mutable_favicon_web()); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): bring this back if we can handle the load. 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // FillSpecificsWithImageData(favicon_info->bitmap_data[SIZE_32], 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // image_specifics->mutable_favicon_web_32()); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // FillSpecificsWithImageData(favicon_info->bitmap_data[SIZE_64], 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // image_specifics->mutable_favicon_touch_64()); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Build a FaviconTrackingSpecifics from a SyncedFaviconInfo. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BuildTrackingSpecifics( 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SyncedFaviconInfo* favicon_info, 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconTrackingSpecifics* tracking_specifics) { 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracking_specifics->set_favicon_url(favicon_info->favicon_url.spec()); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracking_specifics->set_last_visit_time_ms( 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::TimeToProtoTime(favicon_info->last_visit_time)); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracking_specifics->set_is_bookmarked(favicon_info->is_bookmarked); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Updates |favicon_info| with the image data in |bitmap_result|. 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool UpdateFaviconFromBitmapResult( 17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const chrome::FaviconBitmapResult& bitmap_result, 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedFaviconInfo* favicon_info) { 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(favicon_info->favicon_url, bitmap_result.icon_url); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!bitmap_result.is_valid()) { 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Received invalid favicon at " << bitmap_result.icon_url.spec(); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IconSize icon_size = GetIconSizeBinFromBitmapResult( 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_result.pixel_size); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_size == SIZE_INVALID) { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Ignoring unsupported resolution " 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << bitmap_result.pixel_size.height() << "x" 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << bitmap_result.pixel_size.width(); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (!favicon_info->bitmap_data[icon_size].bitmap_data.get() || 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !favicon_info->received_local_update) { 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Storing " << IconSizeToString(icon_size) << "p" 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " favicon for " << favicon_info->favicon_url.spec() 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " with size " << bitmap_result.bitmap_data->size() 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " bytes."; 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->bitmap_data[icon_size] = bitmap_result; 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->received_local_update = true; 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We only allow updating the image data once per restart. 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(2) << "Ignoring local update for " << bitmap_result.icon_url.spec(); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool FaviconInfoHasImages(const SyncedFaviconInfo& favicon_info) { 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return favicon_info.bitmap_data[SIZE_16].bitmap_data.get() || 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_info.bitmap_data[SIZE_32].bitmap_data.get() || 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_info.bitmap_data[SIZE_64].bitmap_data.get(); 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool FaviconInfoHasTracking(const SyncedFaviconInfo& favicon_info) { 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return !favicon_info.last_visit_time.is_null(); 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool FaviconInfoHasValidTypeData(const SyncedFaviconInfo& favicon_info, 2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch syncer::ModelType type) { 2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (type == syncer::FAVICON_IMAGES) 2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return FaviconInfoHasImages(favicon_info); 2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch else if (type == syncer::FAVICON_TRACKING) 2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return FaviconInfoHasTracking(favicon_info); 2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch NOTREACHED(); 2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FaviconCache::FaviconCache(Profile* profile, int max_sync_favicon_limit) 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : profile_(profile), 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this), 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) max_sync_favicon_limit_(max_sync_favicon_limit) { 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) notification_registrar_.Add(this, 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::NOTIFICATION_HISTORY_URLS_DELETED, 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<Profile>(profile_)); 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "Setting favicon limit to " << max_sync_favicon_limit; 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FaviconCache::~FaviconCache() {} 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncMergeResult FaviconCache::MergeDataAndStartSyncing( 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ModelType type, 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncDataList& initial_sync_data, 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<syncer::SyncErrorFactory> error_handler) { 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING); 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (type == syncer::FAVICON_IMAGES) 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_images_sync_processor_ = sync_processor.Pass(); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_tracking_sync_processor_ = sync_processor.Pass(); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncMergeResult merge_result(type); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_num_items_before_association(synced_favicons_.size()); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<GURL> unsynced_favicon_urls; 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (FaviconMap::const_iterator iter = synced_favicons_.begin(); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != synced_favicons_.end(); ++iter) { 2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (FaviconInfoHasValidTypeData(*(iter->second), type)) 2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch unsynced_favicon_urls.insert(iter->first); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList local_changes; 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (syncer::SyncDataList::const_iterator iter = initial_sync_data.begin(); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != initial_sync_data.end(); ++iter) { 2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch GURL remote_url = GetFaviconURLFromSpecifics(iter->GetSpecifics()); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL favicon_url = GetLocalFaviconFromSyncedData(*iter); 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_url.is_valid()) { 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsynced_favicon_urls.erase(favicon_url); 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MergeSyncFavicon(*iter, &local_changes); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_num_items_modified( 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.num_items_modified() + 1); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddLocalFaviconFromSyncedData(*iter); 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_num_items_added(merge_result.num_items_added() + 1); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Rather than trigger a bunch of deletions when we set up sync, we drop 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // local favicons. Those pages that are currently open are likely to result in 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // loading new favicons/refreshing old favicons anyways, at which point 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // they'll be re-added and the appropriate synced favicons will be evicted. 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): implement a smarter ordering of the which favicons to drop. 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int available_favicons = max_sync_favicon_limit_ - initial_sync_data.size(); 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("Sync.FaviconsAvailableAtMerge", 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) available_favicons > 0); 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::set<GURL>::const_iterator iter = unsynced_favicon_urls.begin(); 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != unsynced_favicon_urls.end(); ++iter) { 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (available_favicons > 0) { 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_changes.push_back( 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::ACTION_ADD, 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateSyncDataFromLocalFavicon(type, *iter))); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) available_favicons--; 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconMap::iterator favicon_iter = synced_favicons_.find(*iter); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Dropping local favicon " 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << favicon_iter->second->favicon_url.spec(); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DropSyncedFavicon(favicon_iter); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_num_items_deleted(merge_result.num_items_deleted() + 1); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_COUNTS_10000("Sync.FaviconCount", synced_favicons_.size()); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_num_items_after_association(synced_favicons_.size()); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (type == syncer::FAVICON_IMAGES) { 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_error( 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_images_sync_processor_->ProcessSyncChanges(FROM_HERE, 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_changes)); 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) merge_result.set_error( 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_tracking_sync_processor_->ProcessSyncChanges(FROM_HERE, 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) local_changes)); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return merge_result; 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::StopSyncing(syncer::ModelType type) { 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_images_sync_processor_.reset(); 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_tracking_sync_processor_.reset(); 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cancelable_task_tracker_.TryCancelAll(); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_task_map_.clear(); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncDataList FaviconCache::GetAllSyncData(syncer::ModelType type) 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const { 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncDataList data_list; 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (FaviconMap::const_iterator iter = synced_favicons_.begin(); 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != synced_favicons_.end(); ++iter) { 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_list.push_back(CreateSyncDataFromLocalFavicon(type, iter->first)); 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return data_list; 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncError FaviconCache::ProcessSyncChanges( 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const tracked_objects::Location& from_here, 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncChangeList& change_list) { 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_images_sync_processor_.get() || 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !favicon_tracking_sync_processor_.get()) { 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return syncer::SyncError(FROM_HERE, 338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch syncer::SyncError::DATATYPE_ERROR, 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "One or both favicon types disabled.", 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) change_list[0].sync_data().GetDataType()); 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList new_changes; 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncError error; 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ModelType type = syncer::UNSPECIFIED; 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (syncer::SyncChangeList::const_iterator iter = change_list.begin(); 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != change_list.end(); ++iter) { 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) type = iter->sync_data().GetDataType(); 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING); 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL favicon_url = 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetFaviconURLFromSpecifics(iter->sync_data().GetSpecifics()); 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_url.is_valid()) { 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error.Reset(FROM_HERE, "Received invalid favicon url.", type); 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconMap::iterator favicon_iter = synced_favicons_.find(favicon_url); 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (iter->change_type() == syncer::SyncChange::ACTION_DELETE) { 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_iter == synced_favicons_.end()) { 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Two clients might wind up deleting different parts of the same 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // favicon, so ignore this. 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Deleting favicon at " << favicon_url.spec(); 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If we only have partial data for the favicon (which implies orphaned 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // nodes), delete the local favicon only if the type corresponds to the 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // partial data we have. If we do have orphaned nodes, we rely on the 367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // expiration logic to remove them eventually. 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (type == syncer::FAVICON_IMAGES && 369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FaviconInfoHasImages(*(favicon_iter->second)) && 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !FaviconInfoHasTracking(*(favicon_iter->second))) { 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DropSyncedFavicon(favicon_iter); 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (type == syncer::FAVICON_TRACKING && 373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !FaviconInfoHasImages(*(favicon_iter->second)) && 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FaviconInfoHasTracking(*(favicon_iter->second))) { 375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DropSyncedFavicon(favicon_iter); 376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Only delete the data for the modified type. 378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (type == syncer::FAVICON_TRACKING) { 379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) recent_favicons_.erase(favicon_iter->second); 380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_iter->second->last_visit_time = base::Time(); 381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_iter->second->is_bookmarked = false; 382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) recent_favicons_.insert(favicon_iter->second); 383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!FaviconInfoHasTracking(*(favicon_iter->second))); 3847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(FaviconInfoHasImages(*(favicon_iter->second))); 385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int i = 0; i < NUM_SIZES; ++i) { 387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_iter->second->bitmap_data[i] = 38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconBitmapResult(); 389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(FaviconInfoHasTracking(*(favicon_iter->second))); 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!FaviconInfoHasImages(*(favicon_iter->second))); 392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (iter->change_type() == syncer::SyncChange::ACTION_UPDATE || 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter->change_type() == syncer::SyncChange::ACTION_ADD) { 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Adds and updates are treated the same due to the lack of strong 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // consistency (it's possible we'll receive an update for a tracking info 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // before we've received the add for the image, and should handle both 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // gracefully). 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_iter == synced_favicons_.end()) { 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Adding favicon at " << favicon_url.spec(); 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddLocalFaviconFromSyncedData(iter->sync_data()); 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Updating favicon at " << favicon_url.spec(); 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MergeSyncFavicon(iter->sync_data(), &new_changes); 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error.Reset(FROM_HERE, "Invalid action received.", type); 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note: we deliberately do not expire favicons here. If we received new 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // favicons and are now over the limit, the next local favicon change will 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // trigger the necessary expiration. 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!error.IsSet() && !new_changes.empty()) { 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (type == syncer::FAVICON_IMAGES) { 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error = 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_images_sync_processor_->ProcessSyncChanges(FROM_HERE, 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_changes); 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error = 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_tracking_sync_processor_->ProcessSyncChanges(FROM_HERE, 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_changes); 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return error; 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::OnPageFaviconUpdated(const GURL& page_url) { 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(page_url.is_valid()); 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If a favicon load is already happening for this url, let it finish. 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (page_task_map_.find(page_url) != page_task_map_.end()) 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PageFaviconMap::const_iterator url_iter = page_favicon_map_.find(page_url); 440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (url_iter != page_favicon_map_.end()) { 441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FaviconMap::const_iterator icon_iter = 442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) synced_favicons_.find(url_iter->second); 443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(zea): consider what to do when only a subset of supported 444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // resolutions are available. 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (icon_iter != synced_favicons_.end() && 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) icon_iter->second->bitmap_data[SIZE_16].bitmap_data.get()) { 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(2) << "Using cached favicon url for " << page_url.spec() 448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << ": " << icon_iter->second->favicon_url.spec(); 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UpdateFaviconVisitTime(icon_iter->second->favicon_url, base::Time::Now()); 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UpdateSyncState(icon_iter->second->favicon_url, 451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_INVALID, 452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE); 453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Triggering favicon load for url " << page_url.spec(); 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!profile_) { 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_task_map_[page_url] = 0; // For testing only. 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconService* favicon_service = 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_service) 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): This appears to only fetch one favicon (best match based on 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // desired_size_in_dip). Figure out a way to fetch all favicons we support. 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See crbug.com/181068. 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelableTaskTracker::TaskId id = favicon_service->GetFaviconForURL( 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconService::FaviconForURLParams( 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) profile_, page_url, SupportedFaviconTypes(), kMaxFaviconResolution), 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&FaviconCache::OnFaviconDataAvailable, 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), page_url), 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_task_map_[page_url] = id; 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::OnFaviconVisited(const GURL& page_url, 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& favicon_url) { 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(page_url.is_valid()); 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_url.is_valid() || 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) synced_favicons_.find(favicon_url) == synced_favicons_.end()) { 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): consider triggering a favicon load if we have some but not 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // all desired resolutions? 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnPageFaviconUpdated(page_url); 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Associating " << page_url.spec() << " with favicon at " 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << favicon_url.spec() << " and marking visited."; 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_favicon_map_[page_url] = favicon_url; 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconVisitTime(favicon_url, base::Time::Now()); 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateSyncState(favicon_url, 495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_INVALID, 496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (FaviconInfoHasTracking( 497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *synced_favicons_.find(favicon_url)->second) ? 498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE : 499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_ADD)); 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FaviconCache::GetSyncedFaviconForFaviconURL( 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& favicon_url, 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::RefCountedMemory>* favicon_png) const { 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_url.is_valid()) 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconMap::const_iterator iter = synced_favicons_.find(favicon_url); 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("Sync.FaviconCacheLookupSucceeded", 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != synced_favicons_.end()); 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (iter == synced_favicons_.end()) 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): support getting other resolutions. 515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!iter->second->bitmap_data[SIZE_16].bitmap_data.get()) 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_png = iter->second->bitmap_data[SIZE_16].bitmap_data; 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FaviconCache::GetSyncedFaviconForPageURL( 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& page_url, 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::RefCountedMemory>* favicon_png) const { 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!page_url.is_valid()) 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PageFaviconMap::const_iterator iter = page_favicon_map_.find(page_url); 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (iter == page_favicon_map_.end()) 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetSyncedFaviconForFaviconURL(iter->second, favicon_png); 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::OnReceivedSyncFavicon(const GURL& page_url, 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url, 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& icon_bytes, 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 visit_time_ms) { 539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!icon_url.is_valid() || !page_url.is_valid() || icon_url.SchemeIs("data")) 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Associating " << page_url.spec() << " with favicon at " 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << icon_url.spec(); 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_favicon_map_[page_url] = icon_url; 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there is no actual image, it means there either is no synced 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // favicon, or it's on its way (race condition). 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): potentially trigger a favicon web download here (delayed?). 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_bytes.size() == 0) 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Post a task to do the actual association because this method may have been 552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // called while in a transaction. 55390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&FaviconCache::OnReceivedSyncFaviconImpl, 556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) icon_url, 558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) icon_bytes, 559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) visit_time_ms)); 560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FaviconCache::OnReceivedSyncFaviconImpl( 563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const GURL& icon_url, 564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& icon_bytes, 565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int64 visit_time_ms) { 566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If this favicon is already synced, do nothing else. 567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (synced_favicons_.find(icon_url) != synced_favicons_.end()) 568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Don't add any more favicons once we hit our in memory limit. 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): UMA this. 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (kMaxFaviconsInMem != 0 && synced_favicons_.size() > kMaxFaviconsInMem) 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedFaviconInfo* favicon_info = GetFaviconInfo(icon_url); 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_info) 5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; // We reached the in-memory limit. 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::RefCountedString* temp_string = new base::RefCountedString(); 5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) temp_string->data() = icon_bytes; 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->bitmap_data[SIZE_16].bitmap_data = temp_string; 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We assume legacy favicons are 16x16. 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->bitmap_data[SIZE_16].pixel_size.set_width(16); 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->bitmap_data[SIZE_16].pixel_size.set_height(16); 584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool added_tracking = !FaviconInfoHasTracking(*favicon_info); 585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UpdateFaviconVisitTime(icon_url, 586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::ProtoTimeToTime(visit_time_ms)); 587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UpdateSyncState(icon_url, 589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_ADD, 590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (added_tracking ? 591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_ADD : 592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE)); 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::Observe(int type, 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::NotificationSource& source, 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::NotificationDetails& details) { 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(type, chrome::NOTIFICATION_HISTORY_URLS_DELETED); 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Details<history::URLsDeletedDetails> deleted_details(details); 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We only care about actual user (or sync) deletions. 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (deleted_details->archived) 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!deleted_details->all_history) { 6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeleteSyncedFavicons(deleted_details->favicon_urls); 6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // All history was cleared: just delete all favicons. 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "History clear detected, deleting all synced favicons."; 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList image_deletions, tracking_deletions; 6147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch while (!synced_favicons_.empty()) { 6157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DeleteSyncedFavicon(synced_favicons_.begin(), 6167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &image_deletions, 6177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &tracking_deletions); 6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (favicon_images_sync_processor_.get()) { 6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_images_sync_processor_->ProcessSyncChanges(FROM_HERE, 6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_deletions); 6237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 6247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (favicon_tracking_sync_processor_.get()) { 6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_tracking_sync_processor_->ProcessSyncChanges(FROM_HERE, 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracking_deletions); 6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FaviconCache::FaviconRecencyFunctor::operator()( 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const linked_ptr<SyncedFaviconInfo>& lhs, 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const linked_ptr<SyncedFaviconInfo>& rhs) const { 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): incorporate bookmarked status here once we care about it. 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (lhs->last_visit_time < rhs->last_visit_time) 6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else if (lhs->last_visit_time == rhs->last_visit_time) 6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return lhs->favicon_url.spec() < rhs->favicon_url.spec(); 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::OnFaviconDataAvailable( 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& page_url, 64390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconBitmapResult>& bitmap_results) { 6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PageTaskMap::iterator page_iter = page_task_map_.find(page_url); 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (page_iter == page_task_map_.end()) 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_task_map_.erase(page_iter); 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_results.size() == 0) { 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Either the favicon isn't loaded yet or there is no valid favicon. 6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We already cleared the task id, so just return. 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Favicon load failed for page " << page_url.spec(); 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time now = base::Time::Now(); 657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::map<GURL, LocalFaviconUpdateInfo> favicon_updates; 6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_results.size(); ++i) { 65990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const chrome::FaviconBitmapResult& bitmap_result = bitmap_results[i]; 6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL favicon_url = bitmap_result.icon_url; 661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!favicon_url.is_valid() || favicon_url.SchemeIs("data")) 6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; // Can happen if the page is still loading. 6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedFaviconInfo* favicon_info = GetFaviconInfo(favicon_url); 6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_info) 6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; // We reached the in-memory limit. 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_updates[favicon_url].new_image |= 669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !FaviconInfoHasImages(*favicon_info); 670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_updates[favicon_url].new_tracking |= 671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !FaviconInfoHasTracking(*favicon_info); 672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_updates[favicon_url].image_needs_rewrite |= 673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UpdateFaviconFromBitmapResult(bitmap_result, favicon_info); 674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_updates[favicon_url].favicon_info = favicon_info; 6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (std::map<GURL, LocalFaviconUpdateInfo>::const_iterator 678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) iter = favicon_updates.begin(); iter != favicon_updates.end(); 679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++iter) { 680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SyncedFaviconInfo* favicon_info = iter->second.favicon_info; 6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& favicon_url = favicon_info->favicon_url; 6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_info->last_visit_time.is_null()) { 6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_COUNTS_10000( 6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Sync.FaviconVisitPeriod", 6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (now - favicon_info->last_visit_time).InHours()); 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->received_local_update = true; 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconVisitTime(favicon_url, now); 689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::SyncChangeType image_change = 691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_INVALID; 692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (iter->second.new_image) 693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) image_change = syncer::SyncChange::ACTION_ADD; 694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else if (iter->second.image_needs_rewrite) 695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) image_change = syncer::SyncChange::ACTION_UPDATE; 696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::SyncChangeType tracking_change = 697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE; 698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (iter->second.new_tracking) 699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tracking_change = syncer::SyncChange::ACTION_ADD; 700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UpdateSyncState(favicon_url, image_change, tracking_change); 7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): support multiple favicon urls per page. 7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_favicon_map_[page_url] = favicon_url; 7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::UpdateSyncState( 7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url, 709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::SyncChangeType image_change_type, 710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::SyncChangeType tracking_change_type) { 7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(icon_url.is_valid()); 7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It's possible that we'll receive a favicon update before both types 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // have finished setting up. In that case ignore the update. 7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): consider tracking these skipped updates somehow? 7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_images_sync_processor_.get() || 7167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch !favicon_tracking_sync_processor_.get()) { 7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 7187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconMap::const_iterator iter = synced_favicons_.find(icon_url); 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(iter != synced_favicons_.end()); 7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SyncedFaviconInfo* favicon_info = iter->second.get(); 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList image_changes; 7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList tracking_changes; 726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (image_change_type != syncer::SyncChange::ACTION_INVALID) { 7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::EntitySpecifics new_specifics; 7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconImageSpecifics* image_specifics = 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_specifics.mutable_favicon_image(); 7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BuildImageSpecifics(favicon_info, image_specifics); 7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_changes.push_back( 7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) image_change_type, 7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData::CreateLocalData( 7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url.spec(), 7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url.spec(), 7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_specifics))); 7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (tracking_change_type != syncer::SyncChange::ACTION_INVALID) { 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::EntitySpecifics new_specifics; 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconTrackingSpecifics* tracking_specifics = 7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_specifics.mutable_favicon_tracking(); 7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BuildTrackingSpecifics(favicon_info, tracking_specifics); 7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracking_changes.push_back( 7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tracking_change_type, 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData::CreateLocalData( 7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url.spec(), 7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url.spec(), 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_specifics))); 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExpireFaviconsIfNecessary(&image_changes, &tracking_changes); 7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!image_changes.empty()) { 7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_images_sync_processor_->ProcessSyncChanges(FROM_HERE, 7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_changes); 7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!tracking_changes.empty()) { 7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_tracking_sync_processor_->ProcessSyncChanges(FROM_HERE, 7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracking_changes); 7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyncedFaviconInfo* FaviconCache::GetFaviconInfo( 7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url) { 7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size()); 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (synced_favicons_.count(icon_url) != 0) 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return synced_favicons_[icon_url].get(); 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): implement in-memory eviction. 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Adding favicon info for " << icon_url.spec(); 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedFaviconInfo* favicon_info = new SyncedFaviconInfo(icon_url); 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) synced_favicons_[icon_url] = make_linked_ptr(favicon_info); 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recent_favicons_.insert(synced_favicons_[icon_url]); 7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size()); 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return favicon_info; 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::UpdateFaviconVisitTime(const GURL& icon_url, 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time time) { 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size()); 7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconMap::const_iterator iter = synced_favicons_.find(icon_url); 7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(iter != synced_favicons_.end()); 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (iter->second->last_visit_time >= time) 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Erase, update the time, then re-insert to maintain ordering. 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recent_favicons_.erase(iter->second); 789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "Updating " << icon_url.spec() << " visit time to " 790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << syncer::GetTimeDebugString(time); 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter->second->last_visit_time = time; 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recent_favicons_.insert(iter->second); 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (VLOG_IS_ON(2)) { 7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (RecencySet::const_iterator iter = recent_favicons_.begin(); 7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != recent_favicons_.end(); ++iter) { 797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(2) << "Favicon " << iter->get()->favicon_url.spec() << ": " 798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << syncer::GetTimeDebugString(iter->get()->last_visit_time); 7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size()); 8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::ExpireFaviconsIfNecessary( 8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList* image_changes, 8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList* tracking_changes) { 8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size()); 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): once we have in-memory eviction, we'll need to track sync 8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // favicon count separately from the synced_favicons_/recent_favicons_. 8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Iterate until we've removed the necessary amount. |recent_favicons_| is 8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // already in recency order, so just start from the beginning. 8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(zea): to reduce thrashing, consider removing more than the minimum. 8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (recent_favicons_.size() > max_sync_favicon_limit_) { 8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) linked_ptr<SyncedFaviconInfo> candidate = *recent_favicons_.begin(); 8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Expiring favicon " << candidate->favicon_url.spec(); 8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeleteSyncedFavicon(synced_favicons_.find(candidate->favicon_url), 8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_changes, 8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracking_changes); 8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size()); 8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GURL FaviconCache::GetLocalFaviconFromSyncedData( 8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncData& sync_favicon) const { 8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ModelType type = sync_favicon.GetDataType(); 8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING); 8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL favicon_url = GetFaviconURLFromSpecifics(sync_favicon.GetSpecifics()); 8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (synced_favicons_.count(favicon_url) > 0 ? favicon_url : GURL()); 8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::MergeSyncFavicon(const syncer::SyncData& sync_favicon, 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList* sync_changes) { 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ModelType type = sync_favicon.GetDataType(); 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING); 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::EntitySpecifics new_specifics; 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL favicon_url = GetFaviconURLFromSpecifics(sync_favicon.GetSpecifics()); 8387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch FaviconMap::const_iterator iter = synced_favicons_.find(favicon_url); 8397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(iter != synced_favicons_.end()); 8407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SyncedFaviconInfo* favicon_info = iter->second.get(); 8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (type == syncer::FAVICON_IMAGES) { 8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconImageSpecifics image_specifics = 8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_favicon.GetSpecifics().favicon_image(); 8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remote image data always clobbers local image data. 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool needs_update = false; 8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_specifics.has_favicon_web()) { 8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->bitmap_data[SIZE_16] = GetImageDataFromSpecifics( 8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_specifics.favicon_web()); 850868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (favicon_info->bitmap_data[SIZE_16].bitmap_data.get()) { 8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) needs_update = true; 8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_specifics.has_favicon_web_32()) { 8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->bitmap_data[SIZE_32] = GetImageDataFromSpecifics( 8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_specifics.favicon_web_32()); 856868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (favicon_info->bitmap_data[SIZE_32].bitmap_data.get()) { 8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) needs_update = true; 8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_specifics.has_favicon_touch_64()) { 8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->bitmap_data[SIZE_64] = GetImageDataFromSpecifics( 8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_specifics.favicon_touch_64()); 862868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (favicon_info->bitmap_data[SIZE_64].bitmap_data.get()) { 8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) needs_update = true; 8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (needs_update) 8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BuildImageSpecifics(favicon_info, new_specifics.mutable_favicon_image()); 8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconTrackingSpecifics tracking_specifics = 8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_favicon.GetSpecifics().favicon_tracking(); 8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Tracking data is merged, such that bookmark data is the logical OR 8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of the two, and last visit time is the most recent. 8747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 8757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Time last_visit = syncer::ProtoTimeToTime( 8767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch tracking_specifics.last_visit_time_ms()); 8777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Due to crbug.com/258196, there are tracking nodes out there with 8787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // null visit times. If this is one of those, artificially make it a valid 8797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // visit time, so we know the node exists and update it properly on the next 8807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // real visit. 8817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (last_visit.is_null()) 8827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch last_visit = last_visit + base::TimeDelta::FromMilliseconds(1); 8837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UpdateFaviconVisitTime(favicon_url, last_visit); 8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->is_bookmarked = (favicon_info->is_bookmarked || 8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracking_specifics.is_bookmarked()); 8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (syncer::TimeToProtoTime(favicon_info->last_visit_time) != 8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracking_specifics.last_visit_time_ms() || 8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->is_bookmarked != tracking_specifics.is_bookmarked()) { 8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BuildTrackingSpecifics(favicon_info, 8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_specifics.mutable_favicon_tracking()); 8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(!favicon_info->last_visit_time.is_null()); 8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_specifics.has_favicon_image() || 8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_specifics.has_favicon_tracking()) { 8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_changes->push_back(syncer::SyncChange( 8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChange::ACTION_UPDATE, 9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData::CreateLocalData(favicon_url.spec(), 9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_url.spec(), 9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_specifics))); 9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::AddLocalFaviconFromSyncedData( 9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const syncer::SyncData& sync_favicon) { 9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ModelType type = sync_favicon.GetDataType(); 9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING); 9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (type == syncer::FAVICON_IMAGES) { 9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconImageSpecifics image_specifics = 9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_favicon.GetSpecifics().favicon_image(); 9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL favicon_url = GURL(image_specifics.favicon_url()); 9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(favicon_url.is_valid()); 9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!synced_favicons_.count(favicon_url)); 9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedFaviconInfo* favicon_info = GetFaviconInfo(favicon_url); 9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_info) 9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; // We reached the in-memory limit. 9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_specifics.has_favicon_web()) { 9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->bitmap_data[SIZE_16] = GetImageDataFromSpecifics( 9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_specifics.favicon_web()); 9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_specifics.has_favicon_web_32()) { 9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->bitmap_data[SIZE_32] = GetImageDataFromSpecifics( 9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_specifics.favicon_web_32()); 9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_specifics.has_favicon_touch_64()) { 9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->bitmap_data[SIZE_64] = GetImageDataFromSpecifics( 9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_specifics.favicon_touch_64()); 9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconTrackingSpecifics tracking_specifics = 9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_favicon.GetSpecifics().favicon_tracking(); 9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL favicon_url = GURL(tracking_specifics.favicon_url()); 9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(favicon_url.is_valid()); 9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!synced_favicons_.count(favicon_url)); 9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedFaviconInfo* favicon_info = GetFaviconInfo(favicon_url); 9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_info) 9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; // We reached the in-memory limit. 9437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Time last_visit = syncer::ProtoTimeToTime( 9447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch tracking_specifics.last_visit_time_ms()); 9457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Due to crbug.com/258196, there are tracking nodes out there with 9467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // null visit times. If this is one of those, artificially make it a valid 9477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // visit time, so we know the node exists and update it properly on the next 9487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // real visit. 9497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (last_visit.is_null()) 9507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch last_visit = last_visit + base::TimeDelta::FromMilliseconds(1); 9517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UpdateFaviconVisitTime(favicon_url, last_visit); 9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_info->is_bookmarked = tracking_specifics.is_bookmarked(); 9537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(!favicon_info->last_visit_time.is_null()); 9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncData FaviconCache::CreateSyncDataFromLocalFavicon( 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::ModelType type, 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& favicon_url) const { 9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING); 9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(favicon_url.is_valid()); 9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconMap::const_iterator iter = synced_favicons_.find(favicon_url); 9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(iter != synced_favicons_.end()); 9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncedFaviconInfo* favicon_info = iter->second.get(); 9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncData data; 9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::EntitySpecifics specifics; 9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (type == syncer::FAVICON_IMAGES) { 9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconImageSpecifics* image_specifics = 9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.mutable_favicon_image(); 9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BuildImageSpecifics(favicon_info, image_specifics); 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sync_pb::FaviconTrackingSpecifics* tracking_specifics = 9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics.mutable_favicon_tracking(); 9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BuildTrackingSpecifics(favicon_info, tracking_specifics); 9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data = syncer::SyncData::CreateLocalData(favicon_url.spec(), 9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_url.spec(), 9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) specifics); 9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return data; 9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::DeleteSyncedFavicons(const std::set<GURL>& favicon_urls) { 9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList image_deletions, tracking_deletions; 9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::set<GURL>::const_iterator iter = favicon_urls.begin(); 9862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != favicon_urls.end(); ++iter) { 9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconMap::iterator favicon_iter = synced_favicons_.find(*iter); 9882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_iter == synced_favicons_.end()) 9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeleteSyncedFavicon(favicon_iter, 9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &image_deletions, 9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &tracking_deletions); 9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Deleting " << image_deletions.size() << " synced favicons."; 9957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (favicon_images_sync_processor_.get()) { 9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_images_sync_processor_->ProcessSyncChanges(FROM_HERE, 9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_deletions); 9987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 9997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (favicon_tracking_sync_processor_.get()) { 10002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_tracking_sync_processor_->ProcessSyncChanges(FROM_HERE, 10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tracking_deletions); 10022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid FaviconCache::DeleteSyncedFavicon( 10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconMap::iterator favicon_iter, 10072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList* image_changes, 10082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncer::SyncChangeList* tracking_changes) { 10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) linked_ptr<SyncedFaviconInfo> favicon_info = favicon_iter->second; 1010c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (FaviconInfoHasImages(*(favicon_iter->second))) { 1011c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) image_changes->push_back( 1012c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 1013c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_DELETE, 1014c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncData::CreateLocalDelete( 1015c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_info->favicon_url.spec(), 1016c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::FAVICON_IMAGES))); 1017c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1018c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (FaviconInfoHasTracking(*(favicon_iter->second))) { 1019c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tracking_changes->push_back( 1020c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange(FROM_HERE, 1021c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncChange::ACTION_DELETE, 1022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::SyncData::CreateLocalDelete( 1023c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) favicon_info->favicon_url.spec(), 1024c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) syncer::FAVICON_TRACKING))); 1025c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DropSyncedFavicon(favicon_iter); 10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconCache::DropSyncedFavicon(FaviconMap::iterator favicon_iter) { 10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recent_favicons_.erase(favicon_iter->second); 10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) synced_favicons_.erase(favicon_iter); 10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t FaviconCache::NumFaviconsForTest() const { 10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return synced_favicons_.size(); 10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t FaviconCache::NumTasksForTest() const { 10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return page_task_map_.size(); 10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace browser_sync 1043