Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/sync/glue/favicon_cache.h"
      6 
      7 #include "base/message_loop/message_loop.h"
      8 #include "base/strings/stringprintf.h"
      9 #include "base/time/time.h"
     10 #include "chrome/browser/chrome_notification_types.h"
     11 #include "chrome/browser/history/history_notifications.h"
     12 #include "content/public/browser/notification_service.h"
     13 #include "sync/api/sync_error_factory_mock.h"
     14 #include "sync/api/time.h"
     15 #include "sync/protocol/favicon_image_specifics.pb.h"
     16 #include "sync/protocol/favicon_tracking_specifics.pb.h"
     17 #include "sync/protocol/sync.pb.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 namespace browser_sync {
     21 
     22 namespace {
     23 
     24 // Total number of favicons to use in sync test batches.
     25 const int kFaviconBatchSize = 10;
     26 
     27 // Maximum number of favicons to sync.
     28 const int kMaxSyncFavicons = kFaviconBatchSize*2;
     29 
     30 // TestChangeProcessor --------------------------------------------------------
     31 
     32 // Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
     33 // back up to Sync.
     34 class TestChangeProcessor : public syncer::SyncChangeProcessor {
     35  public:
     36   TestChangeProcessor();
     37   virtual ~TestChangeProcessor();
     38 
     39   // Store a copy of all the changes passed in so we can examine them later.
     40   virtual syncer::SyncError ProcessSyncChanges(
     41       const tracked_objects::Location& from_here,
     42       const syncer::SyncChangeList& change_list) OVERRIDE;
     43 
     44   virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
     45       OVERRIDE {
     46     return syncer::SyncDataList();
     47   }
     48 
     49   bool contains_guid(const std::string& guid) const {
     50     return change_map_.count(guid) != 0;
     51   }
     52 
     53   syncer::SyncChange change_for_guid(const std::string& guid) const {
     54     DCHECK(contains_guid(guid));
     55     return change_map_.find(guid)->second;
     56   }
     57 
     58   // Returns the last change list received, and resets the internal list.
     59   syncer::SyncChangeList GetAndResetChangeList() {
     60     syncer::SyncChangeList list;
     61     list.swap(change_list_);
     62     return list;
     63   }
     64 
     65   void set_erroneous(bool erroneous) { erroneous_ = erroneous; }
     66 
     67  private:
     68   // Track the changes received in ProcessSyncChanges.
     69   std::map<std::string, syncer::SyncChange> change_map_;
     70   syncer::SyncChangeList change_list_;
     71   bool erroneous_;
     72 
     73   DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
     74 };
     75 
     76 TestChangeProcessor::TestChangeProcessor() : erroneous_(false) {
     77 }
     78 
     79 TestChangeProcessor::~TestChangeProcessor() {
     80 }
     81 
     82 syncer::SyncError TestChangeProcessor::ProcessSyncChanges(
     83     const tracked_objects::Location& from_here,
     84     const syncer::SyncChangeList& change_list) {
     85   if (erroneous_) {
     86     return syncer::SyncError(
     87         FROM_HERE,
     88         syncer::SyncError::DATATYPE_ERROR,
     89         "Some error.",
     90         change_list[0].sync_data().GetDataType());
     91   }
     92 
     93   change_list_.insert(change_list_.end(),
     94                       change_list.begin(),
     95                       change_list.end());
     96   change_map_.erase(change_map_.begin(), change_map_.end());
     97   for (syncer::SyncChangeList::const_iterator iter = change_list.begin();
     98       iter != change_list.end(); ++iter) {
     99     change_map_[iter->sync_data().GetTitle()] = *iter;
    100   }
    101   return syncer::SyncError();
    102 }
    103 
    104 
    105 // SyncChangeProcessorDelegate ------------------------------------------------
    106 
    107 class SyncChangeProcessorDelegate : public syncer::SyncChangeProcessor {
    108  public:
    109   explicit SyncChangeProcessorDelegate(syncer::SyncChangeProcessor* recipient);
    110   virtual ~SyncChangeProcessorDelegate();
    111 
    112   // syncer::SyncChangeProcessor implementation.
    113   virtual syncer::SyncError ProcessSyncChanges(
    114       const tracked_objects::Location& from_here,
    115       const syncer::SyncChangeList& change_list) OVERRIDE;
    116 
    117   virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
    118       OVERRIDE {
    119     return recipient_->GetAllSyncData(type);
    120   }
    121 
    122  private:
    123   // The recipient of all sync changes.
    124   syncer::SyncChangeProcessor* recipient_;
    125 
    126   DISALLOW_COPY_AND_ASSIGN(SyncChangeProcessorDelegate);
    127 };
    128 
    129 SyncChangeProcessorDelegate::SyncChangeProcessorDelegate(
    130     syncer::SyncChangeProcessor* recipient)
    131     : recipient_(recipient) {
    132   DCHECK(recipient_);
    133 }
    134 
    135 SyncChangeProcessorDelegate::~SyncChangeProcessorDelegate() {
    136 }
    137 
    138 syncer::SyncError SyncChangeProcessorDelegate::ProcessSyncChanges(
    139     const tracked_objects::Location& from_here,
    140     const syncer::SyncChangeList& change_list) {
    141   return recipient_->ProcessSyncChanges(from_here, change_list);
    142 }
    143 
    144 // TestFaviconData ------------------------------------------------------------
    145 struct TestFaviconData {
    146   TestFaviconData() : last_visit_time(0), is_bookmarked(false) {}
    147   GURL page_url;
    148   GURL icon_url;
    149   std::string image_16;
    150   std::string image_32;
    151   std::string image_64;
    152   int64 last_visit_time;
    153   bool is_bookmarked;
    154 };
    155 
    156 TestFaviconData BuildFaviconData(int index) {
    157   TestFaviconData data;
    158   data.page_url = GURL(base::StringPrintf("http://bla.com/%.2i.html", index));
    159   data.icon_url = GURL(base::StringPrintf("http://bla.com/%.2i.ico", index));
    160   data.image_16 = base::StringPrintf("16 %i", index);
    161   // TODO(zea): enable this once the cache supports writing them.
    162   // data.image_32 = base::StringPrintf("32 %i", index);
    163   // data.image_64 = base::StringPrintf("64 %i", index);
    164   data.last_visit_time = index;
    165   return data;
    166 }
    167 
    168 void FillImageSpecifics(
    169     const TestFaviconData& test_data,
    170     sync_pb::FaviconImageSpecifics* image_specifics) {
    171   image_specifics->set_favicon_url(test_data.icon_url.spec());
    172   if (!test_data.image_16.empty()) {
    173     image_specifics->mutable_favicon_web()->set_height(16);
    174     image_specifics->mutable_favicon_web()->set_width(16);
    175     image_specifics->mutable_favicon_web()->set_favicon(test_data.image_16);
    176   }
    177   if (!test_data.image_32.empty()) {
    178     image_specifics->mutable_favicon_web_32()->set_height(32);
    179     image_specifics->mutable_favicon_web_32()->set_width(32);
    180     image_specifics->mutable_favicon_web_32()->set_favicon(test_data.image_32);
    181   }
    182   if (!test_data.image_64.empty()) {
    183     image_specifics->mutable_favicon_touch_64()->set_height(64);
    184     image_specifics->mutable_favicon_touch_64()->set_width(64);
    185     image_specifics->mutable_favicon_touch_64()->
    186         set_favicon(test_data.image_64);
    187   }
    188 }
    189 
    190 void FillTrackingSpecifics(
    191     const TestFaviconData& test_data,
    192     sync_pb::FaviconTrackingSpecifics* tracking_specifics) {
    193   tracking_specifics->set_favicon_url(test_data.icon_url.spec());
    194   tracking_specifics->set_last_visit_time_ms(test_data.last_visit_time);
    195   tracking_specifics->set_is_bookmarked(test_data.is_bookmarked);
    196 }
    197 
    198 testing::AssertionResult CompareFaviconDataToSpecifics(
    199     const TestFaviconData& test_data,
    200     const sync_pb::EntitySpecifics& specifics) {
    201   if (specifics.has_favicon_image()) {
    202     sync_pb::FaviconImageSpecifics image_specifics = specifics.favicon_image();
    203     if (image_specifics.favicon_url() != test_data.icon_url.spec())
    204       return testing::AssertionFailure() << "Image icon url doesn't match.";
    205     if (!test_data.image_16.empty()) {
    206       if (image_specifics.favicon_web().favicon() != test_data.image_16 ||
    207           image_specifics.favicon_web().height() != 16 ||
    208           image_specifics.favicon_web().width() != 16) {
    209         return testing::AssertionFailure() << "16p image data doesn't match.";
    210       }
    211     } else if (image_specifics.has_favicon_web()) {
    212       return testing::AssertionFailure() << "Missing 16p favicon.";
    213     }
    214     if (!test_data.image_32.empty()) {
    215       if (image_specifics.favicon_web_32().favicon() != test_data.image_32 ||
    216           image_specifics.favicon_web().height() != 32 ||
    217           image_specifics.favicon_web().width() != 32) {
    218         return testing::AssertionFailure() << "32p image data doesn't match.";
    219       }
    220     } else if (image_specifics.has_favicon_web_32()) {
    221       return testing::AssertionFailure() << "Missing 32p favicon.";
    222     }
    223     if (!test_data.image_64.empty()) {
    224       if (image_specifics.favicon_touch_64().favicon() != test_data.image_64 ||
    225           image_specifics.favicon_web().height() != 64 ||
    226           image_specifics.favicon_web().width() != 64) {
    227         return testing::AssertionFailure() << "64p image data doesn't match.";
    228       }
    229     } else if (image_specifics.has_favicon_touch_64()) {
    230       return testing::AssertionFailure() << "Missing 64p favicon.";
    231     }
    232   } else {
    233     sync_pb::FaviconTrackingSpecifics tracking_specifics =
    234         specifics.favicon_tracking();
    235     if (tracking_specifics.favicon_url() != test_data.icon_url.spec())
    236       return testing::AssertionFailure() << "Tracking icon url doesn't match.";
    237     if (tracking_specifics.last_visit_time_ms() != test_data.last_visit_time)
    238       return testing::AssertionFailure() << "Visit time doesn't match.";
    239     if (tracking_specifics.is_bookmarked() != test_data.is_bookmarked)
    240       return testing::AssertionFailure() << "Bookmark status doens't match.";
    241   }
    242   return testing::AssertionSuccess();
    243 }
    244 
    245 testing::AssertionResult VerifyChanges(
    246     syncer::ModelType expected_model_type,
    247     const std::vector<syncer::SyncChange::SyncChangeType>&
    248         expected_change_types,
    249     const std::vector<int>& expected_icons,
    250     const syncer::SyncChangeList& change_list) {
    251   DCHECK_EQ(expected_change_types.size(), expected_icons.size());
    252   if (change_list.size() != expected_icons.size())
    253     return testing::AssertionFailure() << "Change list size doesn't match.";
    254   for (size_t i = 0; i < expected_icons.size(); ++i) {
    255     TestFaviconData data = BuildFaviconData(expected_icons[i]);
    256     if (change_list[i].sync_data().GetDataType() != expected_model_type)
    257       return testing::AssertionFailure() << "Change datatype doesn't match.";
    258     if (change_list[i].change_type() != expected_change_types[i])
    259       return testing::AssertionFailure() << "Change type doesn't match.";
    260     if (change_list[i].change_type() == syncer::SyncChange::ACTION_DELETE) {
    261       if (change_list[i].sync_data().GetTag() != data.icon_url.spec())
    262         return testing::AssertionFailure() << "Deletion url does not match.";
    263     } else {
    264       testing::AssertionResult compare_result =
    265           CompareFaviconDataToSpecifics(
    266               data,
    267               change_list[i].sync_data().GetSpecifics());
    268       if (!compare_result)
    269         return compare_result;
    270     }
    271   }
    272   return testing::AssertionSuccess();
    273 }
    274 
    275 }  // namespace
    276 
    277 class SyncFaviconCacheTest : public testing::Test {
    278  public:
    279   SyncFaviconCacheTest();
    280   virtual ~SyncFaviconCacheTest() {}
    281 
    282   void SetUpInitialSync(const syncer::SyncDataList& initial_image_data,
    283                         const syncer::SyncDataList& initial_tracking_data);
    284 
    285   size_t GetFaviconCount() const;
    286   size_t GetTaskCount() const;
    287 
    288   testing::AssertionResult ExpectFaviconEquals(
    289         const std::string& page_url,
    290         const std::string& bytes) const;
    291   testing::AssertionResult VerifyLocalIcons(
    292       const std::vector<int>& expected_icons);
    293   testing::AssertionResult VerifyLocalCustomIcons(
    294       const std::vector<TestFaviconData>& expected_icons);
    295 
    296   scoped_ptr<syncer::SyncChangeProcessor> CreateAndPassProcessor();
    297   scoped_ptr<syncer::SyncErrorFactory> CreateAndPassSyncErrorFactory();
    298 
    299   FaviconCache* cache() { return &cache_; }
    300   TestChangeProcessor* processor() { return sync_processor_.get(); }
    301 
    302   // Finish an outstanding favicon load for the icon described in |test_data|.
    303   void OnCustomFaviconDataAvailable(const TestFaviconData& test_data);
    304 
    305   // Helper method to run the message loop after invoking
    306   // OnReceivedSyncFavicon, which posts an internal task.
    307   void TriggerSyncFaviconReceived(const GURL& page_url,
    308                                   const GURL& icon_url,
    309                                   const std::string& icon_bytes,
    310                                   int64 last_visit_time_ms);
    311 
    312  private:
    313   base::MessageLoopForUI message_loop_;
    314   FaviconCache cache_;
    315 
    316   // Our dummy ChangeProcessor used to inspect changes pushed to Sync.
    317   scoped_ptr<TestChangeProcessor> sync_processor_;
    318   scoped_ptr<SyncChangeProcessorDelegate> sync_processor_delegate_;
    319 };
    320 
    321 SyncFaviconCacheTest::SyncFaviconCacheTest()
    322     : cache_(NULL, kMaxSyncFavicons),
    323       sync_processor_(new TestChangeProcessor),
    324       sync_processor_delegate_(new SyncChangeProcessorDelegate(
    325                                    sync_processor_.get())) {
    326 }
    327 
    328 void SyncFaviconCacheTest::SetUpInitialSync(
    329     const syncer::SyncDataList& initial_image_data,
    330     const syncer::SyncDataList& initial_tracking_data) {
    331   cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    332                                     initial_image_data,
    333                                     CreateAndPassProcessor(),
    334                                     CreateAndPassSyncErrorFactory());
    335   ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
    336   cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    337                                     initial_tracking_data,
    338                                     CreateAndPassProcessor(),
    339                                     CreateAndPassSyncErrorFactory());
    340   ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
    341 }
    342 
    343 size_t SyncFaviconCacheTest::GetFaviconCount() const {
    344   return cache_.NumFaviconsForTest();
    345 }
    346 
    347 size_t SyncFaviconCacheTest::GetTaskCount() const {
    348   return cache_.NumTasksForTest();
    349 }
    350 
    351 testing::AssertionResult SyncFaviconCacheTest::ExpectFaviconEquals(
    352     const std::string& page_url,
    353     const std::string& bytes) const {
    354   GURL gurl(page_url);
    355   scoped_refptr<base::RefCountedMemory> favicon;
    356   if (!cache_.GetSyncedFaviconForPageURL(gurl, &favicon))
    357     return testing::AssertionFailure() << "Favicon is missing.";
    358   if (favicon->size() != bytes.size())
    359     return testing::AssertionFailure() << "Favicon sizes don't match.";
    360   for (size_t i = 0; i < favicon->size(); ++i) {
    361     if (bytes[i] != *(favicon->front() + i))
    362       return testing::AssertionFailure() << "Favicon data doesn't match.";
    363   }
    364   return testing::AssertionSuccess();
    365 }
    366 
    367 testing::AssertionResult SyncFaviconCacheTest::VerifyLocalIcons(
    368     const std::vector<int>& expected_icons) {
    369   std::vector<TestFaviconData> expected_custom_icons;
    370   for (size_t i = 0; i < expected_icons.size(); ++i) {
    371     expected_custom_icons.push_back(BuildFaviconData(expected_icons[i]));
    372   }
    373   return VerifyLocalCustomIcons(expected_custom_icons);
    374 }
    375 
    376 
    377 testing::AssertionResult SyncFaviconCacheTest::VerifyLocalCustomIcons(
    378     const std::vector<TestFaviconData>& expected_custom_icons) {
    379   syncer::SyncDataList image_data_list =
    380       cache()->GetAllSyncData(syncer::FAVICON_IMAGES);
    381   syncer::SyncDataList tracking_data_list =
    382       cache()->GetAllSyncData(syncer::FAVICON_TRACKING);
    383   if (expected_custom_icons.size() > image_data_list.size() ||
    384       expected_custom_icons.size() > tracking_data_list.size())
    385     return testing::AssertionFailure() << "Number of icons doesn't match.";
    386   for (size_t i = 0; i < expected_custom_icons.size(); ++i) {
    387     const TestFaviconData& test_data = expected_custom_icons[i];
    388     // Find the test data in the data lists. Assume that both lists have the
    389     // same ordering, which may not match the |expected_custom_icons| ordering.
    390     bool found_match = false;
    391     for (size_t j = 0; j < image_data_list.size(); ++j) {
    392       if (image_data_list[j].GetTitle() != test_data.icon_url.spec())
    393         continue;
    394       found_match = true;
    395       const sync_pb::FaviconImageSpecifics& image_specifics =
    396           image_data_list[j].GetSpecifics().favicon_image();
    397       sync_pb::FaviconImageSpecifics expected_image_specifics;
    398       FillImageSpecifics(test_data, &expected_image_specifics);
    399       if (image_specifics.SerializeAsString() !=
    400           expected_image_specifics.SerializeAsString()) {
    401         return testing::AssertionFailure() << "Image data doesn't match.";
    402       }
    403       const sync_pb::FaviconTrackingSpecifics& tracking_specifics =
    404           tracking_data_list[j].GetSpecifics().favicon_tracking();
    405       sync_pb::FaviconTrackingSpecifics expected_tracking_specifics;
    406       FillTrackingSpecifics(test_data, &expected_tracking_specifics);
    407       if (tracking_specifics.SerializeAsString() !=
    408           expected_tracking_specifics.SerializeAsString()) {
    409         return testing::AssertionFailure() << "Tracking data doesn't match.";
    410       }
    411     }
    412     if (!found_match)
    413       return testing::AssertionFailure() << "Could not find favicon.";
    414   }
    415   return testing::AssertionSuccess();
    416 }
    417 
    418 scoped_ptr<syncer::SyncChangeProcessor>
    419 SyncFaviconCacheTest::CreateAndPassProcessor() {
    420   return scoped_ptr<syncer::SyncChangeProcessor>(
    421       new SyncChangeProcessorDelegate(sync_processor_.get()));
    422 }
    423 
    424 scoped_ptr<syncer::SyncErrorFactory> SyncFaviconCacheTest::
    425     CreateAndPassSyncErrorFactory() {
    426   return scoped_ptr<syncer::SyncErrorFactory>(
    427       new syncer::SyncErrorFactoryMock());
    428 }
    429 
    430 void SyncFaviconCacheTest::OnCustomFaviconDataAvailable(
    431     const TestFaviconData& test_data) {
    432   std::vector<chrome::FaviconBitmapResult> bitmap_results;
    433   if (!test_data.image_16.empty()) {
    434     chrome::FaviconBitmapResult bitmap_result;
    435     bitmap_result.icon_url = test_data.icon_url;
    436     bitmap_result.pixel_size.set_width(16);
    437     bitmap_result.pixel_size.set_height(16);
    438     base::RefCountedString* temp_string = new base::RefCountedString();
    439     temp_string->data() = test_data.image_16;
    440     bitmap_result.bitmap_data = temp_string;
    441     bitmap_results.push_back(bitmap_result);
    442   }
    443   if (!test_data.image_32.empty()) {
    444     chrome::FaviconBitmapResult bitmap_result;
    445     bitmap_result.icon_url = test_data.icon_url;
    446     bitmap_result.pixel_size.set_width(32);
    447     bitmap_result.pixel_size.set_height(32);
    448     base::RefCountedString* temp_string = new base::RefCountedString();
    449     temp_string->data() = test_data.image_32;
    450     bitmap_result.bitmap_data = temp_string;
    451     bitmap_results.push_back(bitmap_result);
    452   }
    453   if (!test_data.image_64.empty()) {
    454     chrome::FaviconBitmapResult bitmap_result;
    455     bitmap_result.icon_url = test_data.icon_url;
    456     bitmap_result.pixel_size.set_width(64);
    457     bitmap_result.pixel_size.set_height(64);
    458     base::RefCountedString* temp_string = new base::RefCountedString();
    459     temp_string->data() = test_data.image_64;
    460     bitmap_result.bitmap_data = temp_string;
    461     bitmap_results.push_back(bitmap_result);
    462   }
    463   cache()->OnFaviconDataAvailable(test_data.page_url, bitmap_results);
    464 }
    465 
    466 void SyncFaviconCacheTest::TriggerSyncFaviconReceived(
    467     const GURL& page_url,
    468     const GURL& icon_url,
    469     const std::string& icon_bytes,
    470     int64 last_visit_time_ms) {
    471   cache()->OnReceivedSyncFavicon(page_url,
    472                                  icon_url,
    473                                  icon_bytes,
    474                                  last_visit_time_ms);
    475   message_loop_.RunUntilIdle();
    476 }
    477 
    478 // A freshly constructed cache should be empty.
    479 TEST_F(SyncFaviconCacheTest, Empty) {
    480   EXPECT_EQ(0U, GetFaviconCount());
    481 }
    482 
    483 TEST_F(SyncFaviconCacheTest, ReceiveSyncFavicon) {
    484   std::string page_url = "http://www.google.com";
    485   std::string fav_url = "http://www.google.com/favicon.ico";
    486   std::string bytes = "bytes";
    487   EXPECT_EQ(0U, GetFaviconCount());
    488   TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
    489   EXPECT_EQ(1U, GetFaviconCount());
    490   EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
    491 }
    492 
    493 TEST_F(SyncFaviconCacheTest, ReceiveEmptySyncFavicon) {
    494   std::string page_url = "http://www.google.com";
    495   std::string fav_url = "http://www.google.com/favicon.ico";
    496   std::string bytes = "bytes";
    497   EXPECT_EQ(0U, GetFaviconCount());
    498   TriggerSyncFaviconReceived(GURL(page_url),
    499                              GURL(fav_url),
    500                              std::string(),
    501                              0);
    502   EXPECT_EQ(0U, GetFaviconCount());
    503   EXPECT_FALSE(ExpectFaviconEquals(page_url, std::string()));
    504 
    505   // Then receive the actual favicon.
    506   TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
    507   EXPECT_EQ(1U, GetFaviconCount());
    508   EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
    509 }
    510 
    511 TEST_F(SyncFaviconCacheTest, ReceiveUpdatedSyncFavicon) {
    512   std::string page_url = "http://www.google.com";
    513   std::string fav_url = "http://www.google.com/favicon.ico";
    514   std::string bytes = "bytes";
    515   std::string bytes2 = "bytes2";
    516   EXPECT_EQ(0U, GetFaviconCount());
    517   TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
    518   EXPECT_EQ(1U, GetFaviconCount());
    519   EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
    520 
    521   // The cache should not update existing favicons from tab sync favicons
    522   // (which can be reassociated several times).
    523   TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes2, 0);
    524   EXPECT_EQ(1U, GetFaviconCount());
    525   EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
    526   EXPECT_FALSE(ExpectFaviconEquals(page_url, bytes2));
    527 }
    528 
    529 TEST_F(SyncFaviconCacheTest, MultipleMappings) {
    530   std::string page_url = "http://www.google.com";
    531   std::string page2_url = "http://bla.google.com";
    532   std::string fav_url = "http://www.google.com/favicon.ico";
    533   std::string bytes = "bytes";
    534   EXPECT_EQ(0U, GetFaviconCount());
    535   TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
    536   EXPECT_EQ(1U, GetFaviconCount());
    537   EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
    538 
    539   // Map another page to the same favicon. They should share the same data.
    540   TriggerSyncFaviconReceived(GURL(page2_url), GURL(fav_url), bytes, 0);
    541   EXPECT_EQ(1U, GetFaviconCount());
    542   EXPECT_TRUE(ExpectFaviconEquals(page2_url, bytes));
    543 }
    544 
    545 TEST_F(SyncFaviconCacheTest, SyncEmpty) {
    546   syncer::SyncMergeResult merge_result =
    547       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    548                                         syncer::SyncDataList(),
    549                                         CreateAndPassProcessor(),
    550                                         CreateAndPassSyncErrorFactory());
    551 
    552   EXPECT_EQ(0U, cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
    553   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    554   EXPECT_EQ(0, merge_result.num_items_added());
    555   EXPECT_EQ(0, merge_result.num_items_modified());
    556   EXPECT_EQ(0, merge_result.num_items_deleted());
    557   EXPECT_EQ(0, merge_result.num_items_before_association());
    558   EXPECT_EQ(0, merge_result.num_items_after_association());
    559 
    560   merge_result =
    561       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    562                                         syncer::SyncDataList(),
    563                                         CreateAndPassProcessor(),
    564                                         CreateAndPassSyncErrorFactory());
    565 
    566   EXPECT_EQ(0U, cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
    567   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    568   EXPECT_EQ(0, merge_result.num_items_added());
    569   EXPECT_EQ(0, merge_result.num_items_modified());
    570   EXPECT_EQ(0, merge_result.num_items_deleted());
    571   EXPECT_EQ(0, merge_result.num_items_before_association());
    572   EXPECT_EQ(0, merge_result.num_items_after_association());
    573 }
    574 
    575 // Setting up sync with existing local favicons should push those favicons into
    576 // sync.
    577 TEST_F(SyncFaviconCacheTest, SyncExistingLocal) {
    578   std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
    579   std::vector<int> expected_icons;
    580   for (int i = 0; i < kFaviconBatchSize; ++i) {
    581     TestFaviconData favicon = BuildFaviconData(i);
    582     TriggerSyncFaviconReceived(favicon.page_url,
    583                                favicon.icon_url,
    584                                favicon.image_16,
    585                                i);
    586     expected_change_types.push_back(syncer::SyncChange::ACTION_ADD);
    587     expected_icons.push_back(i);
    588   }
    589 
    590   syncer::SyncMergeResult merge_result =
    591       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    592                                         syncer::SyncDataList(),
    593                                         CreateAndPassProcessor(),
    594                                         CreateAndPassSyncErrorFactory());
    595   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    596             cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
    597   syncer::SyncChangeList change_list = processor()->GetAndResetChangeList();
    598   EXPECT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES,
    599                             expected_change_types,
    600                             expected_icons,
    601                             change_list));
    602   EXPECT_EQ(0, merge_result.num_items_added());
    603   EXPECT_EQ(0, merge_result.num_items_modified());
    604   EXPECT_EQ(0, merge_result.num_items_deleted());
    605   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    606   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    607 
    608   merge_result =
    609       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    610                                         syncer::SyncDataList(),
    611                                         CreateAndPassProcessor(),
    612                                         CreateAndPassSyncErrorFactory());
    613   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    614             cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
    615   change_list = processor()->GetAndResetChangeList();
    616   EXPECT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING,
    617                             expected_change_types,
    618                             expected_icons,
    619                             change_list));
    620   EXPECT_EQ(0, merge_result.num_items_added());
    621   EXPECT_EQ(0, merge_result.num_items_modified());
    622   EXPECT_EQ(0, merge_result.num_items_deleted());
    623   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    624   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    625 }
    626 
    627 // Setting up sync with existing sync data should load that data into the local
    628 // cache.
    629 TEST_F(SyncFaviconCacheTest, SyncExistingRemote) {
    630   syncer::SyncDataList initial_image_data, initial_tracking_data;
    631   std::vector<int> expected_icons;
    632   for (int i = 0; i < kFaviconBatchSize; ++i) {
    633     expected_icons.push_back(i);
    634     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    635     FillImageSpecifics(BuildFaviconData(i),
    636                        image_specifics.mutable_favicon_image());
    637     initial_image_data.push_back(
    638         syncer::SyncData::CreateRemoteData(1,
    639                                            image_specifics,
    640                                            base::Time()));
    641     FillTrackingSpecifics(BuildFaviconData(i),
    642                           tracking_specifics.mutable_favicon_tracking());
    643     initial_tracking_data.push_back(
    644         syncer::SyncData::CreateRemoteData(1,
    645                                            tracking_specifics,
    646                                            base::Time()));
    647   }
    648 
    649   syncer::SyncMergeResult merge_result =
    650       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    651                                         initial_image_data,
    652                                         CreateAndPassProcessor(),
    653                                         CreateAndPassSyncErrorFactory());
    654   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    655             cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
    656   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    657   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_added());
    658   EXPECT_EQ(0, merge_result.num_items_modified());
    659   EXPECT_EQ(0, merge_result.num_items_deleted());
    660   EXPECT_EQ(0, merge_result.num_items_before_association());
    661   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    662 
    663   merge_result =
    664       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    665                                         initial_tracking_data,
    666                                         CreateAndPassProcessor(),
    667                                         CreateAndPassSyncErrorFactory());
    668   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    669             cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
    670   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    671   EXPECT_EQ(0, merge_result.num_items_added());
    672   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
    673   EXPECT_EQ(0, merge_result.num_items_deleted());
    674   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    675   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    676 
    677   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    678 }
    679 
    680 // Setting up sync with local data and sync data should merge the two image
    681 // sets, with remote data having priority in case both exist.
    682 TEST_F(SyncFaviconCacheTest, SyncMergesImages) {
    683   // First go through and add local 16p favicons.
    684   for (int i = 0; i < kFaviconBatchSize; ++i) {
    685     TestFaviconData favicon = BuildFaviconData(i);
    686     TriggerSyncFaviconReceived(favicon.page_url,
    687                                favicon.icon_url,
    688                                favicon.image_16,
    689                                i);
    690   }
    691 
    692   // Then go through and create the initial sync data, which does not have 16p
    693   // favicons for the first half, and has custom 16p favicons for the second.
    694   std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
    695   std::vector<int> expected_icons;
    696   std::vector<TestFaviconData> expected_data;
    697   syncer::SyncDataList initial_image_data, initial_tracking_data;
    698   for (int i = 0; i < kFaviconBatchSize; ++i) {
    699     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    700     TestFaviconData test_data = BuildFaviconData(i);
    701     if (i < kFaviconBatchSize/2) {
    702       test_data.image_16 = std::string();
    703       expected_icons.push_back(i);
    704       expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    705     } else {
    706       test_data.image_16 += "custom";
    707       expected_data.push_back(test_data);
    708     }
    709     FillImageSpecifics(test_data,
    710                        image_specifics.mutable_favicon_image());
    711 
    712     initial_image_data.push_back(
    713         syncer::SyncData::CreateRemoteData(1,
    714                                            image_specifics,
    715                                            base::Time()));
    716     FillTrackingSpecifics(test_data,
    717                           tracking_specifics.mutable_favicon_tracking());
    718     initial_tracking_data.push_back(
    719         syncer::SyncData::CreateRemoteData(1,
    720                                            tracking_specifics,
    721                                            base::Time()));
    722   }
    723 
    724   syncer::SyncMergeResult merge_result =
    725       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    726                                         initial_image_data,
    727                                         CreateAndPassProcessor(),
    728                                         CreateAndPassSyncErrorFactory());
    729   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    730             cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
    731   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    732   EXPECT_EQ((unsigned long)kFaviconBatchSize/2, changes.size());
    733   EXPECT_EQ(0, merge_result.num_items_added());
    734   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
    735   EXPECT_EQ(0, merge_result.num_items_deleted());
    736   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    737   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    738 
    739   merge_result =
    740       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    741                                         initial_tracking_data,
    742                                         CreateAndPassProcessor(),
    743                                         CreateAndPassSyncErrorFactory());
    744   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    745             cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
    746   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    747   EXPECT_EQ(0, merge_result.num_items_added());
    748   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
    749   EXPECT_EQ(0, merge_result.num_items_deleted());
    750   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    751   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    752 
    753   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    754   ASSERT_TRUE(VerifyLocalCustomIcons(expected_data));
    755   ASSERT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES,
    756                             expected_change_types,
    757                             expected_icons,
    758                             changes));
    759 }
    760 
    761 // Setting up sync with local data and sync data should merge the two tracking
    762 // sets, such that the visit time is the most recent.
    763 TEST_F(SyncFaviconCacheTest, SyncMergesTracking) {
    764   // First go through and add local 16p favicons.
    765   for (int i = 0; i < kFaviconBatchSize; ++i) {
    766     TestFaviconData favicon = BuildFaviconData(i);
    767     TriggerSyncFaviconReceived(favicon.page_url,
    768                                favicon.icon_url,
    769                                favicon.image_16,
    770                                i);
    771   }
    772 
    773   // Then go through and create the initial sync data, which for the first half
    774   // the local has a newer visit, and for the second the remote does.
    775   std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
    776   std::vector<int> expected_icons;
    777   std::vector<TestFaviconData> expected_data;
    778   syncer::SyncDataList initial_image_data, initial_tracking_data;
    779   for (int i = 0; i < kFaviconBatchSize; ++i) {
    780     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    781     TestFaviconData test_data = BuildFaviconData(i);
    782     if (i < kFaviconBatchSize/2) {
    783       test_data.last_visit_time = i-1;
    784       expected_icons.push_back(i);
    785       expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    786     } else {
    787       test_data.last_visit_time = i+1;
    788       expected_data.push_back(test_data);
    789     }
    790     FillImageSpecifics(test_data,
    791                        image_specifics.mutable_favicon_image());
    792 
    793     initial_image_data.push_back(
    794         syncer::SyncData::CreateRemoteData(1,
    795                                            image_specifics,
    796                                            base::Time()));
    797     FillTrackingSpecifics(test_data,
    798                           tracking_specifics.mutable_favicon_tracking());
    799     initial_tracking_data.push_back(
    800         syncer::SyncData::CreateRemoteData(1,
    801                                            tracking_specifics,
    802                                            base::Time()));
    803   }
    804 
    805   syncer::SyncMergeResult merge_result =
    806       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    807                                         initial_image_data,
    808                                         CreateAndPassProcessor(),
    809                                         CreateAndPassSyncErrorFactory());
    810   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    811             cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
    812   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    813   EXPECT_EQ(0, merge_result.num_items_added());
    814   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
    815   EXPECT_EQ(0, merge_result.num_items_deleted());
    816   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    817   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    818 
    819   merge_result =
    820       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    821                                         initial_tracking_data,
    822                                         CreateAndPassProcessor(),
    823                                         CreateAndPassSyncErrorFactory());
    824   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    825             cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
    826   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    827   EXPECT_EQ((unsigned long)kFaviconBatchSize/2, changes.size());
    828   EXPECT_EQ(0, merge_result.num_items_added());
    829   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
    830   EXPECT_EQ(0, merge_result.num_items_deleted());
    831   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    832   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    833 
    834   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    835   ASSERT_TRUE(VerifyLocalCustomIcons(expected_data));
    836   ASSERT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING,
    837                             expected_change_types,
    838                             expected_icons,
    839                             changes));
    840 }
    841 
    842 // Receiving old icons (missing image data) should result in pushing the new
    843 // merged icons back to the remote syncer.
    844 TEST_F(SyncFaviconCacheTest, ReceiveStaleImages) {
    845   syncer::SyncDataList initial_image_data, initial_tracking_data;
    846   syncer::SyncChangeList stale_changes;
    847   std::vector<int> expected_icons;
    848   std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
    849   for (int i = 0; i < kFaviconBatchSize; ++i) {
    850     expected_icons.push_back(i);
    851     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    852     FillImageSpecifics(BuildFaviconData(i),
    853                        image_specifics.mutable_favicon_image());
    854     initial_image_data.push_back(
    855         syncer::SyncData::CreateRemoteData(1,
    856                                            image_specifics,
    857                                            base::Time()));
    858     expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    859     image_specifics.mutable_favicon_image()->clear_favicon_web();
    860     stale_changes.push_back(
    861         syncer::SyncChange(
    862              FROM_HERE,
    863              syncer::SyncChange::ACTION_UPDATE,
    864              syncer::SyncData::CreateRemoteData(1,
    865                                                 image_specifics,
    866                                                 base::Time())));
    867     FillTrackingSpecifics(BuildFaviconData(i),
    868                           tracking_specifics.mutable_favicon_tracking());
    869     initial_tracking_data.push_back(
    870         syncer::SyncData::CreateRemoteData(1,
    871                                            tracking_specifics,
    872                                            base::Time()));
    873   }
    874 
    875   SetUpInitialSync(initial_image_data, initial_tracking_data);
    876 
    877   // Now receive the same icons as an update, but with missing image data.
    878   cache()->ProcessSyncChanges(FROM_HERE, stale_changes);
    879   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    880   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    881   ASSERT_EQ((unsigned long)kFaviconBatchSize, changes.size());
    882   ASSERT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES,
    883                             expected_change_types,
    884                             expected_icons,
    885                             changes));
    886 }
    887 
    888 // New icons should be added locally without pushing anything back to the
    889 // remote syncer.
    890 TEST_F(SyncFaviconCacheTest, ReceiveNewImages) {
    891   syncer::SyncDataList initial_image_data, initial_tracking_data;
    892   syncer::SyncChangeList new_changes;
    893   std::vector<int> expected_icons;
    894   for (int i = 0; i < kFaviconBatchSize; ++i) {
    895     expected_icons.push_back(i);
    896     TestFaviconData test_data = BuildFaviconData(i);
    897     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    898     FillImageSpecifics(test_data,
    899                        image_specifics.mutable_favicon_image());
    900     new_changes.push_back(
    901         syncer::SyncChange(
    902              FROM_HERE,
    903              syncer::SyncChange::ACTION_UPDATE,
    904              syncer::SyncData::CreateRemoteData(1,
    905                                                 image_specifics,
    906                                                 base::Time())));
    907     image_specifics.mutable_favicon_image()->mutable_favicon_web()->
    908         mutable_favicon()->append("old");
    909     initial_image_data.push_back(
    910         syncer::SyncData::CreateRemoteData(1,
    911                                            image_specifics,
    912                                            base::Time()));
    913     FillTrackingSpecifics(BuildFaviconData(i),
    914                           tracking_specifics.mutable_favicon_tracking());
    915     initial_tracking_data.push_back(
    916         syncer::SyncData::CreateRemoteData(1,
    917                                            tracking_specifics,
    918                                            base::Time()));
    919   }
    920 
    921   SetUpInitialSync(initial_image_data, initial_tracking_data);
    922 
    923   // Now receive the new icons as an update.
    924   cache()->ProcessSyncChanges(FROM_HERE, new_changes);
    925   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    926   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    927 }
    928 
    929 // Recieving the same icons as the local data should have no effect.
    930 TEST_F(SyncFaviconCacheTest, ReceiveSameImages) {
    931   syncer::SyncDataList initial_image_data, initial_tracking_data;
    932   syncer::SyncChangeList same_changes;
    933   std::vector<int> expected_icons;
    934   for (int i = 0; i < kFaviconBatchSize; ++i) {
    935     expected_icons.push_back(i);
    936     TestFaviconData test_data = BuildFaviconData(i);
    937     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    938     FillImageSpecifics(test_data,
    939                        image_specifics.mutable_favicon_image());
    940     same_changes.push_back(
    941         syncer::SyncChange(
    942              FROM_HERE,
    943              syncer::SyncChange::ACTION_UPDATE,
    944              syncer::SyncData::CreateRemoteData(1,
    945                                                 image_specifics,
    946                                                 base::Time())));
    947     initial_image_data.push_back(
    948         syncer::SyncData::CreateRemoteData(1,
    949                                            image_specifics,
    950                                            base::Time()));
    951     FillTrackingSpecifics(BuildFaviconData(i),
    952                           tracking_specifics.mutable_favicon_tracking());
    953     initial_tracking_data.push_back(
    954         syncer::SyncData::CreateRemoteData(1,
    955                                            tracking_specifics,
    956                                            base::Time()));
    957   }
    958 
    959   SetUpInitialSync(initial_image_data, initial_tracking_data);
    960 
    961   // Now receive the new icons as an update.
    962   cache()->ProcessSyncChanges(FROM_HERE, same_changes);
    963   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    964   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    965 }
    966 
    967 // Receiving stale tracking (old visit times) should result in pushing back
    968 // the newer visit times to the remote syncer.
    969 TEST_F(SyncFaviconCacheTest, ReceiveStaleTracking) {
    970   syncer::SyncDataList initial_image_data, initial_tracking_data;
    971   syncer::SyncChangeList stale_changes;
    972   std::vector<int> expected_icons;
    973   std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
    974   for (int i = 0; i < kFaviconBatchSize; ++i) {
    975     expected_icons.push_back(i);
    976     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    977     FillImageSpecifics(BuildFaviconData(i),
    978                        image_specifics.mutable_favicon_image());
    979     initial_image_data.push_back(
    980         syncer::SyncData::CreateRemoteData(1,
    981                                            image_specifics,
    982                                            base::Time()));
    983     expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    984     FillTrackingSpecifics(BuildFaviconData(i),
    985                           tracking_specifics.mutable_favicon_tracking());
    986     initial_tracking_data.push_back(
    987         syncer::SyncData::CreateRemoteData(1,
    988                                            tracking_specifics,
    989                                            base::Time()));
    990     tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(-1);
    991     stale_changes.push_back(
    992         syncer::SyncChange(
    993              FROM_HERE,
    994              syncer::SyncChange::ACTION_UPDATE,
    995              syncer::SyncData::CreateRemoteData(1,
    996                                                 tracking_specifics,
    997                                                 base::Time())));
    998   }
    999 
   1000   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1001 
   1002   // Now receive the same icons as an update, but with missing image data.
   1003   cache()->ProcessSyncChanges(FROM_HERE, stale_changes);
   1004   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1005   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
   1006   ASSERT_EQ((unsigned long)kFaviconBatchSize, changes.size());
   1007   ASSERT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING,
   1008                             expected_change_types,
   1009                             expected_icons,
   1010                             changes));
   1011 }
   1012 
   1013 // New tracking information should be added locally without pushing anything
   1014 // back to the remote syncer.
   1015 TEST_F(SyncFaviconCacheTest, ReceiveNewTracking) {
   1016   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1017   syncer::SyncChangeList new_changes;
   1018   std::vector<int> expected_icons;
   1019   // We start from one here so that we don't have to deal with a -1 visit time.
   1020   for (int i = 1; i <= kFaviconBatchSize; ++i) {
   1021     expected_icons.push_back(i);
   1022     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1023     FillImageSpecifics(BuildFaviconData(i),
   1024                        image_specifics.mutable_favicon_image());
   1025     initial_image_data.push_back(
   1026         syncer::SyncData::CreateRemoteData(1,
   1027                                            image_specifics,
   1028                                            base::Time()));
   1029     FillTrackingSpecifics(BuildFaviconData(i),
   1030                           tracking_specifics.mutable_favicon_tracking());
   1031     new_changes.push_back(
   1032         syncer::SyncChange(
   1033              FROM_HERE,
   1034              syncer::SyncChange::ACTION_UPDATE,
   1035              syncer::SyncData::CreateRemoteData(1,
   1036                                                 tracking_specifics,
   1037                                                 base::Time())));
   1038     tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(i-1);
   1039     initial_tracking_data.push_back(
   1040         syncer::SyncData::CreateRemoteData(1,
   1041                                            tracking_specifics,
   1042                                            base::Time()));
   1043   }
   1044 
   1045   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1046 
   1047   // Now receive the new icons as an update.
   1048   cache()->ProcessSyncChanges(FROM_HERE, new_changes);
   1049   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1050   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
   1051 }
   1052 
   1053 // Receiving the same tracking information as the local data should have no
   1054 // effect.
   1055 TEST_F(SyncFaviconCacheTest, ReceiveSameTracking) {
   1056   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1057   syncer::SyncChangeList same_changes;
   1058   std::vector<int> expected_icons;
   1059   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1060     expected_icons.push_back(i);
   1061     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1062     FillImageSpecifics(BuildFaviconData(i),
   1063                        image_specifics.mutable_favicon_image());
   1064     initial_image_data.push_back(
   1065         syncer::SyncData::CreateRemoteData(1,
   1066                                            image_specifics,
   1067                                            base::Time()));
   1068     FillTrackingSpecifics(BuildFaviconData(i),
   1069                           tracking_specifics.mutable_favicon_tracking());
   1070     initial_tracking_data.push_back(
   1071         syncer::SyncData::CreateRemoteData(1,
   1072                                            tracking_specifics,
   1073                                            base::Time()));
   1074     same_changes.push_back(
   1075         syncer::SyncChange(
   1076              FROM_HERE,
   1077              syncer::SyncChange::ACTION_UPDATE,
   1078              syncer::SyncData::CreateRemoteData(1,
   1079                                                 tracking_specifics,
   1080                                                 base::Time())));
   1081   }
   1082 
   1083   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1084 
   1085   // Now receive the new icons as an update.
   1086   cache()->ProcessSyncChanges(FROM_HERE, same_changes);
   1087   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1088   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
   1089 }
   1090 
   1091 // Verify we can delete favicons after setting up sync.
   1092 TEST_F(SyncFaviconCacheTest, DeleteFavicons) {
   1093   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1094   syncer::SyncChangeList tracking_deletions, image_deletions;
   1095   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1096     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1097     FillImageSpecifics(BuildFaviconData(i),
   1098                        image_specifics.mutable_favicon_image());
   1099     initial_image_data.push_back(
   1100         syncer::SyncData::CreateRemoteData(1,
   1101                                            image_specifics,
   1102                                            base::Time()));
   1103     FillTrackingSpecifics(BuildFaviconData(i),
   1104                           tracking_specifics.mutable_favicon_tracking());
   1105     initial_tracking_data.push_back(
   1106         syncer::SyncData::CreateRemoteData(1,
   1107                                            tracking_specifics,
   1108                                            base::Time()));
   1109     tracking_deletions.push_back(
   1110         syncer::SyncChange(
   1111              FROM_HERE,
   1112              syncer::SyncChange::ACTION_DELETE,
   1113              syncer::SyncData::CreateRemoteData(1,
   1114                                                 tracking_specifics,
   1115                                                 base::Time())));
   1116     image_deletions.push_back(
   1117         syncer::SyncChange(
   1118              FROM_HERE,
   1119              syncer::SyncChange::ACTION_DELETE,
   1120              syncer::SyncData::CreateRemoteData(1,
   1121                                                 image_specifics,
   1122                                                 base::Time())));
   1123   }
   1124 
   1125   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1126 
   1127   // Now receive the tracking deletions. Since we'll still have orphan data,
   1128   // the favicon count should remain the same.
   1129   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1130   cache()->ProcessSyncChanges(FROM_HERE, tracking_deletions);
   1131   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1132   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1133 
   1134   // Once the image deletions arrive, the favicon count should be 0 again.
   1135   cache()->ProcessSyncChanges(FROM_HERE, image_deletions);
   1136   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1137   EXPECT_EQ(0U, GetFaviconCount());
   1138 }
   1139 
   1140 // Ensure that MergeDataAndStartSyncing enforces the sync favicon limit by
   1141 // dropping local icons.
   1142 TEST_F(SyncFaviconCacheTest, ExpireOnMergeData) {
   1143   std::vector<int> expected_icons;
   1144   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1145 
   1146   // Set up sync so it has the maximum number of favicons, while the local has
   1147   // the same amount of different favicons.
   1148   for (int i = 0; i < kMaxSyncFavicons; ++i) {
   1149     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1150     FillImageSpecifics(BuildFaviconData(i),
   1151                        image_specifics.mutable_favicon_image());
   1152     initial_image_data.push_back(
   1153         syncer::SyncData::CreateRemoteData(1,
   1154                                            image_specifics,
   1155                                            base::Time()));
   1156     FillTrackingSpecifics(BuildFaviconData(i),
   1157                           tracking_specifics.mutable_favicon_tracking());
   1158     initial_tracking_data.push_back(
   1159         syncer::SyncData::CreateRemoteData(1,
   1160                                            tracking_specifics,
   1161                                            base::Time()));
   1162     expected_icons.push_back(i);
   1163 
   1164     TestFaviconData favicon = BuildFaviconData(i+kMaxSyncFavicons);
   1165     TriggerSyncFaviconReceived(favicon.page_url,
   1166                                favicon.icon_url,
   1167                                favicon.image_16,
   1168                                i+kMaxSyncFavicons);
   1169   }
   1170 
   1171   EXPECT_FALSE(VerifyLocalIcons(expected_icons));
   1172 
   1173   syncer::SyncMergeResult merge_result =
   1174       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
   1175                                         initial_image_data,
   1176                                         CreateAndPassProcessor(),
   1177                                         CreateAndPassSyncErrorFactory());
   1178   EXPECT_EQ((unsigned long)kMaxSyncFavicons,
   1179             cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
   1180   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1181   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_added());
   1182   EXPECT_EQ(0, merge_result.num_items_modified());
   1183   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_deleted());
   1184   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_before_association());
   1185   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_after_association());
   1186 
   1187   merge_result =
   1188       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
   1189                                         initial_tracking_data,
   1190                                         CreateAndPassProcessor(),
   1191                                         CreateAndPassSyncErrorFactory());
   1192   EXPECT_EQ((unsigned long)kMaxSyncFavicons,
   1193             cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
   1194   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1195   EXPECT_EQ(0, merge_result.num_items_added());
   1196   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_modified());
   1197   EXPECT_EQ(0, merge_result.num_items_deleted());
   1198   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_before_association());
   1199   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_after_association());
   1200 
   1201   EXPECT_TRUE(VerifyLocalIcons(expected_icons));
   1202 }
   1203 
   1204 // Receiving sync additions (via ProcessSyncChanges) should not trigger
   1205 // expirations.
   1206 TEST_F(SyncFaviconCacheTest, NoExpireOnProcessSyncChanges) {
   1207   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1208   syncer::SyncChangeList image_changes, tracking_changes;
   1209   std::vector<int> expected_icons;
   1210   for (int i = 0; i < kMaxSyncFavicons; ++i) {
   1211     expected_icons.push_back(i);
   1212     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1213     FillImageSpecifics(BuildFaviconData(i),
   1214                        image_specifics.mutable_favicon_image());
   1215     initial_image_data.push_back(
   1216         syncer::SyncData::CreateRemoteData(1,
   1217                                            image_specifics,
   1218                                            base::Time()));
   1219     FillTrackingSpecifics(BuildFaviconData(i),
   1220                           tracking_specifics.mutable_favicon_tracking());
   1221     initial_tracking_data.push_back(
   1222         syncer::SyncData::CreateRemoteData(1,
   1223                                            tracking_specifics,
   1224                                            base::Time()));
   1225     // Set up new tracking specifics for the icons received at change time.
   1226     expected_icons.push_back(i + kMaxSyncFavicons);
   1227     FillImageSpecifics(BuildFaviconData(i + kMaxSyncFavicons),
   1228                        image_specifics.mutable_favicon_image());
   1229     image_changes.push_back(
   1230         syncer::SyncChange(
   1231              FROM_HERE,
   1232              syncer::SyncChange::ACTION_ADD,
   1233              syncer::SyncData::CreateRemoteData(1,
   1234                                                 image_specifics,
   1235                                                 base::Time())));
   1236     FillTrackingSpecifics(BuildFaviconData(i + kMaxSyncFavicons),
   1237                           tracking_specifics.mutable_favicon_tracking());
   1238     tracking_changes.push_back(
   1239         syncer::SyncChange(
   1240              FROM_HERE,
   1241              syncer::SyncChange::ACTION_ADD,
   1242              syncer::SyncData::CreateRemoteData(1,
   1243                                                 tracking_specifics,
   1244                                                 base::Time())));
   1245   }
   1246 
   1247   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1248 
   1249   // Now receive the new icons as an update.
   1250   EXPECT_EQ((unsigned long)kMaxSyncFavicons, GetFaviconCount());
   1251   cache()->ProcessSyncChanges(FROM_HERE, image_changes);
   1252   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1253   cache()->ProcessSyncChanges(FROM_HERE, tracking_changes);
   1254   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1255   EXPECT_TRUE(VerifyLocalIcons(expected_icons));
   1256   EXPECT_GT(GetFaviconCount(), (unsigned long)kMaxSyncFavicons);
   1257 }
   1258 
   1259 // Test that visiting a new page triggers a favicon load and a sync addition.
   1260 TEST_F(SyncFaviconCacheTest, AddOnFaviconVisited) {
   1261   EXPECT_EQ(0U, GetFaviconCount());
   1262   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1263   std::vector<int> expected_icons;
   1264 
   1265   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1266     expected_icons.push_back(i);
   1267     TestFaviconData test_data = BuildFaviconData(i);
   1268     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1269   }
   1270 
   1271   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetTaskCount());
   1272 
   1273   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1274     TestFaviconData test_data = BuildFaviconData(i);
   1275     OnCustomFaviconDataAvailable(test_data);
   1276 
   1277     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1278     ASSERT_EQ(2U, changes.size());
   1279     EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
   1280     EXPECT_EQ(syncer::FAVICON_IMAGES, changes[0].sync_data().GetDataType());
   1281     EXPECT_TRUE(
   1282         CompareFaviconDataToSpecifics(test_data,
   1283                                       changes[0].sync_data().GetSpecifics()));
   1284     EXPECT_EQ(syncer::FAVICON_TRACKING, changes[1].sync_data().GetDataType());
   1285     // Just verify the favicon url for the tracking specifics and that the
   1286     // timestamp is non-null.
   1287     EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[1].change_type());
   1288     EXPECT_EQ(test_data.icon_url.spec(),
   1289               changes[1].sync_data().GetSpecifics().favicon_tracking().
   1290                   favicon_url());
   1291     EXPECT_NE(changes[1].sync_data().GetSpecifics().favicon_tracking().
   1292                   last_visit_time_ms(), 0);
   1293   }
   1294 
   1295   EXPECT_EQ(0U, GetTaskCount());
   1296   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1297 }
   1298 
   1299 // Test that visiting a known page does not trigger a favicon load and just
   1300 // updates the sync tracking info.
   1301 TEST_F(SyncFaviconCacheTest, UpdateOnFaviconVisited) {
   1302   EXPECT_EQ(0U, GetFaviconCount());
   1303   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1304   std::vector<int> expected_icons;
   1305 
   1306   // Add the favicons.
   1307   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1308     expected_icons.push_back(i);
   1309     TestFaviconData test_data = BuildFaviconData(i);
   1310     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1311     OnCustomFaviconDataAvailable(test_data);
   1312   }
   1313   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1314 
   1315   // Visit the favicons again.
   1316   EXPECT_EQ(0U, GetTaskCount());
   1317   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1318     TestFaviconData test_data = BuildFaviconData(i);
   1319     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1320 
   1321     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1322     ASSERT_EQ(1U, changes.size());
   1323     // Just verify the favicon url for the tracking specifics and that the
   1324     // timestamp is non-null.
   1325     EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
   1326     EXPECT_EQ(test_data.icon_url.spec(),
   1327               changes[0].sync_data().GetSpecifics().favicon_tracking().
   1328                   favicon_url());
   1329     EXPECT_NE(changes[0].sync_data().GetSpecifics().favicon_tracking().
   1330                   last_visit_time_ms(), 0);
   1331   }
   1332   EXPECT_EQ(0U, GetTaskCount());
   1333   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1334 }
   1335 
   1336 // Ensure we properly expire old synced favicons as new ones are updated.
   1337 TEST_F(SyncFaviconCacheTest, ExpireOnFaviconVisited) {
   1338   EXPECT_EQ(0U, GetFaviconCount());
   1339   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1340   std::vector<int> expected_icons;
   1341 
   1342   // Add the initial favicons.
   1343   for (int i = 0; i < kMaxSyncFavicons; ++i) {
   1344     expected_icons.push_back(i);
   1345     TestFaviconData test_data = BuildFaviconData(i);
   1346     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1347     OnCustomFaviconDataAvailable(test_data);
   1348   }
   1349   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1350 
   1351   // Visit some new favicons, triggering expirations of the old favicons.
   1352   EXPECT_EQ(0U, GetTaskCount());
   1353   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1354     TestFaviconData old_favicon = BuildFaviconData(i);
   1355     TestFaviconData test_data = BuildFaviconData(i + kMaxSyncFavicons);
   1356     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1357     OnCustomFaviconDataAvailable(test_data);
   1358 
   1359     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1360     ASSERT_EQ(4U, changes.size());
   1361     EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
   1362     EXPECT_TRUE(
   1363         CompareFaviconDataToSpecifics(test_data,
   1364                                       changes[0].sync_data().GetSpecifics()));
   1365     EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, changes[1].change_type());
   1366     EXPECT_EQ(old_favicon.icon_url.spec(), changes[1].sync_data().GetTag());
   1367 
   1368     EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[2].change_type());
   1369     EXPECT_EQ(test_data.icon_url.spec(),
   1370               changes[2].sync_data().GetSpecifics().favicon_tracking().
   1371                   favicon_url());
   1372     EXPECT_NE(changes[2].sync_data().GetSpecifics().favicon_tracking().
   1373                   last_visit_time_ms(), 0);
   1374     EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, changes[3].change_type());
   1375     EXPECT_EQ(old_favicon.icon_url.spec(), changes[3].sync_data().GetTag());
   1376   }
   1377 
   1378   EXPECT_EQ(0U, GetTaskCount());
   1379   EXPECT_EQ((unsigned long)kMaxSyncFavicons, GetFaviconCount());
   1380 }
   1381 
   1382 // A full history clear notification should result in all synced favicons being
   1383 // deleted.
   1384 TEST_F(SyncFaviconCacheTest, HistoryFullClear) {
   1385   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1386   std::vector<int> expected_icons;
   1387   std::vector<syncer::SyncChange::SyncChangeType> expected_deletions;
   1388   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1389     expected_icons.push_back(i);
   1390     expected_deletions.push_back(syncer::SyncChange::ACTION_DELETE);
   1391     TestFaviconData test_data = BuildFaviconData(i);
   1392     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1393     FillImageSpecifics(test_data,
   1394                        image_specifics.mutable_favicon_image());
   1395     initial_image_data.push_back(
   1396         syncer::SyncData::CreateRemoteData(1,
   1397                                            image_specifics,
   1398                                            base::Time()));
   1399     FillTrackingSpecifics(BuildFaviconData(i),
   1400                           tracking_specifics.mutable_favicon_tracking());
   1401     initial_tracking_data.push_back(
   1402         syncer::SyncData::CreateRemoteData(1,
   1403                                            tracking_specifics,
   1404                                            base::Time()));
   1405   }
   1406 
   1407   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1408   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1409   EXPECT_TRUE(changes.empty());
   1410 
   1411   history::URLsDeletedDetails deletions;
   1412   deletions.all_history = true;
   1413   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1414   content::NotificationService::current()->Notify(
   1415         chrome::NOTIFICATION_HISTORY_URLS_DELETED,
   1416         content::Source<Profile>(NULL),
   1417         content::Details<history::URLsDeletedDetails>(&deletions));
   1418   EXPECT_EQ(0U, GetFaviconCount());
   1419   changes = processor()->GetAndResetChangeList();
   1420   ASSERT_EQ(changes.size(), (unsigned long)kFaviconBatchSize*2);
   1421   syncer::SyncChangeList changes_1, changes_2;
   1422   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1423     changes_1.push_back(changes[i]);
   1424     changes_2.push_back(changes[i + kFaviconBatchSize]);
   1425   }
   1426   VerifyChanges(syncer::FAVICON_IMAGES,
   1427                 expected_deletions,
   1428                 expected_icons,
   1429                 changes_1);
   1430   VerifyChanges(syncer::FAVICON_TRACKING,
   1431                 expected_deletions,
   1432                 expected_icons,
   1433                 changes_2);
   1434 }
   1435 
   1436 // A partial history clear notification should result in the expired favicons
   1437 // also being deleted from sync.
   1438 TEST_F(SyncFaviconCacheTest, HistorySubsetClear) {
   1439   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1440   std::vector<int> expected_icons;
   1441   std::vector<syncer::SyncChange::SyncChangeType> expected_deletions;
   1442   history::URLsDeletedDetails deletions;
   1443   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1444     TestFaviconData test_data = BuildFaviconData(i);
   1445     if (i < kFaviconBatchSize/2) {
   1446       expected_icons.push_back(i);
   1447       expected_deletions.push_back(syncer::SyncChange::ACTION_DELETE);
   1448       deletions.favicon_urls.insert(test_data.icon_url);
   1449     }
   1450     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1451     FillImageSpecifics(test_data,
   1452                        image_specifics.mutable_favicon_image());
   1453     initial_image_data.push_back(
   1454         syncer::SyncData::CreateRemoteData(1,
   1455                                            image_specifics,
   1456                                            base::Time()));
   1457     FillTrackingSpecifics(BuildFaviconData(i),
   1458                           tracking_specifics.mutable_favicon_tracking());
   1459     initial_tracking_data.push_back(
   1460         syncer::SyncData::CreateRemoteData(1,
   1461                                            tracking_specifics,
   1462                                            base::Time()));
   1463   }
   1464 
   1465   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1466   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1467   EXPECT_TRUE(changes.empty());
   1468 
   1469   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1470   content::NotificationService::current()->Notify(
   1471         chrome::NOTIFICATION_HISTORY_URLS_DELETED,
   1472         content::Source<Profile>(NULL),
   1473         content::Details<history::URLsDeletedDetails>(&deletions));
   1474   EXPECT_EQ((unsigned long)kFaviconBatchSize/2, GetFaviconCount());
   1475   changes = processor()->GetAndResetChangeList();
   1476   ASSERT_EQ(changes.size(), (unsigned long)kFaviconBatchSize);
   1477   syncer::SyncChangeList changes_1, changes_2;
   1478   for (size_t i = 0; i < kFaviconBatchSize/2; ++i) {
   1479     changes_1.push_back(changes[i]);
   1480     changes_2.push_back(changes[i + kFaviconBatchSize/2]);
   1481   }
   1482   VerifyChanges(syncer::FAVICON_IMAGES,
   1483                 expected_deletions,
   1484                 expected_icons,
   1485                 changes_1);
   1486   VerifyChanges(syncer::FAVICON_TRACKING,
   1487                 expected_deletions,
   1488                 expected_icons,
   1489                 changes_2);
   1490 }
   1491 
   1492 // Any favicon urls with the "data" scheme should be ignored.
   1493 TEST_F(SyncFaviconCacheTest, IgnoreDataScheme) {
   1494   EXPECT_EQ(0U, GetFaviconCount());
   1495   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1496   std::vector<int> expected_icons;
   1497 
   1498   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1499     TestFaviconData test_data = BuildFaviconData(i);
   1500     cache()->OnFaviconVisited(test_data.page_url, GURL());
   1501   }
   1502 
   1503   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetTaskCount());
   1504 
   1505   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1506     TestFaviconData test_data = BuildFaviconData(i);
   1507     test_data.icon_url = GURL("data:image/png;base64;blabla");
   1508     EXPECT_TRUE(test_data.icon_url.is_valid());
   1509     OnCustomFaviconDataAvailable(test_data);
   1510   }
   1511 
   1512   EXPECT_EQ(0U, GetTaskCount());
   1513   EXPECT_EQ(0U, GetFaviconCount());
   1514   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1515   EXPECT_TRUE(changes.empty());
   1516 }
   1517 
   1518 // When visiting a page we've already loaded the favicon for, don't attempt to
   1519 // reload the favicon, just update the visit time using the cached icon url.
   1520 TEST_F(SyncFaviconCacheTest, ReuseCachedIconUrl) {
   1521   EXPECT_EQ(0U, GetFaviconCount());
   1522   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1523   std::vector<int> expected_icons;
   1524 
   1525   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1526     expected_icons.push_back(i);
   1527     TestFaviconData test_data = BuildFaviconData(i);
   1528     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1529   }
   1530 
   1531   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetTaskCount());
   1532 
   1533   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1534     TestFaviconData test_data = BuildFaviconData(i);
   1535     OnCustomFaviconDataAvailable(test_data);
   1536   }
   1537   processor()->GetAndResetChangeList();
   1538   EXPECT_EQ(0U, GetTaskCount());
   1539   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1540 
   1541   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1542     TestFaviconData test_data = BuildFaviconData(i);
   1543     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1544     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1545     ASSERT_EQ(1U, changes.size());
   1546     // Just verify the favicon url for the tracking specifics and that the
   1547     // timestamp is non-null.
   1548     EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
   1549     EXPECT_EQ(test_data.icon_url.spec(),
   1550               changes[0].sync_data().GetSpecifics().favicon_tracking().
   1551                   favicon_url());
   1552     EXPECT_NE(changes[0].sync_data().GetSpecifics().favicon_tracking().
   1553                   last_visit_time_ms(), 0);
   1554   }
   1555   EXPECT_EQ(0U, GetTaskCount());
   1556 }
   1557 
   1558 // If we wind up with orphan image/tracking nodes, then receive an update
   1559 // for those favicons, we should lazily create the missing nodes.
   1560 TEST_F(SyncFaviconCacheTest, UpdatedOrphans) {
   1561   EXPECT_EQ(0U, GetFaviconCount());
   1562   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1563 
   1564   syncer::SyncChangeList initial_image_changes;
   1565   syncer::SyncChangeList initial_tracking_changes;
   1566   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1567     TestFaviconData test_data = BuildFaviconData(i);
   1568     // Even favicons have image data but no tracking data. Odd favicons have
   1569     // tracking data but no image data.
   1570     if (i % 2 == 0) {
   1571       sync_pb::EntitySpecifics image_specifics;
   1572       FillImageSpecifics(BuildFaviconData(i),
   1573                          image_specifics.mutable_favicon_image());
   1574       initial_image_changes.push_back(
   1575           syncer::SyncChange(FROM_HERE,
   1576                              syncer::SyncChange::ACTION_ADD,
   1577                              syncer::SyncData::CreateRemoteData(
   1578                                  1, image_specifics, base::Time())));
   1579     } else {
   1580       sync_pb::EntitySpecifics tracking_specifics;
   1581       FillTrackingSpecifics(BuildFaviconData(i),
   1582                             tracking_specifics.mutable_favicon_tracking());
   1583       initial_tracking_changes.push_back(
   1584           syncer::SyncChange(FROM_HERE,
   1585                              syncer::SyncChange::ACTION_ADD,
   1586                              syncer::SyncData::CreateRemoteData(
   1587                                  1, tracking_specifics, base::Time())));
   1588     }
   1589   }
   1590 
   1591   cache()->ProcessSyncChanges(FROM_HERE, initial_image_changes);
   1592   cache()->ProcessSyncChanges(FROM_HERE, initial_tracking_changes);
   1593   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1594   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1595 
   1596   for (int i = 0; i < kFaviconBatchSize/2; ++i) {
   1597     TestFaviconData test_data = BuildFaviconData(i);
   1598     cache()->OnFaviconVisited(test_data.page_url, GURL());
   1599     EXPECT_EQ(1U, GetTaskCount());
   1600     OnCustomFaviconDataAvailable(test_data);
   1601     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1602 
   1603     // Even favicons had image data, so should now receive new tracking data
   1604     // and updated image data (we allow one update after the initial add).
   1605     // Odd favicons had tracking so should now receive new image data and
   1606     // updated tracking data.
   1607     if (i % 2 == 0) {
   1608       ASSERT_EQ(2U, changes.size());
   1609       EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
   1610       EXPECT_TRUE(
   1611           CompareFaviconDataToSpecifics(test_data,
   1612                                         changes[0].sync_data().GetSpecifics()));
   1613       EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[1].change_type());
   1614       EXPECT_EQ(test_data.icon_url.spec(),
   1615                 changes[1].sync_data().GetSpecifics().favicon_tracking().
   1616                     favicon_url());
   1617       EXPECT_NE(changes[1].sync_data().GetSpecifics().favicon_tracking().
   1618                     last_visit_time_ms(), 0);
   1619     } else {
   1620       ASSERT_EQ(2U, changes.size());
   1621       EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
   1622       EXPECT_TRUE(
   1623           CompareFaviconDataToSpecifics(test_data,
   1624                                         changes[0].sync_data().GetSpecifics()));
   1625       EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[1].change_type());
   1626       EXPECT_EQ(test_data.icon_url.spec(),
   1627                 changes[1].sync_data().GetSpecifics().favicon_tracking().
   1628                     favicon_url());
   1629       EXPECT_NE(changes[1].sync_data().GetSpecifics().favicon_tracking().
   1630                     last_visit_time_ms(), 0);
   1631     }
   1632   }
   1633 
   1634   EXPECT_EQ(0U, GetTaskCount());
   1635   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1636 }
   1637 
   1638 // Verify that orphaned favicon images don't result in creating invalid
   1639 // favicon tracking data.
   1640 TEST_F(SyncFaviconCacheTest, PartialAssociationInfo) {
   1641   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1642   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1643     sync_pb::EntitySpecifics image_specifics;
   1644     FillImageSpecifics(BuildFaviconData(i),
   1645                        image_specifics.mutable_favicon_image());
   1646     initial_image_data.push_back(
   1647         syncer::SyncData::CreateRemoteData(1,
   1648                                            image_specifics,
   1649                                            base::Time()));
   1650     image_specifics.mutable_favicon_image()->clear_favicon_web();
   1651   }
   1652 
   1653   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1654   syncer::SyncChangeList change_list = processor()->GetAndResetChangeList();
   1655   EXPECT_TRUE(change_list.empty());
   1656   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1657 }
   1658 
   1659 // Tests that we don't choke if a favicon visit node with a null visit time is
   1660 // present (see crbug.com/258196) and an update is made.
   1661 TEST_F(SyncFaviconCacheTest, NullFaviconVisitTime) {
   1662   EXPECT_EQ(0U, GetFaviconCount());
   1663 
   1664   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1665   std::vector<int> expected_icons;
   1666   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1667     expected_icons.push_back(i);
   1668     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1669     FillImageSpecifics(BuildFaviconData(i),
   1670                        image_specifics.mutable_favicon_image());
   1671     initial_image_data.push_back(
   1672         syncer::SyncData::CreateRemoteData(1,
   1673                                            image_specifics,
   1674                                            base::Time()));
   1675     FillTrackingSpecifics(BuildFaviconData(i),
   1676                           tracking_specifics.mutable_favicon_tracking());
   1677     tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(
   1678         syncer::TimeToProtoTime(base::Time()));
   1679     initial_tracking_data.push_back(
   1680         syncer::SyncData::CreateRemoteData(1,
   1681                                            tracking_specifics,
   1682                                            base::Time()));
   1683   }
   1684 
   1685   cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
   1686                                     initial_image_data,
   1687                                     CreateAndPassProcessor(),
   1688                                     CreateAndPassSyncErrorFactory());
   1689   ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
   1690   cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
   1691                                     initial_tracking_data,
   1692                                     CreateAndPassProcessor(),
   1693                                     CreateAndPassSyncErrorFactory());
   1694   ASSERT_EQ((unsigned long)kFaviconBatchSize,
   1695             processor()->GetAndResetChangeList().size());
   1696   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1697 
   1698   // Visit the favicons again.
   1699   EXPECT_EQ(0U, GetTaskCount());
   1700   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1701     TestFaviconData test_data = BuildFaviconData(i);
   1702     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1703 
   1704     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1705     ASSERT_EQ(1U, changes.size());
   1706     // Just verify the favicon url for the tracking specifics and that the
   1707     // timestamp is non-null.
   1708     EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
   1709     EXPECT_EQ(test_data.icon_url.spec(),
   1710               changes[0].sync_data().GetSpecifics().favicon_tracking().
   1711                   favicon_url());
   1712     EXPECT_NE(changes[0].sync_data().GetSpecifics().favicon_tracking().
   1713                   last_visit_time_ms(), 0);
   1714   }
   1715   EXPECT_EQ(0U, GetTaskCount());
   1716   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1717 }
   1718 
   1719 // If another synced client has a clock skewed towards the future, it's possible
   1720 // that favicons added locally will be expired as they are added. Ensure this
   1721 // doesn't crash (see crbug.com/306150).
   1722 TEST_F(SyncFaviconCacheTest, VisitFaviconClockSkew) {
   1723   EXPECT_EQ(0U, GetFaviconCount());
   1724   const int kClockSkew = 20;  // 20 minutes in the future.
   1725 
   1726   // Set up sync with kMaxSyncFavicons starting kClockSkew minutes in the
   1727   // future.
   1728   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1729   for (int i = 0; i < kMaxSyncFavicons; ++i) {
   1730     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1731     TestFaviconData test_data = BuildFaviconData(i);
   1732     test_data.last_visit_time =
   1733         syncer::TimeToProtoTime(
   1734             base::Time::Now() + base::TimeDelta::FromMinutes(kClockSkew));
   1735     FillImageSpecifics(test_data,
   1736                        image_specifics.mutable_favicon_image());
   1737     initial_image_data.push_back(
   1738         syncer::SyncData::CreateRemoteData(1,
   1739                                            image_specifics,
   1740                                            base::Time()));
   1741     FillTrackingSpecifics(test_data,
   1742                           tracking_specifics.mutable_favicon_tracking());
   1743     initial_tracking_data.push_back(
   1744         syncer::SyncData::CreateRemoteData(1,
   1745                                            tracking_specifics,
   1746                                            base::Time()));
   1747   }
   1748   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1749 
   1750   // Visit some new favicons with local time, which will be expired as they
   1751   // are added.
   1752   EXPECT_EQ(0U, GetTaskCount());
   1753   for (int i = 0; i < kClockSkew; ++i) {
   1754     TestFaviconData test_data = BuildFaviconData(i + kMaxSyncFavicons);
   1755     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1756     OnCustomFaviconDataAvailable(test_data);
   1757 
   1758     // The changes will be an add followed by a delete for both the image and
   1759     // tracking info.
   1760     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1761     ASSERT_EQ(changes.size(), 4U);
   1762     ASSERT_EQ(changes[0].change_type(), syncer::SyncChange::ACTION_ADD);
   1763     ASSERT_EQ(changes[0].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
   1764     ASSERT_EQ(changes[1].change_type(), syncer::SyncChange::ACTION_DELETE);
   1765     ASSERT_EQ(changes[1].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
   1766     ASSERT_EQ(changes[2].change_type(), syncer::SyncChange::ACTION_ADD);
   1767     ASSERT_EQ(changes[2].sync_data().GetDataType(), syncer::FAVICON_TRACKING);
   1768     ASSERT_EQ(changes[3].change_type(), syncer::SyncChange::ACTION_DELETE);
   1769     ASSERT_EQ(changes[3].sync_data().GetDataType(), syncer::FAVICON_TRACKING);
   1770   }
   1771   EXPECT_EQ(0U, GetTaskCount());
   1772   EXPECT_EQ((unsigned long)kMaxSyncFavicons, GetFaviconCount());
   1773 }
   1774 
   1775 }  // namespace browser_sync
   1776