Home | History | Annotate | Download | only in webdata
      1 // Copyright (c) 2012 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 "base/location.h"
      6 #include "base/message_loop/message_loop.h"
      7 #include "base/strings/utf_string_conversions.h"
      8 #include "chrome/browser/webdata/autofill_profile_syncable_service.h"
      9 #include "components/autofill/core/browser/autofill_profile.h"
     10 #include "components/autofill/core/browser/webdata/autofill_change.h"
     11 #include "content/public/test/test_browser_thread.h"
     12 #include "sync/api/sync_error_factory.h"
     13 #include "sync/api/sync_error_factory_mock.h"
     14 #include "sync/protocol/sync.pb.h"
     15 #include "testing/gmock/include/gmock/gmock.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 using ::testing::_;
     19 using ::testing::DoAll;
     20 using ::testing::Eq;
     21 using ::testing::Return;
     22 using ::testing::Property;
     23 using autofill::AutofillProfile;
     24 using autofill::AutofillProfileChange;
     25 using content::BrowserThread;
     26 
     27 // Some guids for testing.
     28 const char kGuid1[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44B";
     29 const char kGuid2[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44C";
     30 const char kGuid3[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44D";
     31 const char kGuid4[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44E";
     32 const char kHttpOrigin[] = "http://www.example.com/";
     33 const char kHttpsOrigin[] = "https://www.example.com/";
     34 const char kSettingsOrigin[] = "Chrome settings";
     35 
     36 class MockAutofillProfileSyncableService
     37     : public AutofillProfileSyncableService {
     38  public:
     39   MockAutofillProfileSyncableService() {}
     40   virtual ~MockAutofillProfileSyncableService() {}
     41 
     42   using AutofillProfileSyncableService::DataBundle;
     43   using AutofillProfileSyncableService::set_sync_processor;
     44   using AutofillProfileSyncableService::CreateData;
     45 
     46   MOCK_METHOD1(LoadAutofillData, bool(std::vector<AutofillProfile*>*));
     47   MOCK_METHOD1(SaveChangesToWebData,
     48                bool(const AutofillProfileSyncableService::DataBundle&));
     49 };
     50 
     51 ACTION_P(CopyData, data) {
     52   arg0->resize(data->size());
     53   std::copy(data->begin(), data->end(), arg0->begin());
     54 }
     55 
     56 MATCHER_P(CheckSyncChanges, n_sync_changes_list, "") {
     57   if (arg.size() != n_sync_changes_list.size())
     58     return false;
     59   syncer::SyncChangeList::const_iterator passed, expected;
     60   for (passed = arg.begin(), expected = n_sync_changes_list.begin();
     61        passed != arg.end() && expected != n_sync_changes_list.end();
     62        ++passed, ++expected) {
     63     DCHECK(passed->IsValid());
     64     if (passed->change_type() != expected->change_type())
     65       return false;
     66     if (passed->sync_data().GetSpecifics().autofill_profile().guid() !=
     67         expected->sync_data().GetSpecifics().autofill_profile().guid()) {
     68       return false;
     69     }
     70   }
     71   return true;
     72 }
     73 
     74 MATCHER_P(DataBundleCheck, n_bundle, "") {
     75   if ((arg.profiles_to_delete.size() != n_bundle.profiles_to_delete.size()) ||
     76       (arg.profiles_to_update.size() != n_bundle.profiles_to_update.size()) ||
     77       (arg.profiles_to_add.size() != n_bundle.profiles_to_add.size()))
     78     return false;
     79   for (size_t i = 0; i < arg.profiles_to_delete.size(); ++i) {
     80     if (arg.profiles_to_delete[i] != n_bundle.profiles_to_delete[i])
     81       return false;
     82   }
     83   for (size_t i = 0; i < arg.profiles_to_update.size(); ++i) {
     84     if (*arg.profiles_to_update[i] != *n_bundle.profiles_to_update[i])
     85       return false;
     86   }
     87   for (size_t i = 0; i < arg.profiles_to_add.size(); ++i) {
     88     if (*arg.profiles_to_add[i] != *n_bundle.profiles_to_add[i])
     89       return false;
     90   }
     91   return true;
     92 }
     93 
     94 class MockSyncChangeProcessor : public syncer::SyncChangeProcessor {
     95  public:
     96   MockSyncChangeProcessor() {}
     97   virtual ~MockSyncChangeProcessor() {}
     98 
     99   MOCK_METHOD2(ProcessSyncChanges,
    100                syncer::SyncError(const tracked_objects::Location&,
    101                                  const syncer::SyncChangeList&));
    102 };
    103 
    104 class TestSyncChangeProcessor : public syncer::SyncChangeProcessor {
    105  public:
    106   TestSyncChangeProcessor() {}
    107   virtual ~TestSyncChangeProcessor() {}
    108 
    109   virtual syncer::SyncError ProcessSyncChanges(
    110       const tracked_objects::Location& location,
    111       const syncer::SyncChangeList& changes) OVERRIDE {
    112     changes_ = changes;
    113     return syncer::SyncError();
    114   }
    115 
    116   const syncer::SyncChangeList& changes() { return changes_; }
    117 
    118  private:
    119   syncer::SyncChangeList changes_;
    120 };
    121 
    122 class AutofillProfileSyncableServiceTest : public testing::Test {
    123  public:
    124   AutofillProfileSyncableServiceTest()
    125     : ui_thread_(BrowserThread::UI, &message_loop_),
    126       db_thread_(BrowserThread::DB, &message_loop_) {}
    127 
    128   virtual void SetUp() OVERRIDE {
    129     sync_processor_.reset(new MockSyncChangeProcessor);
    130   }
    131 
    132   // Wrapper around AutofillProfileSyncableService::MergeDataAndStartSyncing()
    133   // that also verifies expectations.
    134   void MergeDataAndStartSyncing(
    135       const std::vector<AutofillProfile*>& profiles_from_web_db,
    136       const syncer::SyncDataList& data_list,
    137       const MockAutofillProfileSyncableService::DataBundle& expected_bundle,
    138       const syncer::SyncChangeList& expected_change_list) {
    139     EXPECT_CALL(autofill_syncable_service_, LoadAutofillData(_))
    140         .Times(1)
    141         .WillOnce(DoAll(CopyData(&profiles_from_web_db), Return(true)));
    142     EXPECT_CALL(autofill_syncable_service_,
    143                 SaveChangesToWebData(DataBundleCheck(expected_bundle)))
    144         .Times(1)
    145         .WillOnce(Return(true));
    146     ON_CALL(*sync_processor_, ProcessSyncChanges(_, _))
    147         .WillByDefault(Return(syncer::SyncError()));
    148     EXPECT_CALL(*sync_processor_,
    149                 ProcessSyncChanges(_, CheckSyncChanges(expected_change_list)))
    150         .Times(1)
    151         .WillOnce(Return(syncer::SyncError()));
    152 
    153     // Takes ownership of sync_processor_.
    154     autofill_syncable_service_.MergeDataAndStartSyncing(
    155         syncer::AUTOFILL_PROFILE, data_list,
    156         sync_processor_.PassAs<syncer::SyncChangeProcessor>(),
    157         scoped_ptr<syncer::SyncErrorFactory>(
    158             new syncer::SyncErrorFactoryMock()));
    159   }
    160 
    161  protected:
    162   base::MessageLoop message_loop_;
    163   content::TestBrowserThread ui_thread_;
    164   content::TestBrowserThread db_thread_;
    165   MockAutofillProfileSyncableService autofill_syncable_service_;
    166   scoped_ptr<MockSyncChangeProcessor> sync_processor_;
    167 };
    168 
    169 TEST_F(AutofillProfileSyncableServiceTest, MergeDataAndStartSyncing) {
    170   std::vector<AutofillProfile*> profiles_from_web_db;
    171   std::string guid_present1 = kGuid1;
    172   std::string guid_present2 = kGuid2;
    173   std::string guid_synced1 = kGuid3;
    174   std::string guid_synced2 = kGuid4;
    175   std::string origin_present1 = kHttpOrigin;
    176   std::string origin_present2 = std::string();
    177   std::string origin_synced1 = kHttpsOrigin;
    178   std::string origin_synced2 = kSettingsOrigin;
    179 
    180   profiles_from_web_db.push_back(
    181       new AutofillProfile(guid_present1, origin_present1));
    182   profiles_from_web_db.back()->SetRawInfo(
    183       autofill::NAME_FIRST, UTF8ToUTF16("John"));
    184   profiles_from_web_db.back()->SetRawInfo(
    185       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
    186   profiles_from_web_db.push_back(
    187       new AutofillProfile(guid_present2, origin_present2));
    188   profiles_from_web_db.back()->SetRawInfo(
    189       autofill::NAME_FIRST, UTF8ToUTF16("Tom"));
    190   profiles_from_web_db.back()->SetRawInfo(
    191       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("2 2nd st"));
    192 
    193   syncer::SyncDataList data_list;
    194   AutofillProfile profile1(guid_synced1, origin_synced1);
    195   profile1.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Jane"));
    196   data_list.push_back(autofill_syncable_service_.CreateData(profile1));
    197   AutofillProfile profile2(guid_synced2, origin_synced2);
    198   profile2.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Harry"));
    199   data_list.push_back(autofill_syncable_service_.CreateData(profile2));
    200   // This one will have the name and origin updated.
    201   AutofillProfile profile3(guid_present2, origin_synced2);
    202   profile3.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Tom Doe"));
    203   data_list.push_back(autofill_syncable_service_.CreateData(profile3));
    204 
    205   syncer::SyncChangeList expected_change_list;
    206   expected_change_list.push_back(
    207       syncer::SyncChange(FROM_HERE,
    208                          syncer::SyncChange::ACTION_ADD,
    209                          MockAutofillProfileSyncableService::CreateData(
    210                              *profiles_from_web_db.front())));
    211 
    212   MockAutofillProfileSyncableService::DataBundle expected_bundle;
    213   expected_bundle.profiles_to_add.push_back(&profile1);
    214   expected_bundle.profiles_to_add.push_back(&profile2);
    215   expected_bundle.profiles_to_update.push_back(&profile3);
    216 
    217   MergeDataAndStartSyncing(
    218       profiles_from_web_db, data_list, expected_bundle, expected_change_list);
    219   autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
    220 }
    221 
    222 TEST_F(AutofillProfileSyncableServiceTest, MergeIdenticalProfiles) {
    223   std::vector<AutofillProfile*> profiles_from_web_db;
    224   std::string guid_present1 = kGuid1;
    225   std::string guid_present2 = kGuid2;
    226   std::string guid_synced1 = kGuid3;
    227   std::string guid_synced2 = kGuid4;
    228   std::string origin_present1 = kHttpOrigin;
    229   std::string origin_present2 = kSettingsOrigin;
    230   std::string origin_synced1 = kHttpsOrigin;
    231   std::string origin_synced2 = kHttpsOrigin;
    232 
    233   profiles_from_web_db.push_back(
    234       new AutofillProfile(guid_present1, origin_present1));
    235   profiles_from_web_db.back()->SetRawInfo(
    236       autofill::NAME_FIRST, UTF8ToUTF16("John"));
    237   profiles_from_web_db.back()->SetRawInfo(
    238       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
    239   profiles_from_web_db.push_back(
    240       new AutofillProfile(guid_present2, origin_present2));
    241   profiles_from_web_db.back()->SetRawInfo(
    242       autofill::NAME_FIRST, UTF8ToUTF16("Tom"));
    243   profiles_from_web_db.back()->SetRawInfo(
    244       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("2 2nd st"));
    245 
    246   // The synced profiles are identical to the local ones, except that the guids
    247   // are different.
    248   syncer::SyncDataList data_list;
    249   AutofillProfile profile1(guid_synced1, origin_synced1);
    250   profile1.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("John"));
    251   profile1.SetRawInfo(autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
    252   data_list.push_back(autofill_syncable_service_.CreateData(profile1));
    253   AutofillProfile profile2(guid_synced2, origin_synced2);
    254   profile2.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Tom"));
    255   profile2.SetRawInfo(autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("2 2nd st"));
    256   data_list.push_back(autofill_syncable_service_.CreateData(profile2));
    257 
    258   AutofillProfile expected_profile(profile2);
    259   expected_profile.set_origin(kSettingsOrigin);
    260   syncer::SyncChangeList expected_change_list;
    261   expected_change_list.push_back(
    262       syncer::SyncChange(FROM_HERE,
    263                          syncer::SyncChange::ACTION_UPDATE,
    264                          MockAutofillProfileSyncableService::CreateData(
    265                              expected_profile)));
    266 
    267   MockAutofillProfileSyncableService::DataBundle expected_bundle;
    268   expected_bundle.profiles_to_delete.push_back(guid_present1);
    269   expected_bundle.profiles_to_delete.push_back(guid_present2);
    270   expected_bundle.profiles_to_add.push_back(&profile1);
    271   expected_bundle.profiles_to_add.push_back(&expected_profile);
    272 
    273   MergeDataAndStartSyncing(
    274       profiles_from_web_db, data_list, expected_bundle, expected_change_list);
    275   autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
    276 }
    277 
    278 TEST_F(AutofillProfileSyncableServiceTest, MergeSimilarProfiles) {
    279   std::vector<AutofillProfile*> profiles_from_web_db;
    280   std::string guid_present1 = kGuid1;
    281   std::string guid_present2 = kGuid2;
    282   std::string guid_synced1 = kGuid3;
    283   std::string guid_synced2 = kGuid4;
    284   std::string origin_present1 = kHttpOrigin;
    285   std::string origin_present2 = kSettingsOrigin;
    286   std::string origin_synced1 = kHttpsOrigin;
    287   std::string origin_synced2 = kHttpsOrigin;
    288 
    289   profiles_from_web_db.push_back(
    290       new AutofillProfile(guid_present1, origin_present1));
    291   profiles_from_web_db.back()->SetRawInfo(
    292       autofill::NAME_FIRST, UTF8ToUTF16("John"));
    293   profiles_from_web_db.back()->SetRawInfo(
    294       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
    295   profiles_from_web_db.push_back(
    296       new AutofillProfile(guid_present2, origin_present2));
    297   profiles_from_web_db.back()->SetRawInfo(
    298       autofill::NAME_FIRST, UTF8ToUTF16("Tom"));
    299   profiles_from_web_db.back()->SetRawInfo(
    300       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("2 2nd st"));
    301 
    302   // The synced profiles are identical to the local ones, except that the guids
    303   // are different.
    304   syncer::SyncDataList data_list;
    305   AutofillProfile profile1(guid_synced1, origin_synced1);
    306   profile1.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("John"));
    307   profile1.SetRawInfo(autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
    308   profile1.SetRawInfo(autofill::COMPANY_NAME, UTF8ToUTF16("Frobbers, Inc."));
    309   data_list.push_back(autofill_syncable_service_.CreateData(profile1));
    310   AutofillProfile profile2(guid_synced2, origin_synced2);
    311   profile2.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Tom"));
    312   profile2.SetRawInfo(autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("2 2nd st"));
    313   profile2.SetRawInfo(autofill::COMPANY_NAME, UTF8ToUTF16("Fizzbang, LLC."));
    314   data_list.push_back(autofill_syncable_service_.CreateData(profile2));
    315 
    316   // The first profile should have its origin updated.
    317   // The second profile should remain as-is, because an unverified profile
    318   // should never overwrite a verified one.
    319   AutofillProfile expected_profile(profile1);
    320   expected_profile.set_origin(origin_present1);
    321   syncer::SyncChangeList expected_change_list;
    322   expected_change_list.push_back(
    323       syncer::SyncChange(FROM_HERE,
    324                          syncer::SyncChange::ACTION_ADD,
    325                          MockAutofillProfileSyncableService::CreateData(
    326                              *profiles_from_web_db.back())));
    327   expected_change_list.push_back(
    328       syncer::SyncChange(FROM_HERE,
    329                          syncer::SyncChange::ACTION_UPDATE,
    330                          MockAutofillProfileSyncableService::CreateData(
    331                              expected_profile)));
    332 
    333   MockAutofillProfileSyncableService::DataBundle expected_bundle;
    334   expected_bundle.profiles_to_delete.push_back(guid_present1);
    335   expected_bundle.profiles_to_add.push_back(&expected_profile);
    336   expected_bundle.profiles_to_add.push_back(&profile2);
    337 
    338   MergeDataAndStartSyncing(
    339       profiles_from_web_db, data_list, expected_bundle, expected_change_list);
    340   autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
    341 }
    342 
    343 // Ensure that no Sync events are generated to fill in missing origins from Sync
    344 // with explicitly present empty ones.  This ensures that the migration to add
    345 // origins to profiles does not generate lots of needless Sync updates.
    346 TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyOrigins) {
    347   std::vector<AutofillProfile*> profiles_from_web_db;
    348 
    349   // Create a profile with an empty origin.
    350   AutofillProfile profile(kGuid1, std::string());
    351   profile.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("John"));
    352   profile.SetRawInfo(autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("1 1st st"));
    353 
    354   profiles_from_web_db.push_back(new AutofillProfile(profile));
    355 
    356   // Create a Sync profile identical to |profile|, except with no origin set.
    357   sync_pb::EntitySpecifics specifics;
    358   sync_pb::AutofillProfileSpecifics* autofill_specifics =
    359       specifics.mutable_autofill_profile();
    360   autofill_specifics->set_guid(profile.guid());
    361   autofill_specifics->add_name_first("John");
    362   autofill_specifics->add_name_middle(std::string());
    363   autofill_specifics->add_name_last(std::string());
    364   autofill_specifics->add_email_address(std::string());
    365   autofill_specifics->add_phone_home_whole_number(std::string());
    366   autofill_specifics->set_address_home_line1("1 1st st");
    367   EXPECT_FALSE(autofill_specifics->has_origin());
    368 
    369   syncer::SyncDataList data_list;
    370   data_list.push_back(
    371       syncer::SyncData::CreateLocalData(
    372           profile.guid(), profile.guid(), specifics));
    373 
    374   MockAutofillProfileSyncableService::DataBundle expected_bundle;
    375   EXPECT_CALL(autofill_syncable_service_, LoadAutofillData(_))
    376       .Times(1)
    377       .WillOnce(DoAll(CopyData(&profiles_from_web_db), Return(true)));
    378   EXPECT_CALL(autofill_syncable_service_,
    379               SaveChangesToWebData(DataBundleCheck(expected_bundle)))
    380       .Times(1)
    381       .WillOnce(Return(true));
    382   EXPECT_CALL(*sync_processor_, ProcessSyncChanges(_, _)).Times(0);
    383 
    384   // Takes ownership of sync_processor_.
    385   autofill_syncable_service_.MergeDataAndStartSyncing(
    386       syncer::AUTOFILL_PROFILE, data_list,
    387       sync_processor_.PassAs<syncer::SyncChangeProcessor>(),
    388       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
    389 
    390   autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
    391 }
    392 
    393 TEST_F(AutofillProfileSyncableServiceTest, GetAllSyncData) {
    394   std::vector<AutofillProfile*> profiles_from_web_db;
    395   std::string guid_present1 = kGuid1;
    396   std::string guid_present2 = kGuid2;
    397 
    398   profiles_from_web_db.push_back(
    399       new AutofillProfile(guid_present1, kHttpOrigin));
    400   profiles_from_web_db.back()->SetRawInfo(
    401       autofill::NAME_FIRST, UTF8ToUTF16("John"));
    402   profiles_from_web_db.push_back(
    403       new AutofillProfile(guid_present2, kHttpsOrigin));
    404   profiles_from_web_db.back()->SetRawInfo(
    405       autofill::NAME_FIRST, UTF8ToUTF16("Jane"));
    406 
    407   syncer::SyncChangeList expected_change_list;
    408   expected_change_list.push_back(
    409       syncer::SyncChange(FROM_HERE,
    410                          syncer::SyncChange::ACTION_ADD,
    411                          MockAutofillProfileSyncableService::CreateData(
    412                              *profiles_from_web_db.front())));
    413   expected_change_list.push_back(
    414       syncer::SyncChange(FROM_HERE,
    415                          syncer::SyncChange::ACTION_ADD,
    416                          MockAutofillProfileSyncableService::CreateData(
    417                              *profiles_from_web_db.back())));
    418 
    419   MockAutofillProfileSyncableService::DataBundle expected_bundle;
    420   syncer::SyncDataList data_list;
    421   MergeDataAndStartSyncing(
    422       profiles_from_web_db, data_list, expected_bundle, expected_change_list);
    423 
    424   syncer::SyncDataList data =
    425       autofill_syncable_service_.GetAllSyncData(syncer::AUTOFILL_PROFILE);
    426 
    427   ASSERT_EQ(2U, data.size());
    428   EXPECT_EQ(guid_present1, data[0].GetSpecifics().autofill_profile().guid());
    429   EXPECT_EQ(guid_present2, data[1].GetSpecifics().autofill_profile().guid());
    430   EXPECT_EQ(kHttpOrigin, data[0].GetSpecifics().autofill_profile().origin());
    431   EXPECT_EQ(kHttpsOrigin, data[1].GetSpecifics().autofill_profile().origin());
    432 
    433   autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
    434 }
    435 
    436 TEST_F(AutofillProfileSyncableServiceTest, ProcessSyncChanges) {
    437   std::vector<AutofillProfile *> profiles_from_web_db;
    438   std::string guid_present = kGuid1;
    439   std::string guid_synced = kGuid2;
    440 
    441   syncer::SyncChangeList change_list;
    442   AutofillProfile profile(guid_synced, kHttpOrigin);
    443   profile.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Jane"));
    444   change_list.push_back(
    445       syncer::SyncChange(
    446           FROM_HERE,
    447           syncer::SyncChange::ACTION_ADD,
    448           MockAutofillProfileSyncableService::CreateData(profile)));
    449   AutofillProfile empty_profile(guid_present, kHttpsOrigin);
    450   change_list.push_back(
    451       syncer::SyncChange(
    452           FROM_HERE,
    453           syncer::SyncChange::ACTION_DELETE,
    454           MockAutofillProfileSyncableService::CreateData(empty_profile)));
    455 
    456   MockAutofillProfileSyncableService::DataBundle expected_bundle;
    457   expected_bundle.profiles_to_delete.push_back(guid_present);
    458   expected_bundle.profiles_to_add.push_back(&profile);
    459 
    460   EXPECT_CALL(autofill_syncable_service_, SaveChangesToWebData(
    461               DataBundleCheck(expected_bundle)))
    462       .Times(1)
    463       .WillOnce(Return(true));
    464 
    465   autofill_syncable_service_.set_sync_processor(sync_processor_.release());
    466   syncer::SyncError error = autofill_syncable_service_.ProcessSyncChanges(
    467       FROM_HERE, change_list);
    468 
    469   EXPECT_FALSE(error.IsSet());
    470 }
    471 
    472 TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileAdded) {
    473   // Will be owned by the syncable service.  Keep a reference available here for
    474   // verifying test expectations.
    475   TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
    476   autofill_syncable_service_.set_sync_processor(sync_change_processor);
    477 
    478   AutofillProfile profile(kGuid1, kHttpsOrigin);
    479   profile.SetRawInfo(autofill::NAME_FIRST, UTF8ToUTF16("Jane"));
    480   AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
    481   autofill_syncable_service_.AutofillProfileChanged(change);
    482 
    483   ASSERT_EQ(1U, sync_change_processor->changes().size());
    484   syncer::SyncChange result = sync_change_processor->changes()[0];
    485   EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());
    486 
    487   sync_pb::AutofillProfileSpecifics specifics =
    488       result.sync_data().GetSpecifics().autofill_profile();
    489   EXPECT_EQ(kGuid1, specifics.guid());
    490   EXPECT_EQ(kHttpsOrigin, specifics.origin());
    491   EXPECT_THAT(specifics.name_first(), testing::ElementsAre("Jane"));
    492 }
    493 
    494 TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileDeleted) {
    495   // Will be owned by the syncable service.  Keep a reference available here for
    496   // verifying test expectations.
    497   TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
    498   autofill_syncable_service_.set_sync_processor(sync_change_processor);
    499 
    500   AutofillProfileChange change(AutofillProfileChange::REMOVE, kGuid2, NULL);
    501   autofill_syncable_service_.AutofillProfileChanged(change);
    502 
    503   ASSERT_EQ(1U, sync_change_processor->changes().size());
    504   syncer::SyncChange result = sync_change_processor->changes()[0];
    505   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, result.change_type());
    506   sync_pb::AutofillProfileSpecifics specifics =
    507       result.sync_data().GetSpecifics().autofill_profile();
    508   EXPECT_EQ(kGuid2, specifics.guid());
    509 }
    510 
    511 TEST_F(AutofillProfileSyncableServiceTest, UpdateField) {
    512   AutofillProfile profile(kGuid1, kSettingsOrigin);
    513   std::string company1 = "A Company";
    514   std::string company2 = "Another Company";
    515   profile.SetRawInfo(autofill::COMPANY_NAME, UTF8ToUTF16(company1));
    516   EXPECT_FALSE(AutofillProfileSyncableService::UpdateField(
    517       autofill::COMPANY_NAME, company1, &profile));
    518   EXPECT_EQ(profile.GetRawInfo(autofill::COMPANY_NAME), UTF8ToUTF16(company1));
    519   EXPECT_TRUE(AutofillProfileSyncableService::UpdateField(
    520       autofill::COMPANY_NAME, company2, &profile));
    521   EXPECT_EQ(profile.GetRawInfo(autofill::COMPANY_NAME), UTF8ToUTF16(company2));
    522   EXPECT_FALSE(AutofillProfileSyncableService::UpdateField(
    523       autofill::COMPANY_NAME, company2, &profile));
    524   EXPECT_EQ(profile.GetRawInfo(autofill::COMPANY_NAME), UTF8ToUTF16(company2));
    525 }
    526 
    527 TEST_F(AutofillProfileSyncableServiceTest, UpdateMultivaluedField) {
    528   AutofillProfile profile(kGuid1, kHttpsOrigin);
    529 
    530   std::vector<string16> values;
    531   values.push_back(UTF8ToUTF16("1 (at) 1.com"));
    532   values.push_back(UTF8ToUTF16("2 (at) 1.com"));
    533   profile.SetRawMultiInfo(autofill::EMAIL_ADDRESS, values);
    534 
    535   ::google::protobuf::RepeatedPtrField<std::string> specifics_fields;
    536   specifics_fields.AddAllocated(new std::string("2 (at) 1.com"));
    537   specifics_fields.AddAllocated(new std::string("3 (at) 1.com"));
    538 
    539   EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField(
    540       autofill::EMAIL_ADDRESS, specifics_fields, &profile));
    541   profile.GetRawMultiInfo(autofill::EMAIL_ADDRESS, &values);
    542   ASSERT_TRUE(values.size() == 2);
    543   EXPECT_EQ(values[0], UTF8ToUTF16("2 (at) 1.com"));
    544   EXPECT_EQ(values[1], UTF8ToUTF16("3 (at) 1.com"));
    545 
    546   EXPECT_FALSE(AutofillProfileSyncableService::UpdateMultivaluedField(
    547       autofill::EMAIL_ADDRESS, specifics_fields, &profile));
    548   profile.GetRawMultiInfo(autofill::EMAIL_ADDRESS, &values);
    549   ASSERT_EQ(values.size(), 2U);
    550   EXPECT_EQ(values[0], UTF8ToUTF16("2 (at) 1.com"));
    551   EXPECT_EQ(values[1], UTF8ToUTF16("3 (at) 1.com"));
    552   EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField(
    553       autofill::EMAIL_ADDRESS,
    554       ::google::protobuf::RepeatedPtrField<std::string>(),
    555       &profile));
    556   profile.GetRawMultiInfo(autofill::EMAIL_ADDRESS, &values);
    557   ASSERT_EQ(values.size(), 1U);  // Always have at least an empty string.
    558   EXPECT_EQ(values[0], UTF8ToUTF16(""));
    559 }
    560 
    561 TEST_F(AutofillProfileSyncableServiceTest, MergeProfile) {
    562   AutofillProfile profile1(kGuid1, kHttpOrigin);
    563   profile1.SetRawInfo(
    564       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("111 First St."));
    565 
    566   std::vector<string16> values;
    567   values.push_back(UTF8ToUTF16("1 (at) 1.com"));
    568   values.push_back(UTF8ToUTF16("2 (at) 1.com"));
    569   profile1.SetRawMultiInfo(autofill::EMAIL_ADDRESS, values);
    570 
    571   AutofillProfile profile2(kGuid2, kHttpsOrigin);
    572   profile2.SetRawInfo(
    573       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("111 First St."));
    574 
    575   // |values| now is [ "1 (at) 1.com", "2 (at) 1.com", "3 (at) 1.com" ].
    576   values.push_back(UTF8ToUTF16("3 (at) 1.com"));
    577   profile2.SetRawMultiInfo(autofill::EMAIL_ADDRESS, values);
    578 
    579   values.clear();
    580   values.push_back(UTF8ToUTF16("John"));
    581   profile1.SetRawMultiInfo(autofill::NAME_FIRST, values);
    582   values.push_back(UTF8ToUTF16("Jane"));
    583   profile2.SetRawMultiInfo(autofill::NAME_FIRST, values);
    584 
    585   values.clear();
    586   values.push_back(UTF8ToUTF16("Doe"));
    587   profile1.SetRawMultiInfo(autofill::NAME_LAST, values);
    588   values.push_back(UTF8ToUTF16("Other"));
    589   profile2.SetRawMultiInfo(autofill::NAME_LAST, values);
    590 
    591   values.clear();
    592   values.push_back(UTF8ToUTF16("650234567"));
    593   profile2.SetRawMultiInfo(autofill::PHONE_HOME_WHOLE_NUMBER, values);
    594 
    595   EXPECT_FALSE(AutofillProfileSyncableService::MergeProfile(profile2,
    596                                                             &profile1,
    597                                                             "en-US"));
    598 
    599   profile1.GetRawMultiInfo(autofill::NAME_FIRST, &values);
    600   ASSERT_EQ(values.size(), 2U);
    601   EXPECT_EQ(values[0], UTF8ToUTF16("John"));
    602   EXPECT_EQ(values[1], UTF8ToUTF16("Jane"));
    603 
    604   profile1.GetRawMultiInfo(autofill::NAME_LAST, &values);
    605   ASSERT_EQ(values.size(), 2U);
    606   EXPECT_EQ(values[0], UTF8ToUTF16("Doe"));
    607   EXPECT_EQ(values[1], UTF8ToUTF16("Other"));
    608 
    609   profile1.GetRawMultiInfo(autofill::EMAIL_ADDRESS, &values);
    610   ASSERT_EQ(values.size(), 3U);
    611   EXPECT_EQ(values[0], UTF8ToUTF16("1 (at) 1.com"));
    612   EXPECT_EQ(values[1], UTF8ToUTF16("2 (at) 1.com"));
    613   EXPECT_EQ(values[2], UTF8ToUTF16("3 (at) 1.com"));
    614 
    615   profile1.GetRawMultiInfo(autofill::PHONE_HOME_WHOLE_NUMBER, &values);
    616   ASSERT_EQ(values.size(), 1U);
    617   EXPECT_EQ(values[0], UTF8ToUTF16("650234567"));
    618 
    619   EXPECT_EQ(profile2.origin(), profile1.origin());
    620 
    621   AutofillProfile profile3(kGuid3, kHttpOrigin);
    622   profile3.SetRawInfo(
    623       autofill::ADDRESS_HOME_LINE1, UTF8ToUTF16("111 First St."));
    624 
    625   values.clear();
    626   values.push_back(UTF8ToUTF16("Jane"));
    627   profile3.SetRawMultiInfo(autofill::NAME_FIRST, values);
    628 
    629   values.clear();
    630   values.push_back(UTF8ToUTF16("Doe"));
    631   profile3.SetRawMultiInfo(autofill::NAME_LAST, values);
    632 
    633   EXPECT_TRUE(AutofillProfileSyncableService::MergeProfile(profile3,
    634                                                            &profile1,
    635                                                             "en-US"));
    636 
    637   profile1.GetRawMultiInfo(autofill::NAME_FIRST, &values);
    638   ASSERT_EQ(values.size(), 3U);
    639   EXPECT_EQ(values[0], UTF8ToUTF16("John"));
    640   EXPECT_EQ(values[1], UTF8ToUTF16("Jane"));
    641   EXPECT_EQ(values[2], UTF8ToUTF16("Jane"));
    642 
    643   profile1.GetRawMultiInfo(autofill::NAME_LAST, &values);
    644   ASSERT_EQ(values.size(), 3U);
    645   EXPECT_EQ(values[0], UTF8ToUTF16("Doe"));
    646   EXPECT_EQ(values[1], UTF8ToUTF16("Other"));
    647   EXPECT_EQ(values[2], UTF8ToUTF16("Doe"));
    648 
    649   // Middle name should have three entries as well.
    650   profile1.GetRawMultiInfo(autofill::NAME_MIDDLE, &values);
    651   ASSERT_EQ(values.size(), 3U);
    652   EXPECT_TRUE(values[0].empty());
    653   EXPECT_TRUE(values[1].empty());
    654   EXPECT_TRUE(values[2].empty());
    655 
    656   profile1.GetRawMultiInfo(autofill::EMAIL_ADDRESS, &values);
    657   ASSERT_EQ(values.size(), 3U);
    658   EXPECT_EQ(values[0], UTF8ToUTF16("1 (at) 1.com"));
    659   EXPECT_EQ(values[1], UTF8ToUTF16("2 (at) 1.com"));
    660   EXPECT_EQ(values[2], UTF8ToUTF16("3 (at) 1.com"));
    661 
    662   profile1.GetRawMultiInfo(autofill::PHONE_HOME_WHOLE_NUMBER, &values);
    663   ASSERT_EQ(values.size(), 1U);
    664   EXPECT_EQ(values[0], UTF8ToUTF16("650234567"));
    665 }
    666