autofill_profile_syncable_service_unittest.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
1// Copyright 2014 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 "components/autofill/core/browser/autofill_profile.h"
9#include "components/autofill/core/browser/webdata/autofill_change.h"
10#include "components/autofill/core/browser/webdata/autofill_profile_syncable_service.h"
11#include "sync/api/sync_error_factory.h"
12#include "sync/api/sync_error_factory_mock.h"
13#include "sync/protocol/sync.pb.h"
14#include "testing/gmock/include/gmock/gmock.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace autofill {
18
19using ::testing::_;
20using ::testing::DoAll;
21using ::testing::Eq;
22using ::testing::Return;
23using ::testing::Property;
24using base::ASCIIToUTF16;
25
26namespace {
27
28// Some guids for testing.
29const char kGuid1[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44B";
30const char kGuid2[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44C";
31const char kGuid3[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44D";
32const char kGuid4[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44E";
33const char kHttpOrigin[] = "http://www.example.com/";
34const char kHttpsOrigin[] = "https://www.example.com/";
35const char kSettingsOrigin[] = "Chrome settings";
36
37class MockAutofillProfileSyncableService
38    : public AutofillProfileSyncableService {
39 public:
40  MockAutofillProfileSyncableService() {}
41  virtual ~MockAutofillProfileSyncableService() {}
42
43  using AutofillProfileSyncableService::DataBundle;
44  using AutofillProfileSyncableService::set_sync_processor;
45  using AutofillProfileSyncableService::CreateData;
46
47  MOCK_METHOD1(LoadAutofillData, bool(std::vector<AutofillProfile*>*));
48  MOCK_METHOD1(SaveChangesToWebData,
49               bool(const AutofillProfileSyncableService::DataBundle&));
50};
51
52ACTION_P(CopyData, data) {
53  arg0->resize(data->size());
54  std::copy(data->begin(), data->end(), arg0->begin());
55}
56
57MATCHER_P(CheckSyncChanges, n_sync_changes_list, "") {
58  if (arg.size() != n_sync_changes_list.size())
59    return false;
60  syncer::SyncChangeList::const_iterator passed, expected;
61  for (passed = arg.begin(), expected = n_sync_changes_list.begin();
62       passed != arg.end() && expected != n_sync_changes_list.end();
63       ++passed, ++expected) {
64    DCHECK(passed->IsValid());
65    if (passed->change_type() != expected->change_type())
66      return false;
67    if (passed->sync_data().GetSpecifics().SerializeAsString() !=
68            expected->sync_data().GetSpecifics().SerializeAsString()) {
69      return false;
70    }
71  }
72  return true;
73}
74
75MATCHER_P(DataBundleCheck, n_bundle, "") {
76  if ((arg.profiles_to_delete.size() != n_bundle.profiles_to_delete.size()) ||
77      (arg.profiles_to_update.size() != n_bundle.profiles_to_update.size()) ||
78      (arg.profiles_to_add.size() != n_bundle.profiles_to_add.size()))
79    return false;
80  for (size_t i = 0; i < arg.profiles_to_delete.size(); ++i) {
81    if (arg.profiles_to_delete[i] != n_bundle.profiles_to_delete[i])
82      return false;
83  }
84  for (size_t i = 0; i < arg.profiles_to_update.size(); ++i) {
85    if (*arg.profiles_to_update[i] != *n_bundle.profiles_to_update[i])
86      return false;
87  }
88  for (size_t i = 0; i < arg.profiles_to_add.size(); ++i) {
89    if (*arg.profiles_to_add[i] != *n_bundle.profiles_to_add[i])
90      return false;
91  }
92  return true;
93}
94
95class MockSyncChangeProcessor : public syncer::SyncChangeProcessor {
96 public:
97  MockSyncChangeProcessor() {}
98  virtual ~MockSyncChangeProcessor() {}
99
100  MOCK_METHOD2(ProcessSyncChanges,
101               syncer::SyncError(const tracked_objects::Location&,
102                                 const syncer::SyncChangeList&));
103  virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type)
104      const OVERRIDE { return syncer::SyncDataList(); }
105};
106
107class TestSyncChangeProcessor : public syncer::SyncChangeProcessor {
108 public:
109  TestSyncChangeProcessor() {}
110  virtual ~TestSyncChangeProcessor() {}
111
112  virtual syncer::SyncError ProcessSyncChanges(
113      const tracked_objects::Location& location,
114      const syncer::SyncChangeList& changes) OVERRIDE {
115    changes_ = changes;
116    return syncer::SyncError();
117  }
118
119  virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
120      OVERRIDE {
121    return syncer::SyncDataList();
122  }
123
124  const syncer::SyncChangeList& changes() { return changes_; }
125
126 private:
127  syncer::SyncChangeList changes_;
128};
129
130// Returns a profile with all fields set.  Contains identical data to the data
131// returned from ConstructCompleteSyncData().
132scoped_ptr<AutofillProfile> ConstructCompleteProfile() {
133  scoped_ptr<AutofillProfile> profile(
134      new AutofillProfile(kGuid1, kHttpsOrigin));
135
136  std::vector<base::string16> names;
137  names.push_back(ASCIIToUTF16("John K. Doe, Jr."));
138  names.push_back(ASCIIToUTF16("Jane Luise Smith MD"));
139  profile->SetRawMultiInfo(NAME_FULL, names);
140
141  std::vector<base::string16> emails;
142  emails.push_back(ASCIIToUTF16("user@example.com"));
143  emails.push_back(ASCIIToUTF16("superuser@example.org"));
144  profile->SetRawMultiInfo(EMAIL_ADDRESS, emails);
145
146  std::vector<base::string16> phones;
147  phones.push_back(ASCIIToUTF16("1.800.555.1234"));
148  phones.push_back(ASCIIToUTF16("1.866.650.0000"));
149  profile->SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, phones);
150
151  profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
152                      ASCIIToUTF16("123 Fake St.\n"
153                                   "Apt. 42"));
154  EXPECT_EQ(ASCIIToUTF16("123 Fake St."),
155            profile->GetRawInfo(ADDRESS_HOME_LINE1));
156  EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile->GetRawInfo(ADDRESS_HOME_LINE2));
157
158  profile->SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Google, Inc."));
159  profile->SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("Mountain View"));
160  profile->SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("California"));
161  profile->SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("94043"));
162  profile->SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
163  profile->SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("CEDEX"));
164  profile->SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
165                      ASCIIToUTF16("Santa Clara"));
166  profile->set_language_code("en");
167  return profile.Pass();
168}
169
170// Returns SyncData with all Autofill profile fields set.  Contains identical
171// data to the data returned from ConstructCompleteProfile().
172syncer::SyncData ConstructCompleteSyncData() {
173  sync_pb::EntitySpecifics entity_specifics;
174  sync_pb::AutofillProfileSpecifics* specifics =
175      entity_specifics.mutable_autofill_profile();
176
177  specifics->set_guid(kGuid1);
178  specifics->set_origin(kHttpsOrigin);
179
180  specifics->add_name_first("John");
181  specifics->add_name_middle("K.");
182  specifics->add_name_last("Doe");
183  specifics->add_name_full("John K. Doe, Jr.");
184
185  specifics->add_name_first("Jane");
186  specifics->add_name_middle("Luise");
187  specifics->add_name_last("Smith");
188  specifics->add_name_full("Jane Luise Smith MD");
189
190  specifics->add_email_address("user@example.com");
191  specifics->add_email_address("superuser@example.org");
192
193  specifics->add_phone_home_whole_number("1.800.555.1234");
194  specifics->add_phone_home_whole_number("1.866.650.0000");
195
196  specifics->set_address_home_line1("123 Fake St.");
197  specifics->set_address_home_line2("Apt. 42");
198  specifics->set_address_home_street_address("123 Fake St.\n"
199                                             "Apt. 42");
200
201  specifics->set_company_name("Google, Inc.");
202  specifics->set_address_home_city("Mountain View");
203  specifics->set_address_home_state("California");
204  specifics->set_address_home_zip("94043");
205  specifics->set_address_home_country("US");
206  specifics->set_address_home_sorting_code("CEDEX");
207  specifics->set_address_home_dependent_locality("Santa Clara");
208  specifics->set_address_home_language_code("en");
209
210  return syncer::SyncData::CreateLocalData(kGuid1, kGuid1, entity_specifics);
211}
212
213}  // namespace
214
215class AutofillProfileSyncableServiceTest : public testing::Test {
216 public:
217  AutofillProfileSyncableServiceTest() {}
218
219  virtual void SetUp() OVERRIDE {
220    sync_processor_.reset(new MockSyncChangeProcessor);
221  }
222
223  // Wrapper around AutofillProfileSyncableService::MergeDataAndStartSyncing()
224  // that also verifies expectations.
225  void MergeDataAndStartSyncing(
226      const std::vector<AutofillProfile*>& profiles_from_web_db,
227      const syncer::SyncDataList& data_list,
228      const MockAutofillProfileSyncableService::DataBundle& expected_bundle,
229      const syncer::SyncChangeList& expected_change_list) {
230    EXPECT_CALL(autofill_syncable_service_, LoadAutofillData(_))
231        .Times(1)
232        .WillOnce(DoAll(CopyData(&profiles_from_web_db), Return(true)));
233    EXPECT_CALL(autofill_syncable_service_,
234                SaveChangesToWebData(DataBundleCheck(expected_bundle)))
235        .Times(1)
236        .WillOnce(Return(true));
237    if (expected_change_list.empty()) {
238      EXPECT_CALL(*sync_processor_, ProcessSyncChanges(_, _)).Times(0);
239    } else {
240      ON_CALL(*sync_processor_, ProcessSyncChanges(_, _))
241          .WillByDefault(Return(syncer::SyncError()));
242      EXPECT_CALL(*sync_processor_,
243                  ProcessSyncChanges(_, CheckSyncChanges(expected_change_list)))
244          .Times(1)
245          .WillOnce(Return(syncer::SyncError()));
246    }
247
248    // Takes ownership of sync_processor_.
249    autofill_syncable_service_.MergeDataAndStartSyncing(
250        syncer::AUTOFILL_PROFILE, data_list,
251        sync_processor_.PassAs<syncer::SyncChangeProcessor>(),
252        scoped_ptr<syncer::SyncErrorFactory>(
253            new syncer::SyncErrorFactoryMock()));
254  }
255
256 protected:
257  base::MessageLoop message_loop_;
258  MockAutofillProfileSyncableService autofill_syncable_service_;
259  scoped_ptr<MockSyncChangeProcessor> sync_processor_;
260};
261
262TEST_F(AutofillProfileSyncableServiceTest, MergeDataAndStartSyncing) {
263  std::vector<AutofillProfile*> profiles_from_web_db;
264  std::string guid_present1 = kGuid1;
265  std::string guid_present2 = kGuid2;
266  std::string guid_synced1 = kGuid3;
267  std::string guid_synced2 = kGuid4;
268  std::string origin_present1 = kHttpOrigin;
269  std::string origin_present2 = std::string();
270  std::string origin_synced1 = kHttpsOrigin;
271  std::string origin_synced2 = kSettingsOrigin;
272
273  profiles_from_web_db.push_back(
274      new AutofillProfile(guid_present1, origin_present1));
275  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
276  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
277                                          ASCIIToUTF16("1 1st st"));
278  profiles_from_web_db.push_back(
279      new AutofillProfile(guid_present2, origin_present2));
280  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
281  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
282                                          ASCIIToUTF16("2 2nd st"));
283
284  syncer::SyncDataList data_list;
285  AutofillProfile profile1(guid_synced1, origin_synced1);
286  profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
287  data_list.push_back(autofill_syncable_service_.CreateData(profile1));
288  AutofillProfile profile2(guid_synced2, origin_synced2);
289  profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Harry"));
290  data_list.push_back(autofill_syncable_service_.CreateData(profile2));
291  // This one will have the name and origin updated.
292  AutofillProfile profile3(guid_present2, origin_synced2);
293  profile3.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom Doe"));
294  data_list.push_back(autofill_syncable_service_.CreateData(profile3));
295
296  syncer::SyncChangeList expected_change_list;
297  expected_change_list.push_back(
298      syncer::SyncChange(FROM_HERE,
299                         syncer::SyncChange::ACTION_ADD,
300                         MockAutofillProfileSyncableService::CreateData(
301                             *profiles_from_web_db.front())));
302
303  MockAutofillProfileSyncableService::DataBundle expected_bundle;
304  expected_bundle.profiles_to_add.push_back(&profile1);
305  expected_bundle.profiles_to_add.push_back(&profile2);
306  expected_bundle.profiles_to_update.push_back(&profile3);
307
308  MergeDataAndStartSyncing(
309      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
310  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
311}
312
313TEST_F(AutofillProfileSyncableServiceTest, MergeIdenticalProfiles) {
314  std::vector<AutofillProfile*> profiles_from_web_db;
315  std::string guid_present1 = kGuid1;
316  std::string guid_present2 = kGuid2;
317  std::string guid_synced1 = kGuid3;
318  std::string guid_synced2 = kGuid4;
319  std::string origin_present1 = kHttpOrigin;
320  std::string origin_present2 = kSettingsOrigin;
321  std::string origin_synced1 = kHttpsOrigin;
322  std::string origin_synced2 = kHttpsOrigin;
323
324  profiles_from_web_db.push_back(
325      new AutofillProfile(guid_present1, origin_present1));
326  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
327  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
328                                          ASCIIToUTF16("1 1st st"));
329  profiles_from_web_db.push_back(
330      new AutofillProfile(guid_present2, origin_present2));
331  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
332  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
333                                          ASCIIToUTF16("2 2nd st"));
334
335  // The synced profiles are identical to the local ones, except that the guids
336  // are different.
337  syncer::SyncDataList data_list;
338  AutofillProfile profile1(guid_synced1, origin_synced1);
339  profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
340  profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
341  data_list.push_back(autofill_syncable_service_.CreateData(profile1));
342  AutofillProfile profile2(guid_synced2, origin_synced2);
343  profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
344  profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st"));
345  data_list.push_back(autofill_syncable_service_.CreateData(profile2));
346
347  AutofillProfile expected_profile(profile2);
348  expected_profile.set_origin(kSettingsOrigin);
349  syncer::SyncChangeList expected_change_list;
350  expected_change_list.push_back(
351      syncer::SyncChange(FROM_HERE,
352                         syncer::SyncChange::ACTION_UPDATE,
353                         MockAutofillProfileSyncableService::CreateData(
354                             expected_profile)));
355
356  MockAutofillProfileSyncableService::DataBundle expected_bundle;
357  expected_bundle.profiles_to_delete.push_back(guid_present1);
358  expected_bundle.profiles_to_delete.push_back(guid_present2);
359  expected_bundle.profiles_to_add.push_back(&profile1);
360  expected_bundle.profiles_to_add.push_back(&expected_profile);
361
362  MergeDataAndStartSyncing(
363      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
364  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
365}
366
367TEST_F(AutofillProfileSyncableServiceTest, MergeSimilarProfiles) {
368  std::vector<AutofillProfile*> profiles_from_web_db;
369  std::string guid_present1 = kGuid1;
370  std::string guid_present2 = kGuid2;
371  std::string guid_synced1 = kGuid3;
372  std::string guid_synced2 = kGuid4;
373  std::string origin_present1 = kHttpOrigin;
374  std::string origin_present2 = kSettingsOrigin;
375  std::string origin_synced1 = kHttpsOrigin;
376  std::string origin_synced2 = kHttpsOrigin;
377
378  profiles_from_web_db.push_back(
379      new AutofillProfile(guid_present1, origin_present1));
380  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
381  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
382                                          ASCIIToUTF16("1 1st st"));
383  profiles_from_web_db.push_back(
384      new AutofillProfile(guid_present2, origin_present2));
385  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
386  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
387                                          ASCIIToUTF16("2 2nd st"));
388
389  // The synced profiles are identical to the local ones, except that the guids
390  // are different.
391  syncer::SyncDataList data_list;
392  AutofillProfile profile1(guid_synced1, origin_synced1);
393  profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
394  profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
395  profile1.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Frobbers, Inc."));
396  data_list.push_back(autofill_syncable_service_.CreateData(profile1));
397  AutofillProfile profile2(guid_synced2, origin_synced2);
398  profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
399  profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st"));
400  profile2.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Fizzbang, LLC."));
401  data_list.push_back(autofill_syncable_service_.CreateData(profile2));
402
403  // The first profile should have its origin updated.
404  // The second profile should remain as-is, because an unverified profile
405  // should never overwrite a verified one.
406  AutofillProfile expected_profile(profile1);
407  expected_profile.set_origin(origin_present1);
408  syncer::SyncChangeList expected_change_list;
409  expected_change_list.push_back(
410      syncer::SyncChange(FROM_HERE,
411                         syncer::SyncChange::ACTION_ADD,
412                         MockAutofillProfileSyncableService::CreateData(
413                             *profiles_from_web_db.back())));
414  expected_change_list.push_back(
415      syncer::SyncChange(FROM_HERE,
416                         syncer::SyncChange::ACTION_UPDATE,
417                         MockAutofillProfileSyncableService::CreateData(
418                             expected_profile)));
419
420  MockAutofillProfileSyncableService::DataBundle expected_bundle;
421  expected_bundle.profiles_to_delete.push_back(guid_present1);
422  expected_bundle.profiles_to_add.push_back(&expected_profile);
423  expected_bundle.profiles_to_add.push_back(&profile2);
424
425  MergeDataAndStartSyncing(
426      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
427  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
428}
429
430// Ensure that no Sync events are generated to fill in missing origins from Sync
431// with explicitly present empty ones.  This ensures that the migration to add
432// origins to profiles does not generate lots of needless Sync updates.
433TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyOrigins) {
434  std::vector<AutofillProfile*> profiles_from_web_db;
435
436  // Create a profile with an empty origin.
437  AutofillProfile profile(kGuid1, std::string());
438  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
439  profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
440
441  profiles_from_web_db.push_back(new AutofillProfile(profile));
442
443  // Create a Sync profile identical to |profile|, except with no origin set.
444  sync_pb::EntitySpecifics specifics;
445  sync_pb::AutofillProfileSpecifics* autofill_specifics =
446      specifics.mutable_autofill_profile();
447  autofill_specifics->set_guid(profile.guid());
448  autofill_specifics->add_name_first("John");
449  autofill_specifics->add_name_middle(std::string());
450  autofill_specifics->add_name_last(std::string());
451  autofill_specifics->add_name_full("John");
452  autofill_specifics->add_email_address(std::string());
453  autofill_specifics->add_phone_home_whole_number(std::string());
454  autofill_specifics->set_address_home_line1("1 1st st");
455  EXPECT_FALSE(autofill_specifics->has_origin());
456
457  syncer::SyncDataList data_list;
458  data_list.push_back(
459      syncer::SyncData::CreateLocalData(
460          profile.guid(), profile.guid(), specifics));
461
462  MockAutofillProfileSyncableService::DataBundle expected_bundle;
463  syncer::SyncChangeList expected_change_list;
464  MergeDataAndStartSyncing(
465      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
466  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
467}
468
469TEST_F(AutofillProfileSyncableServiceTest, GetAllSyncData) {
470  std::vector<AutofillProfile*> profiles_from_web_db;
471  std::string guid_present1 = kGuid1;
472  std::string guid_present2 = kGuid2;
473
474  profiles_from_web_db.push_back(
475      new AutofillProfile(guid_present1, kHttpOrigin));
476  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
477  profiles_from_web_db.push_back(
478      new AutofillProfile(guid_present2, kHttpsOrigin));
479  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
480
481  syncer::SyncChangeList expected_change_list;
482  expected_change_list.push_back(
483      syncer::SyncChange(FROM_HERE,
484                         syncer::SyncChange::ACTION_ADD,
485                         MockAutofillProfileSyncableService::CreateData(
486                             *profiles_from_web_db.front())));
487  expected_change_list.push_back(
488      syncer::SyncChange(FROM_HERE,
489                         syncer::SyncChange::ACTION_ADD,
490                         MockAutofillProfileSyncableService::CreateData(
491                             *profiles_from_web_db.back())));
492
493  MockAutofillProfileSyncableService::DataBundle expected_bundle;
494  syncer::SyncDataList data_list;
495  MergeDataAndStartSyncing(
496      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
497
498  syncer::SyncDataList data =
499      autofill_syncable_service_.GetAllSyncData(syncer::AUTOFILL_PROFILE);
500
501  ASSERT_EQ(2U, data.size());
502  EXPECT_EQ(guid_present1, data[0].GetSpecifics().autofill_profile().guid());
503  EXPECT_EQ(guid_present2, data[1].GetSpecifics().autofill_profile().guid());
504  EXPECT_EQ(kHttpOrigin, data[0].GetSpecifics().autofill_profile().origin());
505  EXPECT_EQ(kHttpsOrigin, data[1].GetSpecifics().autofill_profile().origin());
506
507  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
508}
509
510TEST_F(AutofillProfileSyncableServiceTest, ProcessSyncChanges) {
511  std::vector<AutofillProfile *> profiles_from_web_db;
512  std::string guid_present = kGuid1;
513  std::string guid_synced = kGuid2;
514
515  syncer::SyncChangeList change_list;
516  AutofillProfile profile(guid_synced, kHttpOrigin);
517  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
518  change_list.push_back(
519      syncer::SyncChange(
520          FROM_HERE,
521          syncer::SyncChange::ACTION_ADD,
522          MockAutofillProfileSyncableService::CreateData(profile)));
523  AutofillProfile empty_profile(guid_present, kHttpsOrigin);
524  change_list.push_back(
525      syncer::SyncChange(
526          FROM_HERE,
527          syncer::SyncChange::ACTION_DELETE,
528          MockAutofillProfileSyncableService::CreateData(empty_profile)));
529
530  MockAutofillProfileSyncableService::DataBundle expected_bundle;
531  expected_bundle.profiles_to_delete.push_back(guid_present);
532  expected_bundle.profiles_to_add.push_back(&profile);
533
534  EXPECT_CALL(autofill_syncable_service_, SaveChangesToWebData(
535              DataBundleCheck(expected_bundle)))
536      .Times(1)
537      .WillOnce(Return(true));
538
539  autofill_syncable_service_.set_sync_processor(sync_processor_.release());
540  syncer::SyncError error = autofill_syncable_service_.ProcessSyncChanges(
541      FROM_HERE, change_list);
542
543  EXPECT_FALSE(error.IsSet());
544}
545
546TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileAdded) {
547  // Will be owned by the syncable service.  Keep a reference available here for
548  // verifying test expectations.
549  TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
550  autofill_syncable_service_.set_sync_processor(sync_change_processor);
551
552  AutofillProfile profile(kGuid1, kHttpsOrigin);
553  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
554  AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
555  autofill_syncable_service_.AutofillProfileChanged(change);
556
557  ASSERT_EQ(1U, sync_change_processor->changes().size());
558  syncer::SyncChange result = sync_change_processor->changes()[0];
559  EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());
560
561  sync_pb::AutofillProfileSpecifics specifics =
562      result.sync_data().GetSpecifics().autofill_profile();
563  EXPECT_EQ(kGuid1, specifics.guid());
564  EXPECT_EQ(kHttpsOrigin, specifics.origin());
565  EXPECT_THAT(specifics.name_first(), testing::ElementsAre("Jane"));
566}
567
568TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileDeleted) {
569  // Will be owned by the syncable service.  Keep a reference available here for
570  // verifying test expectations.
571  TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
572  autofill_syncable_service_.set_sync_processor(sync_change_processor);
573
574  AutofillProfileChange change(AutofillProfileChange::REMOVE, kGuid2, NULL);
575  autofill_syncable_service_.AutofillProfileChanged(change);
576
577  ASSERT_EQ(1U, sync_change_processor->changes().size());
578  syncer::SyncChange result = sync_change_processor->changes()[0];
579  EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, result.change_type());
580  sync_pb::AutofillProfileSpecifics specifics =
581      result.sync_data().GetSpecifics().autofill_profile();
582  EXPECT_EQ(kGuid2, specifics.guid());
583}
584
585TEST_F(AutofillProfileSyncableServiceTest, UpdateField) {
586  AutofillProfile profile(kGuid1, kSettingsOrigin);
587  std::string company1 = "A Company";
588  std::string company2 = "Another Company";
589  profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16(company1));
590  EXPECT_FALSE(AutofillProfileSyncableService::UpdateField(
591      COMPANY_NAME, company1, &profile));
592  EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company1));
593  EXPECT_TRUE(AutofillProfileSyncableService::UpdateField(
594      COMPANY_NAME, company2, &profile));
595  EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company2));
596  EXPECT_FALSE(AutofillProfileSyncableService::UpdateField(
597      COMPANY_NAME, company2, &profile));
598  EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company2));
599}
600
601TEST_F(AutofillProfileSyncableServiceTest, UpdateMultivaluedField) {
602  AutofillProfile profile(kGuid1, kHttpsOrigin);
603
604  std::vector<base::string16> values;
605  values.push_back(ASCIIToUTF16("1@1.com"));
606  values.push_back(ASCIIToUTF16("2@1.com"));
607  profile.SetRawMultiInfo(EMAIL_ADDRESS, values);
608
609  ::google::protobuf::RepeatedPtrField<std::string> specifics_fields;
610  specifics_fields.AddAllocated(new std::string("2@1.com"));
611  specifics_fields.AddAllocated(new std::string("3@1.com"));
612
613  EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField(
614      EMAIL_ADDRESS, specifics_fields, &profile));
615  profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
616  ASSERT_TRUE(values.size() == 2);
617  EXPECT_EQ(values[0], ASCIIToUTF16("2@1.com"));
618  EXPECT_EQ(values[1], ASCIIToUTF16("3@1.com"));
619
620  EXPECT_FALSE(AutofillProfileSyncableService::UpdateMultivaluedField(
621      EMAIL_ADDRESS, specifics_fields, &profile));
622  profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
623  ASSERT_EQ(values.size(), 2U);
624  EXPECT_EQ(values[0], ASCIIToUTF16("2@1.com"));
625  EXPECT_EQ(values[1], ASCIIToUTF16("3@1.com"));
626  EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField(
627      EMAIL_ADDRESS, ::google::protobuf::RepeatedPtrField<std::string>(),
628      &profile));
629  profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
630  ASSERT_EQ(values.size(), 1U);  // Always have at least an empty string.
631  EXPECT_EQ(values[0], ASCIIToUTF16(""));
632}
633
634TEST_F(AutofillProfileSyncableServiceTest, MergeProfile) {
635  AutofillProfile profile1(kGuid1, kHttpOrigin);
636  profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));
637
638  std::vector<base::string16> values;
639  values.push_back(ASCIIToUTF16("1@1.com"));
640  values.push_back(ASCIIToUTF16("2@1.com"));
641  profile1.SetRawMultiInfo(EMAIL_ADDRESS, values);
642
643  AutofillProfile profile2(kGuid2, kHttpsOrigin);
644  profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));
645
646  // |values| now is [ "1@1.com", "2@1.com", "3@1.com" ].
647  values.push_back(ASCIIToUTF16("3@1.com"));
648  profile2.SetRawMultiInfo(EMAIL_ADDRESS, values);
649
650  values.clear();
651  values.push_back(ASCIIToUTF16("John"));
652  profile1.SetRawMultiInfo(NAME_FIRST, values);
653  values.push_back(ASCIIToUTF16("Jane"));
654  profile2.SetRawMultiInfo(NAME_FIRST, values);
655
656  values.clear();
657  values.push_back(ASCIIToUTF16("Doe"));
658  profile1.SetRawMultiInfo(NAME_LAST, values);
659  values.push_back(ASCIIToUTF16("Other"));
660  profile2.SetRawMultiInfo(NAME_LAST, values);
661
662  values.clear();
663  values.push_back(ASCIIToUTF16("650234567"));
664  profile2.SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, values);
665
666  profile1.set_language_code("en");
667
668  EXPECT_FALSE(AutofillProfileSyncableService::MergeProfile(profile2,
669                                                            &profile1,
670                                                            "en-US"));
671
672  profile1.GetRawMultiInfo(NAME_FIRST, &values);
673  ASSERT_EQ(values.size(), 2U);
674  EXPECT_EQ(values[0], ASCIIToUTF16("John"));
675  EXPECT_EQ(values[1], ASCIIToUTF16("Jane"));
676
677  profile1.GetRawMultiInfo(NAME_LAST, &values);
678  ASSERT_EQ(values.size(), 2U);
679  EXPECT_EQ(values[0], ASCIIToUTF16("Doe"));
680  EXPECT_EQ(values[1], ASCIIToUTF16("Other"));
681
682  profile1.GetRawMultiInfo(EMAIL_ADDRESS, &values);
683  ASSERT_EQ(values.size(), 3U);
684  EXPECT_EQ(values[0], ASCIIToUTF16("1@1.com"));
685  EXPECT_EQ(values[1], ASCIIToUTF16("2@1.com"));
686  EXPECT_EQ(values[2], ASCIIToUTF16("3@1.com"));
687
688  profile1.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values);
689  ASSERT_EQ(values.size(), 1U);
690  EXPECT_EQ(values[0], ASCIIToUTF16("650234567"));
691
692  EXPECT_EQ(profile2.origin(), profile1.origin());
693
694  AutofillProfile profile3(kGuid3, kHttpOrigin);
695  profile3.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));
696
697  values.clear();
698  values.push_back(ASCIIToUTF16("Jane"));
699  profile3.SetRawMultiInfo(NAME_FIRST, values);
700
701  values.clear();
702  values.push_back(ASCIIToUTF16("Doe"));
703  profile3.SetRawMultiInfo(NAME_LAST, values);
704
705  EXPECT_TRUE(AutofillProfileSyncableService::MergeProfile(profile3,
706                                                           &profile1,
707                                                            "en-US"));
708
709  profile1.GetRawMultiInfo(NAME_FIRST, &values);
710  ASSERT_EQ(values.size(), 3U);
711  EXPECT_EQ(values[0], ASCIIToUTF16("John"));
712  EXPECT_EQ(values[1], ASCIIToUTF16("Jane"));
713  EXPECT_EQ(values[2], ASCIIToUTF16("Jane"));
714
715  profile1.GetRawMultiInfo(NAME_LAST, &values);
716  ASSERT_EQ(values.size(), 3U);
717  EXPECT_EQ(values[0], ASCIIToUTF16("Doe"));
718  EXPECT_EQ(values[1], ASCIIToUTF16("Other"));
719  EXPECT_EQ(values[2], ASCIIToUTF16("Doe"));
720
721  // Middle name should have three entries as well.
722  profile1.GetRawMultiInfo(NAME_MIDDLE, &values);
723  ASSERT_EQ(values.size(), 3U);
724  EXPECT_TRUE(values[0].empty());
725  EXPECT_TRUE(values[1].empty());
726  EXPECT_TRUE(values[2].empty());
727
728  profile1.GetRawMultiInfo(EMAIL_ADDRESS, &values);
729  ASSERT_EQ(values.size(), 3U);
730  EXPECT_EQ(values[0], ASCIIToUTF16("1@1.com"));
731  EXPECT_EQ(values[1], ASCIIToUTF16("2@1.com"));
732  EXPECT_EQ(values[2], ASCIIToUTF16("3@1.com"));
733
734  profile1.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values);
735  ASSERT_EQ(values.size(), 1U);
736  EXPECT_EQ(values[0], ASCIIToUTF16("650234567"));
737}
738
739// Ensure that all profile fields are able to be synced up from the client to
740// the server.
741TEST_F(AutofillProfileSyncableServiceTest, SyncAllFieldsToServer) {
742  std::vector<AutofillProfile*> profiles_from_web_db;
743
744  // Create a profile with all fields set.
745  profiles_from_web_db.push_back(ConstructCompleteProfile().release());
746
747  // Set up expectations: No changes to the WebDB, and all fields correctly
748  // copied to Sync.
749  MockAutofillProfileSyncableService::DataBundle expected_bundle;
750  syncer::SyncChangeList expected_change_list;
751  expected_change_list.push_back(
752      syncer::SyncChange(FROM_HERE,
753                         syncer::SyncChange::ACTION_ADD,
754                         ConstructCompleteSyncData()));
755
756  // Verify the expectations.
757  syncer::SyncDataList data_list;
758  MergeDataAndStartSyncing(
759      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
760  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
761}
762
763// Ensure that all profile fields are able to be synced down from the server to
764// the client.
765TEST_F(AutofillProfileSyncableServiceTest, SyncAllFieldsToClient) {
766  // Create a profile with all fields set.
767  syncer::SyncDataList data_list;
768  data_list.push_back(ConstructCompleteSyncData());
769
770  // Set up expectations: All fields correctly copied to the WebDB, and no
771  // changes propagated to Sync.
772  syncer::SyncChangeList expected_change_list;
773  scoped_ptr<AutofillProfile> expected_profile = ConstructCompleteProfile();
774  MockAutofillProfileSyncableService::DataBundle expected_bundle;
775  expected_bundle.profiles_to_add.push_back(expected_profile.get());
776
777  // Verify the expectations.
778  std::vector<AutofillProfile*> profiles_from_web_db;
779  MergeDataAndStartSyncing(
780      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
781  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
782}
783
784// Ensure that the street address field takes precedence over the address line 1
785// and line 2 fields, even though these are expected to always be in sync in
786// practice.
787TEST_F(AutofillProfileSyncableServiceTest,
788       StreetAddressTakesPrecedenceOverAddressLines) {
789  // Create a Sync profile with conflicting address data in the street address
790  // field vs. the address line 1 and address line 2 fields.
791  sync_pb::EntitySpecifics specifics;
792  sync_pb::AutofillProfileSpecifics* autofill_specifics =
793      specifics.mutable_autofill_profile();
794  autofill_specifics->set_guid(kGuid1);
795  autofill_specifics->set_origin(kHttpsOrigin);
796  autofill_specifics->add_name_first(std::string());
797  autofill_specifics->add_name_middle(std::string());
798  autofill_specifics->add_name_last(std::string());
799  autofill_specifics->add_email_address(std::string());
800  autofill_specifics->add_phone_home_whole_number(std::string());
801  autofill_specifics->set_address_home_line1("123 Example St.");
802  autofill_specifics->set_address_home_line2("Apt. 42");
803  autofill_specifics->set_address_home_street_address("456 El Camino Real\n"
804                                                      "Suite #1337");
805
806  syncer::SyncDataList data_list;
807  data_list.push_back(
808      syncer::SyncData::CreateLocalData(kGuid1, kGuid1, specifics));
809
810  // Set up expectations: Full street address takes precedence over address
811  // lines.
812  syncer::SyncChangeList expected_change_list;
813  AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
814  expected_profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
815                              ASCIIToUTF16("456 El Camino Real\n"
816                                           "Suite #1337"));
817  EXPECT_EQ(ASCIIToUTF16("456 El Camino Real"),
818            expected_profile.GetRawInfo(ADDRESS_HOME_LINE1));
819  EXPECT_EQ(ASCIIToUTF16("Suite #1337"),
820            expected_profile.GetRawInfo(ADDRESS_HOME_LINE2));
821  MockAutofillProfileSyncableService::DataBundle expected_bundle;
822  expected_bundle.profiles_to_add.push_back(&expected_profile);
823
824  // Verify the expectations.
825  std::vector<AutofillProfile*> profiles_from_web_db;
826  MergeDataAndStartSyncing(
827      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
828  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
829}
830
831// Ensure that no Sync events are generated to fill in missing street address
832// fields from Sync with explicitly present ones identical to the data stored in
833// the line1 and line2 fields.  This ensures that the migration to add the
834// street address field to profiles does not generate lots of needless Sync
835// updates.
836TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyStreetAddress) {
837  std::vector<AutofillProfile*> profiles_from_web_db;
838
839  // Create a profile with the street address set.
840  AutofillProfile profile(kGuid1, kHttpsOrigin);
841  profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
842                     ASCIIToUTF16("123 Example St.\n"
843                                  "Apt. 42"));
844  EXPECT_EQ(ASCIIToUTF16("123 Example St."),
845            profile.GetRawInfo(ADDRESS_HOME_LINE1));
846  EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile.GetRawInfo(ADDRESS_HOME_LINE2));
847
848  profiles_from_web_db.push_back(new AutofillProfile(profile));
849
850  // Create a Sync profile identical to |profile|, except without street address
851  // explicitly set.
852  sync_pb::EntitySpecifics specifics;
853  sync_pb::AutofillProfileSpecifics* autofill_specifics =
854      specifics.mutable_autofill_profile();
855  autofill_specifics->set_guid(profile.guid());
856  autofill_specifics->set_origin(profile.origin());
857  autofill_specifics->add_name_first(std::string());
858  autofill_specifics->add_name_middle(std::string());
859  autofill_specifics->add_name_last(std::string());
860  autofill_specifics->add_name_full(std::string());
861  autofill_specifics->add_email_address(std::string());
862  autofill_specifics->add_phone_home_whole_number(std::string());
863  autofill_specifics->set_address_home_line1("123 Example St.");
864  autofill_specifics->set_address_home_line2("Apt. 42");
865  EXPECT_FALSE(autofill_specifics->has_address_home_street_address());
866
867  syncer::SyncDataList data_list;
868  data_list.push_back(
869      syncer::SyncData::CreateLocalData(
870          profile.guid(), profile.guid(), specifics));
871
872  MockAutofillProfileSyncableService::DataBundle expected_bundle;
873  syncer::SyncChangeList expected_change_list;
874  MergeDataAndStartSyncing(
875      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
876  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
877}
878
879// Sync data without origin should not overwrite existing origin in local
880// autofill profile.
881TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesOrigin) {
882  std::vector<AutofillProfile*> profiles_from_web_db;
883
884  // Local autofill profile has an origin.
885  AutofillProfile profile(kGuid1, kHttpsOrigin);
886  profiles_from_web_db.push_back(new AutofillProfile(profile));
887
888  // Remote data does not have an origin value.
889  sync_pb::EntitySpecifics specifics;
890  sync_pb::AutofillProfileSpecifics* autofill_specifics =
891      specifics.mutable_autofill_profile();
892  autofill_specifics->set_guid(profile.guid());
893  autofill_specifics->add_name_first("John");
894  autofill_specifics->add_name_middle(std::string());
895  autofill_specifics->add_name_last(std::string());
896  autofill_specifics->add_name_full("John");
897  autofill_specifics->add_email_address(std::string());
898  autofill_specifics->add_phone_home_whole_number(std::string());
899  EXPECT_FALSE(autofill_specifics->has_origin());
900
901  syncer::SyncDataList data_list;
902  data_list.push_back(
903      syncer::SyncData::CreateLocalData(
904          profile.guid(), profile.guid(), specifics));
905
906  // Expect the local autofill profile to still have an origin after sync.
907  MockAutofillProfileSyncableService::DataBundle expected_bundle;
908  AutofillProfile expected_profile(profile.guid(), profile.origin());
909  expected_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
910  expected_bundle.profiles_to_update.push_back(&expected_profile);
911
912  // Expect no sync events to add origin to the remote data.
913  syncer::SyncChangeList expected_empty_change_list;
914
915  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
916                           expected_bundle, expected_empty_change_list);
917  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
918}
919
920// Missing language code field should not generate sync events.
921TEST_F(AutofillProfileSyncableServiceTest, NoLanguageCodeNoSync) {
922  std::vector<AutofillProfile*> profiles_from_web_db;
923
924  // Local autofill profile has an empty language code.
925  AutofillProfile profile(kGuid1, kHttpsOrigin);
926  EXPECT_TRUE(profile.language_code().empty());
927  profiles_from_web_db.push_back(new AutofillProfile(profile));
928
929  // Remote data does not have a language code value.
930  sync_pb::EntitySpecifics specifics;
931  sync_pb::AutofillProfileSpecifics* autofill_specifics =
932      specifics.mutable_autofill_profile();
933  autofill_specifics->set_guid(profile.guid());
934  autofill_specifics->set_origin(profile.origin());
935  autofill_specifics->add_name_first(std::string());
936  autofill_specifics->add_name_middle(std::string());
937  autofill_specifics->add_name_last(std::string());
938  autofill_specifics->add_name_full(std::string());
939  autofill_specifics->add_email_address(std::string());
940  autofill_specifics->add_phone_home_whole_number(std::string());
941  EXPECT_FALSE(autofill_specifics->has_address_home_language_code());
942
943  syncer::SyncDataList data_list;
944  data_list.push_back(
945      syncer::SyncData::CreateLocalData(
946          profile.guid(), profile.guid(), specifics));
947
948  // Expect no changes to local and remote data.
949  MockAutofillProfileSyncableService::DataBundle expected_empty_bundle;
950  syncer::SyncChangeList expected_empty_change_list;
951
952  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
953                           expected_empty_bundle, expected_empty_change_list);
954  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
955}
956
957// Empty language code should be overwritten by sync.
958TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesEmptyLanguageCode) {
959  std::vector<AutofillProfile*> profiles_from_web_db;
960
961  // Local autofill profile has an empty language code.
962  AutofillProfile profile(kGuid1, kHttpsOrigin);
963  EXPECT_TRUE(profile.language_code().empty());
964  profiles_from_web_db.push_back(new AutofillProfile(profile));
965
966  // Remote data has "en" language code.
967  sync_pb::EntitySpecifics specifics;
968  sync_pb::AutofillProfileSpecifics* autofill_specifics =
969      specifics.mutable_autofill_profile();
970  autofill_specifics->set_guid(profile.guid());
971  autofill_specifics->set_origin(profile.origin());
972  autofill_specifics->add_name_first(std::string());
973  autofill_specifics->add_name_middle(std::string());
974  autofill_specifics->add_name_last(std::string());
975  autofill_specifics->add_name_full(std::string());
976  autofill_specifics->add_email_address(std::string());
977  autofill_specifics->add_phone_home_whole_number(std::string());
978  autofill_specifics->set_address_home_language_code("en");
979  EXPECT_TRUE(autofill_specifics->has_address_home_language_code());
980
981  syncer::SyncDataList data_list;
982  data_list.push_back(
983      syncer::SyncData::CreateLocalData(
984          profile.guid(), profile.guid(), specifics));
985
986  // Expect the local autofill profile to have "en" language code after sync.
987  MockAutofillProfileSyncableService::DataBundle expected_bundle;
988  AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
989  expected_profile.set_language_code("en");
990  expected_bundle.profiles_to_update.push_back(&expected_profile);
991
992  // Expect not changes to remote data.
993  syncer::SyncChangeList expected_empty_change_list;
994
995  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
996                           expected_bundle, expected_empty_change_list);
997  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
998}
999
1000// Incorrect language code should be overwritten by sync.
1001TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesIncorrectLanguageCode) {
1002  std::vector<AutofillProfile*> profiles_from_web_db;
1003
1004  // Local autofill profile has "de" language code.
1005  AutofillProfile profile(kGuid1, kHttpsOrigin);
1006  profile.set_language_code("de");
1007  profiles_from_web_db.push_back(new AutofillProfile(profile));
1008
1009  // Remote data has "en" language code.
1010  sync_pb::EntitySpecifics specifics;
1011  sync_pb::AutofillProfileSpecifics* autofill_specifics =
1012      specifics.mutable_autofill_profile();
1013  autofill_specifics->set_guid(profile.guid());
1014  autofill_specifics->set_origin(profile.origin());
1015  autofill_specifics->add_name_first(std::string());
1016  autofill_specifics->add_name_middle(std::string());
1017  autofill_specifics->add_name_last(std::string());
1018  autofill_specifics->add_name_full(std::string());
1019  autofill_specifics->add_email_address(std::string());
1020  autofill_specifics->add_phone_home_whole_number(std::string());
1021  autofill_specifics->set_address_home_language_code("en");
1022  EXPECT_TRUE(autofill_specifics->has_address_home_language_code());
1023
1024  syncer::SyncDataList data_list;
1025  data_list.push_back(
1026      syncer::SyncData::CreateLocalData(
1027          profile.guid(), profile.guid(), specifics));
1028
1029  // Expect the local autofill profile to have "en" language code after sync.
1030  MockAutofillProfileSyncableService::DataBundle expected_bundle;
1031  AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
1032  expected_profile.set_language_code("en");
1033  expected_bundle.profiles_to_update.push_back(&expected_profile);
1034
1035  // Expect no changes to remote data.
1036  syncer::SyncChangeList expected_empty_change_list;
1037
1038  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
1039                           expected_bundle, expected_empty_change_list);
1040  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
1041}
1042
1043// Sync data without language code should not overwrite existing language code
1044// in local autofill profile.
1045TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesLanguageCode) {
1046  std::vector<AutofillProfile*> profiles_from_web_db;
1047
1048  // Local autofill profile has "en" language code.
1049  AutofillProfile profile(kGuid1, kHttpsOrigin);
1050  profile.set_language_code("en");
1051  profiles_from_web_db.push_back(new AutofillProfile(profile));
1052
1053  // Remote data does not have a language code value.
1054  sync_pb::EntitySpecifics specifics;
1055  sync_pb::AutofillProfileSpecifics* autofill_specifics =
1056      specifics.mutable_autofill_profile();
1057  autofill_specifics->set_guid(profile.guid());
1058  autofill_specifics->set_origin(profile.origin());
1059  autofill_specifics->add_name_first("John");
1060  autofill_specifics->add_name_middle(std::string());
1061  autofill_specifics->add_name_last(std::string());
1062  autofill_specifics->add_name_full("John");
1063  autofill_specifics->add_email_address(std::string());
1064  autofill_specifics->add_phone_home_whole_number(std::string());
1065  EXPECT_FALSE(autofill_specifics->has_address_home_language_code());
1066
1067  syncer::SyncDataList data_list;
1068  data_list.push_back(
1069      syncer::SyncData::CreateLocalData(
1070          profile.guid(), profile.guid(), specifics));
1071
1072  // Expect local autofill profile to still have "en" language code after sync.
1073  MockAutofillProfileSyncableService::DataBundle expected_bundle;
1074  AutofillProfile expected_profile(profile.guid(), profile.origin());
1075  expected_profile.set_language_code("en");
1076  expected_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
1077  expected_bundle.profiles_to_update.push_back(&expected_profile);
1078
1079  // Expect no changes to remote data.
1080  syncer::SyncChangeList expected_empty_change_list;
1081
1082  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
1083                           expected_bundle, expected_empty_change_list);
1084  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
1085}
1086
1087// Language code in autofill profiles should be synced to the server.
1088TEST_F(AutofillProfileSyncableServiceTest, LanguageCodePropagates) {
1089  TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
1090  autofill_syncable_service_.set_sync_processor(sync_change_processor);
1091
1092  AutofillProfile profile(kGuid1, kHttpsOrigin);
1093  profile.set_language_code("en");
1094  AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
1095  autofill_syncable_service_.AutofillProfileChanged(change);
1096
1097  ASSERT_EQ(1U, sync_change_processor->changes().size());
1098  syncer::SyncChange result = sync_change_processor->changes()[0];
1099  EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());
1100
1101  sync_pb::AutofillProfileSpecifics specifics =
1102      result.sync_data().GetSpecifics().autofill_profile();
1103  EXPECT_EQ(kGuid1, specifics.guid());
1104  EXPECT_EQ(kHttpsOrigin, specifics.origin());
1105  EXPECT_EQ("en", specifics.address_home_language_code());
1106}
1107
1108// Missing full name field should not generate sync events.
1109TEST_F(AutofillProfileSyncableServiceTest, NoFullNameNoSync) {
1110  std::vector<AutofillProfile*> profiles_from_web_db;
1111
1112  // Local autofill profile has an empty full name.
1113  AutofillProfile profile(kGuid1, kHttpsOrigin);
1114  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
1115  profiles_from_web_db.push_back(new AutofillProfile(profile));
1116
1117  // Remote data does not have a full name.
1118  sync_pb::EntitySpecifics specifics;
1119  sync_pb::AutofillProfileSpecifics* autofill_specifics =
1120      specifics.mutable_autofill_profile();
1121  autofill_specifics->set_guid(profile.guid());
1122  autofill_specifics->set_origin(profile.origin());
1123  autofill_specifics->add_name_first(std::string("John"));
1124  autofill_specifics->add_name_middle(std::string());
1125  autofill_specifics->add_name_last(std::string());
1126  autofill_specifics->add_email_address(std::string());
1127  autofill_specifics->add_phone_home_whole_number(std::string());
1128
1129  syncer::SyncDataList data_list;
1130  data_list.push_back(
1131      syncer::SyncData::CreateLocalData(
1132          profile.guid(), profile.guid(), specifics));
1133
1134  // Expect no changes to local and remote data.
1135  MockAutofillProfileSyncableService::DataBundle expected_empty_bundle;
1136  syncer::SyncChangeList expected_empty_change_list;
1137
1138  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
1139                           expected_empty_bundle, expected_empty_change_list);
1140  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
1141}
1142
1143TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesFullName) {
1144  std::vector<AutofillProfile*> profiles_from_web_db;
1145
1146  // Local autofill profile has a full name.
1147  AutofillProfile profile(kGuid1, kHttpsOrigin);
1148  profile.SetRawInfo(NAME_FULL, ASCIIToUTF16("John Jacob Smith, Jr"));
1149  profiles_from_web_db.push_back(new AutofillProfile(profile));
1150
1151  // Remote data does not have a full name value.
1152  sync_pb::EntitySpecifics specifics;
1153  sync_pb::AutofillProfileSpecifics* autofill_specifics =
1154      specifics.mutable_autofill_profile();
1155  autofill_specifics->set_guid(profile.guid());
1156  autofill_specifics->set_origin(profile.origin());
1157  autofill_specifics->add_name_first(std::string("John"));
1158  autofill_specifics->add_name_middle(std::string("Jacob"));
1159  autofill_specifics->add_name_last(std::string("Smith"));
1160
1161  syncer::SyncDataList data_list;
1162  data_list.push_back(
1163      syncer::SyncData::CreateLocalData(
1164          profile.guid(), profile.guid(), specifics));
1165
1166  // Expect local autofill profile to still have the same full name after sync.
1167  MockAutofillProfileSyncableService::DataBundle expected_bundle;
1168  AutofillProfile expected_profile(profile.guid(), profile.origin());
1169  expected_profile.SetRawInfo(NAME_FULL, ASCIIToUTF16("John Jacob Smith, Jr"));
1170  expected_bundle.profiles_to_update.push_back(&expected_profile);
1171
1172  // Expect no changes to remote data.
1173  syncer::SyncChangeList expected_empty_change_list;
1174
1175  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
1176                           expected_bundle, expected_empty_change_list);
1177  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
1178}
1179
1180}  // namespace autofill
1181