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