profile_sync_service_autofill_unittest.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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 <set>
6#include <string>
7#include <vector>
8
9#include "testing/gtest/include/gtest/gtest.h"
10
11#include "base/callback.h"
12#include "base/message_loop.h"
13#include "base/ref_counted.h"
14#include "base/scoped_ptr.h"
15#include "base/string16.h"
16#include "base/task.h"
17#include "base/time.h"
18#include "base/utf_string_conversions.h"
19#include "base/waitable_event.h"
20#include "chrome/browser/autofill/autofill_common_unittest.h"
21#include "chrome/browser/chrome_thread.h"
22#include "chrome/browser/sync/abstract_profile_sync_service_test.h"
23#include "chrome/browser/sync/engine/model_changing_syncer_command.h"
24#include "chrome/browser/sync/engine/syncapi.h"
25#include "chrome/browser/sync/engine/syncer_util.h"
26#include "chrome/browser/sync/glue/autofill_change_processor.h"
27#include "chrome/browser/sync/glue/autofill_data_type_controller.h"
28#include "chrome/browser/sync/glue/autofill_model_associator.h"
29#include "chrome/browser/sync/profile_sync_factory.h"
30#include "chrome/browser/sync/profile_sync_service.h"
31#include "chrome/browser/sync/profile_sync_test_util.h"
32#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
33#include "chrome/browser/sync/syncable/syncable.h"
34#include "chrome/browser/sync/syncable/model_type.h"
35#include "chrome/browser/sync/test_profile_sync_service.h"
36#include "chrome/browser/webdata/autofill_change.h"
37#include "chrome/browser/webdata/autofill_entry.h"
38#include "chrome/browser/webdata/web_database.h"
39#include "chrome/common/net/gaia/gaia_constants.h"
40#include "chrome/common/notification_source.h"
41#include "chrome/common/notification_type.h"
42#include "chrome/test/profile_mock.h"
43#include "chrome/test/sync/engine/test_id_factory.h"
44#include "testing/gmock/include/gmock/gmock.h"
45
46using base::Time;
47using base::WaitableEvent;
48using browser_sync::AutofillChangeProcessor;
49using browser_sync::AutofillDataTypeController;
50using browser_sync::AutofillModelAssociator;
51using browser_sync::GROUP_DB;
52using browser_sync::kAutofillTag;
53using browser_sync::SyncBackendHostForProfileSyncTest;
54using browser_sync::SyncerUtil;
55using browser_sync::UnrecoverableErrorHandler;
56using syncable::CREATE_NEW_UPDATE_ITEM;
57using syncable::AUTOFILL;
58using syncable::DirectoryChangeEvent;
59using syncable::GET_BY_SERVER_TAG;
60using syncable::INVALID;
61using syncable::SERVER_PARENT_ID;
62using syncable::SERVER_SPECIFICS;
63using syncable::OriginalEntries;
64using syncable::WriterTag;
65using syncable::WriteTransaction;
66using testing::_;
67using testing::DoAll;
68using testing::DoDefault;
69using testing::ElementsAre;
70using testing::Eq;
71using testing::Invoke;
72using testing::Mock;
73using testing::Return;
74using testing::SaveArg;
75using testing::SetArgumentPointee;
76
77namespace syncable {
78class Id;
79}
80
81class WebDatabaseMock : public WebDatabase {
82 public:
83  MOCK_METHOD2(RemoveFormElement,
84               bool(const string16& name, const string16& value));  // NOLINT
85  MOCK_METHOD1(GetAllAutofillEntries,
86               bool(std::vector<AutofillEntry>* entries));  // NOLINT
87  MOCK_METHOD3(GetAutofillTimestamps,
88               bool(const string16& name,  // NOLINT
89                    const string16& value,
90                    std::vector<base::Time>* timestamps));
91  MOCK_METHOD1(UpdateAutofillEntries,
92               bool(const std::vector<AutofillEntry>&));  // NOLINT
93  MOCK_METHOD1(GetAutoFillProfiles,
94               bool(std::vector<AutoFillProfile*>*));  // NOLINT
95  MOCK_METHOD1(UpdateAutoFillProfile,
96               bool(const AutoFillProfile&));  // NOLINT
97  MOCK_METHOD1(AddAutoFillProfile,
98               bool(const AutoFillProfile&));  // NOLINT
99  MOCK_METHOD1(RemoveAutoFillProfile,
100               bool(int));  // NOLINT
101};
102
103class WebDataServiceFake : public WebDataService {
104 public:
105  explicit WebDataServiceFake(WebDatabase* web_database)
106      : web_database_(web_database) {}
107  virtual bool IsDatabaseLoaded() {
108    return true;
109  }
110
111  virtual WebDatabase* GetDatabase() {
112    return web_database_;
113  }
114
115 private:
116  WebDatabase* web_database_;
117};
118
119class PersonalDataManagerMock: public PersonalDataManager {
120 public:
121  MOCK_CONST_METHOD0(IsDataLoaded, bool());
122  MOCK_METHOD0(LoadProfiles, void());
123  MOCK_METHOD0(LoadCreditCards, void());
124  MOCK_METHOD0(Refresh, void());
125};
126
127ACTION_P4(MakeAutofillSyncComponents, service, wd, pdm, dtc) {
128  EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::DB));
129  if (!ChromeThread::CurrentlyOn(ChromeThread::DB))
130    return ProfileSyncFactory::SyncComponents(NULL, NULL);
131  AutofillModelAssociator* model_associator =
132      new AutofillModelAssociator(service, wd, pdm);
133  AutofillChangeProcessor* change_processor =
134      new AutofillChangeProcessor(model_associator, wd, pdm, dtc);
135  return ProfileSyncFactory::SyncComponents(model_associator,
136                                            change_processor);
137}
138
139class ProfileSyncServiceAutofillTest : public AbstractProfileSyncServiceTest {
140 protected:
141  ProfileSyncServiceAutofillTest() : db_thread_(ChromeThread::DB) {
142  }
143
144  virtual void SetUp() {
145    web_data_service_ = new WebDataServiceFake(&web_database_);
146    personal_data_manager_ = new PersonalDataManagerMock();
147    EXPECT_CALL(*personal_data_manager_, LoadProfiles()).Times(1);
148    EXPECT_CALL(*personal_data_manager_, LoadCreditCards()).Times(1);
149    personal_data_manager_->Init(&profile_);
150    db_thread_.Start();
151
152    notification_service_ = new ThreadNotificationService(&db_thread_);
153    notification_service_->Init();
154  }
155
156  virtual void TearDown() {
157    service_.reset();
158    notification_service_->TearDown();
159    db_thread_.Stop();
160    MessageLoop::current()->RunAllPending();
161  }
162
163  void StartSyncService(Task* task, bool will_fail_association) {
164    if (!service_.get()) {
165      service_.reset(
166          new TestProfileSyncService(&factory_, &profile_, "test_user", false,
167                                     task));
168      AutofillDataTypeController* data_type_controller =
169          new AutofillDataTypeController(&factory_,
170                                         &profile_,
171                                         service_.get());
172
173     SyncBackendHostForProfileSyncTest::
174         SetDefaultExpectationsForWorkerCreation(&profile_);
175
176      EXPECT_CALL(factory_, CreateAutofillSyncComponents(_, _, _, _)).
177          WillOnce(MakeAutofillSyncComponents(service_.get(),
178                                              &web_database_,
179                                              personal_data_manager_.get(),
180                                              data_type_controller));
181      EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).
182          WillOnce(ReturnNewDataTypeManager());
183
184      EXPECT_CALL(profile_, GetWebDataService(_)).
185          WillOnce(Return(web_data_service_.get()));
186
187      EXPECT_CALL(profile_, GetPersonalDataManager()).
188          WillRepeatedly(Return(personal_data_manager_.get()));
189
190      EXPECT_CALL(*personal_data_manager_, IsDataLoaded()).
191          WillRepeatedly(Return(true));
192
193       // We need tokens to get the tests going
194      token_service_.IssueAuthTokenForTest(
195          GaiaConstants::kSyncService, "token");
196
197      EXPECT_CALL(profile_, GetTokenService()).
198          WillRepeatedly(Return(&token_service_));
199
200      service_->set_num_expected_resumes(will_fail_association ? 0 : 1);
201      service_->RegisterDataTypeController(data_type_controller);
202      service_->Initialize();
203      MessageLoop::current()->Run();
204    }
205  }
206
207  bool AddAutofillSyncNode(const AutofillEntry& entry) {
208    sync_api::WriteTransaction trans(
209        service_->backend()->GetUserShareHandle());
210    sync_api::ReadNode autofill_root(&trans);
211    if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag))
212      return false;
213
214    sync_api::WriteNode node(&trans);
215    std::string tag = AutofillModelAssociator::KeyToTag(entry.key().name(),
216                                                        entry.key().value());
217    if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag))
218      return false;
219
220    AutofillChangeProcessor::WriteAutofillEntry(entry, &node);
221    return true;
222  }
223
224  bool AddAutofillProfileSyncNode(const AutoFillProfile& profile) {
225    sync_api::WriteTransaction trans(
226        service_->backend()->GetUserShareHandle());
227    sync_api::ReadNode autofill_root(&trans);
228    if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag))
229      return false;
230    sync_api::WriteNode node(&trans);
231    std::string tag = AutofillModelAssociator::ProfileLabelToTag(
232        profile.Label());
233    if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag))
234      return false;
235    AutofillChangeProcessor::WriteAutofillProfile(profile, &node);
236    sync_pb::AutofillSpecifics s(node.GetAutofillSpecifics());
237    s.mutable_profile()->set_label(UTF16ToUTF8(profile.Label()));
238    node.SetAutofillSpecifics(s);
239    return true;
240  }
241
242  bool GetAutofillEntriesFromSyncDB(std::vector<AutofillEntry>* entries,
243                                    std::vector<AutoFillProfile>* profiles) {
244    sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle());
245    sync_api::ReadNode autofill_root(&trans);
246    if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag))
247      return false;
248
249    int64 child_id = autofill_root.GetFirstChildId();
250    while (child_id != sync_api::kInvalidId) {
251      sync_api::ReadNode child_node(&trans);
252      if (!child_node.InitByIdLookup(child_id))
253        return false;
254
255      const sync_pb::AutofillSpecifics& autofill(
256          child_node.GetAutofillSpecifics());
257      if (autofill.has_value()) {
258        AutofillKey key(UTF8ToUTF16(autofill.name()),
259                        UTF8ToUTF16(autofill.value()));
260        std::vector<base::Time> timestamps;
261        int timestamps_count = autofill.usage_timestamp_size();
262        for (int i = 0; i < timestamps_count; ++i) {
263          timestamps.push_back(Time::FromInternalValue(
264              autofill.usage_timestamp(i)));
265        }
266        entries->push_back(AutofillEntry(key, timestamps));
267      } else if (autofill.has_profile()) {
268        AutoFillProfile p(UTF8ToUTF16(autofill.profile().label()), 0);
269        AutofillModelAssociator::OverwriteProfileWithServerData(&p,
270            autofill.profile());
271        profiles->push_back(p);
272      }
273      child_id = child_node.GetSuccessorId();
274    }
275    return true;
276  }
277
278  void SetIdleChangeProcessorExpectations() {
279    EXPECT_CALL(web_database_, RemoveFormElement(_, _)).Times(0);
280    EXPECT_CALL(web_database_, GetAutofillTimestamps(_, _, _)).Times(0);
281    EXPECT_CALL(web_database_, UpdateAutofillEntries(_)).Times(0);
282  }
283
284  static AutofillEntry MakeAutofillEntry(const char* name,
285                                         const char* value,
286                                         time_t timestamp0,
287                                         time_t timestamp1) {
288    std::vector<Time> timestamps;
289    if (timestamp0 > 0)
290      timestamps.push_back(Time::FromTimeT(timestamp0));
291    if (timestamp1 > 0)
292      timestamps.push_back(Time::FromTimeT(timestamp1));
293    return AutofillEntry(
294        AutofillKey(ASCIIToUTF16(name), ASCIIToUTF16(value)), timestamps);
295  }
296
297  static AutofillEntry MakeAutofillEntry(const char* name,
298                                         const char* value,
299                                         time_t timestamp) {
300    return MakeAutofillEntry(name, value, timestamp, -1);
301  }
302
303  friend class AddAutofillEntriesTask;
304  friend class FakeServerUpdater;
305
306  ChromeThread db_thread_;
307  scoped_refptr<ThreadNotificationService> notification_service_;
308
309  ProfileMock profile_;
310  WebDatabaseMock web_database_;
311  scoped_refptr<WebDataService> web_data_service_;
312  scoped_refptr<PersonalDataManagerMock> personal_data_manager_;
313};
314
315class AddAutofillEntriesTask : public Task {
316 public:
317  AddAutofillEntriesTask(ProfileSyncServiceAutofillTest* test,
318                         const std::vector<AutofillEntry>& entries,
319                         const std::vector<AutoFillProfile>& profiles)
320      : test_(test), entries_(entries), profiles_(profiles), success_(false) {
321  }
322
323  virtual void Run() {
324    if (!test_->CreateRoot(syncable::AUTOFILL))
325      return;
326    for (size_t i = 0; i < entries_.size(); ++i) {
327      if (!test_->AddAutofillSyncNode(entries_[i]))
328        return;
329    }
330    for (size_t i = 0; i < profiles_.size(); ++i) {
331      if (!test_->AddAutofillProfileSyncNode(profiles_[i]))
332        return;
333    }
334    success_ = true;
335  }
336
337  bool success() { return success_; }
338
339 private:
340  ProfileSyncServiceAutofillTest* test_;
341  const std::vector<AutofillEntry>& entries_;
342  const std::vector<AutoFillProfile>& profiles_;
343  bool success_;
344};
345
346// Overload write transaction to use custom NotifyTransactionComplete
347static const bool kLoggingInfo = true;
348class WriteTransactionTest: public WriteTransaction {
349 public:
350  WriteTransactionTest(const ScopedDirLookup& directory,
351                       WriterTag writer, const char* source_file,
352                       int line,
353                       scoped_ptr<WaitableEvent> *wait_for_syncapi)
354      : WriteTransaction(directory, writer, source_file, line),
355        wait_for_syncapi_(wait_for_syncapi) { }
356
357  virtual void NotifyTransactionComplete() {
358    // This is where we differ. Force a thread change here, giving another
359    // thread a chance to create a WriteTransaction
360    (*wait_for_syncapi_)->Wait();
361
362    WriteTransaction::NotifyTransactionComplete();
363  }
364
365 private:
366  scoped_ptr<WaitableEvent> *wait_for_syncapi_;
367};
368
369// Our fake server updater. Needs the RefCountedThreadSafe inheritance so we can
370// post tasks with it.
371class FakeServerUpdater: public base::RefCountedThreadSafe<FakeServerUpdater> {
372 public:
373  FakeServerUpdater(TestProfileSyncService *service,
374                    scoped_ptr<WaitableEvent> *wait_for_start,
375                    scoped_ptr<WaitableEvent> *wait_for_syncapi)
376      : entry_(ProfileSyncServiceAutofillTest::MakeAutofillEntry("0", "0", 0)),
377        service_(service),
378        wait_for_start_(wait_for_start),
379        wait_for_syncapi_(wait_for_syncapi),
380        is_finished_(false, false) { }
381
382  void Update() {
383    // This gets called in a modelsafeworker thread.
384    ASSERT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::DB));
385
386    UserShare* user_share = service_->backend()->GetUserShareHandle();
387    DirectoryManager* dir_manager = user_share->dir_manager.get();
388    ScopedDirLookup dir(dir_manager, user_share->name);
389    ASSERT_TRUE(dir.good());
390
391    // Create autofill protobuf
392    std::string tag = AutofillModelAssociator::KeyToTag(entry_.key().name(),
393                                                        entry_.key().value());
394    sync_pb::AutofillSpecifics new_autofill;
395    new_autofill.set_name(UTF16ToUTF8(entry_.key().name()));
396    new_autofill.set_value(UTF16ToUTF8(entry_.key().value()));
397    const std::vector<base::Time>& ts(entry_.timestamps());
398    for (std::vector<base::Time>::const_iterator timestamp = ts.begin();
399         timestamp != ts.end(); ++timestamp) {
400      new_autofill.add_usage_timestamp(timestamp->ToInternalValue());
401    }
402
403    sync_pb::EntitySpecifics entity_specifics;
404    entity_specifics.MutableExtension(sync_pb::autofill)->
405        CopyFrom(new_autofill);
406
407    {
408      // Tell main thread we've started
409      (*wait_for_start_)->Signal();
410
411      // Create write transaction.
412      WriteTransactionTest trans(dir, UNITTEST, __FILE__, __LINE__,
413                                 wait_for_syncapi_);
414
415      // Create actual entry based on autofill protobuf information.
416      // Simulates effects of SyncerUtil::UpdateLocalDataFromServerData
417      MutableEntry parent(&trans, GET_BY_SERVER_TAG, kAutofillTag);
418      MutableEntry item(&trans, CREATE, parent.Get(syncable::ID), tag);
419      ASSERT_TRUE(item.good());
420      item.Put(SPECIFICS, entity_specifics);
421      item.Put(SERVER_SPECIFICS, entity_specifics);
422      item.Put(BASE_VERSION, 1);
423      syncable::Id server_parent_id = ids_.NewServerId();
424      item.Put(syncable::ID, server_parent_id);
425      syncable::Id new_predecessor =
426          SyncerUtil::ComputePrevIdFromServerPosition(&trans, &item,
427          server_parent_id);
428      ASSERT_TRUE(item.PutPredecessor(new_predecessor));
429    }
430    LOG(INFO) << "FakeServerUpdater finishing.";
431    is_finished_.Signal();
432  }
433
434  void CreateNewEntry(const AutofillEntry& entry) {
435    entry_ = entry;
436    scoped_ptr<Callback0::Type> c(NewCallback((FakeServerUpdater *)this,
437                                              &FakeServerUpdater::Update));
438    std::vector<browser_sync::ModelSafeWorker*> workers;
439    service_->backend()->GetWorkers(&workers);
440
441    ASSERT_FALSE(ChromeThread::CurrentlyOn(ChromeThread::DB));
442    if (!ChromeThread::PostTask(ChromeThread::DB, FROM_HERE,
443         NewRunnableMethod(this, &FakeServerUpdater::Update))) {
444      NOTREACHED() << "Failed to post task to the db thread.";
445      return;
446    }
447  }
448
449  void CreateNewEntryAndWait(const AutofillEntry& entry) {
450    entry_ = entry;
451    scoped_ptr<Callback0::Type> c(NewCallback((FakeServerUpdater *)this,
452                                              &FakeServerUpdater::Update));
453    std::vector<browser_sync::ModelSafeWorker*> workers;
454    service_->backend()->GetWorkers(&workers);
455
456    ASSERT_FALSE(ChromeThread::CurrentlyOn(ChromeThread::DB));
457    is_finished_.Reset();
458    if (!ChromeThread::PostTask(ChromeThread::DB, FROM_HERE,
459         NewRunnableMethod(this, &FakeServerUpdater::Update))) {
460      NOTREACHED() << "Failed to post task to the db thread.";
461      return;
462    }
463    is_finished_.Wait();
464  }
465
466 private:
467  friend class base::RefCountedThreadSafe<FakeServerUpdater>;
468  ~FakeServerUpdater() { }
469
470  AutofillEntry entry_;
471  TestProfileSyncService *service_;
472  scoped_ptr<WaitableEvent> *wait_for_start_;
473  scoped_ptr<WaitableEvent> *wait_for_syncapi_;
474  WaitableEvent is_finished_;
475  syncable::Id parent_id_;
476  TestIdFactory ids_;
477};
478
479// TODO(skrul): Test abort startup.
480// TODO(skrul): Test processing of cloud changes.
481// TODO(tim): Add autofill data type controller test, and a case to cover
482//            waiting for the PersonalDataManager.
483TEST_F(ProfileSyncServiceAutofillTest, FailModelAssociation) {
484  // Don't create the root autofill node so startup fails.
485  StartSyncService(NULL, true);
486  EXPECT_TRUE(service_->unrecoverable_error_detected());
487}
488
489TEST_F(ProfileSyncServiceAutofillTest, EmptyNativeEmptySync) {
490  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
491  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
492  SetIdleChangeProcessorExpectations();
493  CreateRootTask task(this, syncable::AUTOFILL);
494  EXPECT_CALL(*personal_data_manager_, Refresh());
495  StartSyncService(&task, false);
496  ASSERT_TRUE(task.success());
497  std::vector<AutofillEntry> sync_entries;
498  std::vector<AutoFillProfile> sync_profiles;
499  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
500  EXPECT_EQ(0U, sync_entries.size());
501  EXPECT_EQ(0U, sync_profiles.size());
502}
503
504TEST_F(ProfileSyncServiceAutofillTest, HasNativeEntriesEmptySync) {
505  std::vector<AutofillEntry> entries;
506  entries.push_back(MakeAutofillEntry("foo", "bar", 1));
507  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).
508      WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true)));
509  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
510  SetIdleChangeProcessorExpectations();
511  CreateRootTask task(this, syncable::AUTOFILL);
512  EXPECT_CALL(*personal_data_manager_, Refresh());
513  StartSyncService(&task, false);
514  ASSERT_TRUE(task.success());
515  std::vector<AutofillEntry> sync_entries;
516  std::vector<AutoFillProfile> sync_profiles;
517  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
518  ASSERT_EQ(1U, entries.size());
519  EXPECT_TRUE(entries[0] == sync_entries[0]);
520  EXPECT_EQ(0U, sync_profiles.size());
521}
522
523TEST_F(ProfileSyncServiceAutofillTest, HasMixedNativeEmptySync) {
524  std::vector<AutofillEntry> entries;
525  entries.push_back(MakeAutofillEntry("foo", "bar", 1));
526  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).
527      WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true)));
528
529  std::vector<AutoFillProfile*> profiles;
530  std::vector<AutoFillProfile> expected_profiles;
531  // Owned by GetAutoFillProfiles caller.
532  AutoFillProfile* profile0 = new AutoFillProfile(string16(), 0);
533  autofill_unittest::SetProfileInfo(profile0,
534      "Billing", "Marion", "Mitchell", "Morrison",
535      "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
536      "91601", "US", "12345678910", "01987654321");
537  profiles.push_back(profile0);
538  expected_profiles.push_back(*profile0);
539  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
540      WillOnce(DoAll(SetArgumentPointee<0>(profiles), Return(true)));
541  EXPECT_CALL(*personal_data_manager_, Refresh());
542  SetIdleChangeProcessorExpectations();
543  CreateRootTask task(this, syncable::AUTOFILL);
544  StartSyncService(&task, false);
545  ASSERT_TRUE(task.success());
546  std::vector<AutofillEntry> sync_entries;
547  std::vector<AutoFillProfile> sync_profiles;
548  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
549  ASSERT_EQ(1U, entries.size());
550  EXPECT_TRUE(entries[0] == sync_entries[0]);
551  EXPECT_EQ(1U, sync_profiles.size());
552  EXPECT_EQ(expected_profiles[0], sync_profiles[0]);
553}
554
555bool ProfilesMatchExceptLabelImpl(AutoFillProfile p1, AutoFillProfile p2) {
556  const AutoFillFieldType types[] = { NAME_FIRST,
557                                      NAME_MIDDLE,
558                                      NAME_LAST,
559                                      EMAIL_ADDRESS,
560                                      COMPANY_NAME,
561                                      ADDRESS_HOME_LINE1,
562                                      ADDRESS_HOME_LINE2,
563                                      ADDRESS_HOME_CITY,
564                                      ADDRESS_HOME_STATE,
565                                      ADDRESS_HOME_ZIP,
566                                      ADDRESS_HOME_COUNTRY,
567                                      PHONE_HOME_NUMBER,
568                                      PHONE_FAX_NUMBER };
569  if (p1.Label() == p2.Label())
570    return false;
571
572  for (size_t index = 0; index < arraysize(types); ++index) {
573    if (p1.GetFieldText(AutoFillType(types[index])) !=
574        p2.GetFieldText(AutoFillType(types[index])))
575      return false;
576  }
577  return true;
578}
579
580MATCHER_P(ProfileMatchesExceptLabel, profile, "") {
581  return ProfilesMatchExceptLabelImpl(arg, profile);
582}
583
584TEST_F(ProfileSyncServiceAutofillTest, HasDuplicateProfileLabelsEmptySync) {
585  std::vector<AutoFillProfile> expected_profiles;
586  std::vector<AutoFillProfile*> profiles;
587  AutoFillProfile* profile0 = new AutoFillProfile(string16(), 0);
588  autofill_unittest::SetProfileInfo(profile0,
589      "Billing", "Marion", "Mitchell", "Morrison",
590      "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
591      "91601", "US", "12345678910", "01987654321");
592  AutoFillProfile* profile1 = new AutoFillProfile(string16(), 0);
593  autofill_unittest::SetProfileInfo(profile1,
594      "Billing", "Same", "Label", "Morrison",
595      "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
596      "91601", "US", "12345678910", "01987654321");
597  profiles.push_back(profile0);
598  profiles.push_back(profile1);
599  expected_profiles.push_back(*profile0);
600  expected_profiles.push_back(*profile1);
601  AutoFillProfile relabelled_profile;
602  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
603  EXPECT_CALL(*personal_data_manager_, Refresh());
604  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
605      WillOnce(DoAll(SetArgumentPointee<0>(profiles), Return(true)));
606  EXPECT_CALL(web_database_, UpdateAutoFillProfile(
607      ProfileMatchesExceptLabel(expected_profiles[1]))).
608      WillOnce(DoAll(SaveArg<0>(&relabelled_profile), Return(true)));
609
610  SetIdleChangeProcessorExpectations();
611  CreateRootTask task(this, syncable::AUTOFILL);
612  StartSyncService(&task, false);
613  ASSERT_TRUE(task.success());
614  std::vector<AutofillEntry> sync_entries;
615  std::vector<AutoFillProfile> sync_profiles;
616  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
617  EXPECT_EQ(0U, sync_entries.size());
618  EXPECT_EQ(2U, sync_profiles.size());
619  EXPECT_EQ(expected_profiles[0], sync_profiles[1]);
620  EXPECT_TRUE(ProfilesMatchExceptLabelImpl(expected_profiles[1],
621                                           sync_profiles[0]));
622  EXPECT_EQ(sync_profiles[0].Label(), relabelled_profile.Label());
623}
624
625TEST_F(ProfileSyncServiceAutofillTest, HasNativeWithDuplicatesEmptySync) {
626  // There is buggy autofill code that allows duplicate name/value
627  // pairs to exist in the database with separate pair_ids.
628  std::vector<AutofillEntry> entries;
629  entries.push_back(MakeAutofillEntry("foo", "bar", 1));
630  entries.push_back(MakeAutofillEntry("dup", "", 2));
631  entries.push_back(MakeAutofillEntry("dup", "", 3));
632  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).
633      WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true)));
634  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
635  SetIdleChangeProcessorExpectations();
636  CreateRootTask task(this, syncable::AUTOFILL);
637  EXPECT_CALL(*personal_data_manager_, Refresh());
638  StartSyncService(&task, false);
639  ASSERT_TRUE(task.success());
640  std::vector<AutofillEntry> sync_entries;
641  std::vector<AutoFillProfile> sync_profiles;
642  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
643  EXPECT_EQ(2U, sync_entries.size());
644}
645
646TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncNoMerge) {
647  AutofillEntry native_entry(MakeAutofillEntry("native", "entry", 1));
648  AutofillEntry sync_entry(MakeAutofillEntry("sync", "entry", 2));
649  AutoFillProfile sync_profile(string16(), 0);
650  autofill_unittest::SetProfileInfo(&sync_profile,
651      "Billing", "Marion", "Mitchell", "Morrison",
652      "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
653      "91601", "US", "12345678910", "01987654321");
654
655  AutoFillProfile* native_profile = new AutoFillProfile(string16(), 0);
656  autofill_unittest::SetProfileInfo(native_profile,
657      "Work", "Josephine", "Alicia", "Saenz",
658      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
659      "32801", "US", "19482937549", "13502849239");
660
661  std::vector<AutofillEntry> native_entries;
662  native_entries.push_back(native_entry);
663  std::vector<AutoFillProfile*> native_profiles;
664  native_profiles.push_back(native_profile);
665
666  std::vector<AutoFillProfile> expected_profiles;
667  expected_profiles.push_back(*native_profile);
668  expected_profiles.push_back(sync_profile);
669
670  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).
671      WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true)));
672  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
673      WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true)));
674  std::vector<AutofillEntry> sync_entries;
675  sync_entries.push_back(sync_entry);
676  std::vector<AutoFillProfile> sync_profiles;
677  sync_profiles.push_back(sync_profile);
678  AddAutofillEntriesTask task(this, sync_entries, sync_profiles);
679
680  AutoFillProfile to_be_added(sync_profile);
681  to_be_added.set_unique_id(1);
682  EXPECT_CALL(web_database_, UpdateAutofillEntries(ElementsAre(sync_entry))).
683      WillOnce(Return(true));
684  EXPECT_CALL(web_database_, AddAutoFillProfile(Eq(to_be_added))).
685      WillOnce(Return(true));
686  EXPECT_CALL(*personal_data_manager_, Refresh());
687  StartSyncService(&task, false);
688  ASSERT_TRUE(task.success());
689
690  std::set<AutofillEntry> expected_entries;
691  expected_entries.insert(native_entry);
692  expected_entries.insert(sync_entry);
693
694  std::vector<AutofillEntry> new_sync_entries;
695  std::vector<AutoFillProfile> new_sync_profiles;
696  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
697                                           &new_sync_profiles));
698  std::set<AutofillEntry> new_sync_entries_set(new_sync_entries.begin(),
699                                               new_sync_entries.end());
700
701  EXPECT_TRUE(expected_entries == new_sync_entries_set);
702  EXPECT_EQ(2U, new_sync_profiles.size());
703  EXPECT_EQ(expected_profiles[0], new_sync_profiles[0]);
704  EXPECT_EQ(expected_profiles[1], new_sync_profiles[1]);
705}
706
707TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncMergeEntry) {
708  AutofillEntry native_entry(MakeAutofillEntry("merge", "entry", 1));
709  AutofillEntry sync_entry(MakeAutofillEntry("merge", "entry", 2));
710  AutofillEntry merged_entry(MakeAutofillEntry("merge", "entry", 1, 2));
711
712  std::vector<AutofillEntry> native_entries;
713  native_entries.push_back(native_entry);
714  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).
715      WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true)));
716  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
717
718  std::vector<AutofillEntry> sync_entries;
719  std::vector<AutoFillProfile> sync_profiles;
720  sync_entries.push_back(sync_entry);
721  AddAutofillEntriesTask task(this, sync_entries, sync_profiles);
722
723  EXPECT_CALL(web_database_, UpdateAutofillEntries(ElementsAre(merged_entry))).
724      WillOnce(Return(true));
725  EXPECT_CALL(*personal_data_manager_, Refresh());
726  StartSyncService(&task, false);
727  ASSERT_TRUE(task.success());
728
729  std::vector<AutofillEntry> new_sync_entries;
730  std::vector<AutoFillProfile> new_sync_profiles;
731  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
732                                           &new_sync_profiles));
733  ASSERT_EQ(1U, new_sync_entries.size());
734  EXPECT_TRUE(merged_entry == new_sync_entries[0]);
735}
736
737TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncMergeProfile) {
738  AutoFillProfile sync_profile(string16(), 0);
739  autofill_unittest::SetProfileInfo(&sync_profile,
740      "Billing", "Marion", "Mitchell", "Morrison",
741      "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
742      "91601", "US", "12345678910", "01987654321");
743
744  AutoFillProfile* native_profile = new AutoFillProfile(string16(), 0);
745  autofill_unittest::SetProfileInfo(native_profile,
746      "Billing", "Josephine", "Alicia", "Saenz",
747      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
748      "32801", "US", "19482937549", "13502849239");
749
750  std::vector<AutoFillProfile*> native_profiles;
751  native_profiles.push_back(native_profile);
752  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true));
753  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
754      WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true)));
755
756  std::vector<AutofillEntry> sync_entries;
757  std::vector<AutoFillProfile> sync_profiles;
758  sync_profiles.push_back(sync_profile);
759  AddAutofillEntriesTask task(this, sync_entries, sync_profiles);
760
761  EXPECT_CALL(web_database_, UpdateAutoFillProfile(Eq(sync_profile))).
762      WillOnce(Return(true));
763  EXPECT_CALL(*personal_data_manager_, Refresh());
764  StartSyncService(&task, false);
765  ASSERT_TRUE(task.success());
766
767  std::vector<AutofillEntry> new_sync_entries;
768  std::vector<AutoFillProfile> new_sync_profiles;
769  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
770                                           &new_sync_profiles));
771  ASSERT_EQ(1U, new_sync_profiles.size());
772  EXPECT_TRUE(sync_profile == new_sync_profiles[0]);
773}
774
775TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddEntry) {
776  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
777  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
778  EXPECT_CALL(*personal_data_manager_, Refresh());
779  SetIdleChangeProcessorExpectations();
780  CreateRootTask task(this, syncable::AUTOFILL);
781  StartSyncService(&task, false);
782  ASSERT_TRUE(task.success());
783
784  AutofillEntry added_entry(MakeAutofillEntry("added", "entry", 1));
785  std::vector<base::Time> timestamps(added_entry.timestamps());
786
787  EXPECT_CALL(web_database_, GetAutofillTimestamps(_, _, _)).
788      WillOnce(DoAll(SetArgumentPointee<2>(timestamps), Return(true)));
789
790  AutofillChangeList changes;
791  changes.push_back(AutofillChange(AutofillChange::ADD, added_entry.key()));
792  scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
793  notifier->Notify(NotificationType::AUTOFILL_ENTRIES_CHANGED,
794                   Source<WebDataService>(web_data_service_.get()),
795                   Details<AutofillChangeList>(&changes));
796
797  std::vector<AutofillEntry> new_sync_entries;
798  std::vector<AutoFillProfile> new_sync_profiles;
799  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
800                                           &new_sync_profiles));
801  ASSERT_EQ(1U, new_sync_entries.size());
802  EXPECT_TRUE(added_entry == new_sync_entries[0]);
803}
804
805TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfile) {
806  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
807  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
808  EXPECT_CALL(*personal_data_manager_, Refresh());
809  SetIdleChangeProcessorExpectations();
810  CreateRootTask task(this, syncable::AUTOFILL);
811  StartSyncService(&task, false);
812  ASSERT_TRUE(task.success());
813
814  AutoFillProfile added_profile(string16(), 0);
815  autofill_unittest::SetProfileInfo(&added_profile,
816      "Billing", "Josephine", "Alicia", "Saenz",
817      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
818      "32801", "US", "19482937549", "13502849239");
819
820  AutofillProfileChange change(AutofillProfileChange::ADD,
821      added_profile.Label(), &added_profile, string16());
822  scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
823  notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED,
824                   Source<WebDataService>(web_data_service_.get()),
825                   Details<AutofillProfileChange>(&change));
826
827  std::vector<AutofillEntry> new_sync_entries;
828  std::vector<AutoFillProfile> new_sync_profiles;
829  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
830                                           &new_sync_profiles));
831  ASSERT_EQ(1U, new_sync_profiles.size());
832  EXPECT_TRUE(added_profile == new_sync_profiles[0]);
833}
834
835TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfileConflict) {
836  AutoFillProfile sync_profile(string16(), 0);
837  autofill_unittest::SetProfileInfo(&sync_profile,
838      "Billing", "Marion", "Mitchell", "Morrison",
839      "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
840      "91601", "US", "12345678910", "01987654321");
841
842  std::vector<AutofillEntry> sync_entries;
843  std::vector<AutoFillProfile> sync_profiles;
844  sync_profiles.push_back(sync_profile);
845  AddAutofillEntriesTask task(this, sync_entries, sync_profiles);
846
847  sync_profile.set_unique_id(1);
848  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
849  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
850  EXPECT_CALL(web_database_, AddAutoFillProfile(Eq(sync_profile))).
851              WillOnce(Return(true));
852  EXPECT_CALL(*personal_data_manager_, Refresh());
853  SetIdleChangeProcessorExpectations();
854  StartSyncService(&task, false);
855  ASSERT_TRUE(task.success());
856
857  AutoFillProfile added_profile(string16(), 0);
858  autofill_unittest::SetProfileInfo(&added_profile,
859      "Billing", "Josephine", "Alicia", "Saenz",
860      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
861      "32801", "US", "19482937549", "13502849239");
862
863  AutofillProfileChange change(AutofillProfileChange::ADD,
864      added_profile.Label(), &added_profile, string16());
865
866  AutoFillProfile relabelled_profile;
867  EXPECT_CALL(web_database_, UpdateAutoFillProfile(
868      ProfileMatchesExceptLabel(added_profile))).
869      WillOnce(DoAll(SaveArg<0>(&relabelled_profile), Return(true)));
870  EXPECT_CALL(*personal_data_manager_, Refresh());
871
872  scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
873  notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED,
874                   Source<WebDataService>(web_data_service_.get()),
875                   Details<AutofillProfileChange>(&change));
876
877  std::vector<AutofillEntry> new_sync_entries;
878  std::vector<AutoFillProfile> new_sync_profiles;
879  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
880                                           &new_sync_profiles));
881  ASSERT_EQ(2U, new_sync_profiles.size());
882  sync_profile.set_unique_id(0);  // The sync DB doesn't store IDs.
883  EXPECT_EQ(sync_profile, new_sync_profiles[1]);
884  EXPECT_TRUE(ProfilesMatchExceptLabelImpl(added_profile,
885                                           new_sync_profiles[0]));
886  EXPECT_EQ(new_sync_profiles[0].Label(), relabelled_profile.Label());
887}
888
889TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateEntry) {
890  AutofillEntry original_entry(MakeAutofillEntry("my", "entry", 1));
891  std::vector<AutofillEntry> original_entries;
892  original_entries.push_back(original_entry);
893
894  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).
895      WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true)));
896  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
897  EXPECT_CALL(*personal_data_manager_, Refresh());
898  CreateRootTask task(this, syncable::AUTOFILL);
899  StartSyncService(&task, false);
900  ASSERT_TRUE(task.success());
901
902  AutofillEntry updated_entry(MakeAutofillEntry("my", "entry", 1, 2));
903  std::vector<base::Time> timestamps(updated_entry.timestamps());
904
905  EXPECT_CALL(web_database_, GetAutofillTimestamps(_, _, _)).
906      WillOnce(DoAll(SetArgumentPointee<2>(timestamps), Return(true)));
907
908  AutofillChangeList changes;
909  changes.push_back(AutofillChange(AutofillChange::UPDATE,
910                                   updated_entry.key()));
911  scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
912  notifier->Notify(NotificationType::AUTOFILL_ENTRIES_CHANGED,
913                   Source<WebDataService>(web_data_service_.get()),
914                   Details<AutofillChangeList>(&changes));
915
916  std::vector<AutofillEntry> new_sync_entries;
917  std::vector<AutoFillProfile> new_sync_profiles;
918  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
919                                           &new_sync_profiles));
920  ASSERT_EQ(1U, new_sync_entries.size());
921  EXPECT_TRUE(updated_entry == new_sync_entries[0]);
922}
923
924
925TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateProfile) {
926  AutoFillProfile* native_profile = new AutoFillProfile(string16(), 0);
927  autofill_unittest::SetProfileInfo(native_profile,
928      "Billing", "Josephine", "Alicia", "Saenz",
929      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
930      "32801", "US", "19482937549", "13502849239");
931  std::vector<AutoFillProfile*> native_profiles;
932  native_profiles.push_back(native_profile);
933  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true));
934  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
935      WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true)));
936  EXPECT_CALL(*personal_data_manager_, Refresh());
937  CreateRootTask task(this, syncable::AUTOFILL);
938  StartSyncService(&task, false);
939  ASSERT_TRUE(task.success());
940
941  AutoFillProfile update_profile(string16(), 0);
942  autofill_unittest::SetProfileInfo(&update_profile,
943      "Billing", "Changin'", "Mah", "Namez",
944      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
945      "32801", "US", "19482937549", "13502849239");
946
947  AutofillProfileChange change(AutofillProfileChange::UPDATE,
948                               update_profile.Label(), &update_profile,
949                               ASCIIToUTF16("Billing"));
950  scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
951  notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED,
952                   Source<WebDataService>(web_data_service_.get()),
953                   Details<AutofillProfileChange>(&change));
954
955  std::vector<AutofillEntry> new_sync_entries;
956  std::vector<AutoFillProfile> new_sync_profiles;
957  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
958                                           &new_sync_profiles));
959  ASSERT_EQ(1U, new_sync_profiles.size());
960  EXPECT_TRUE(update_profile == new_sync_profiles[0]);
961}
962
963TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateProfileRelabel) {
964  AutoFillProfile* native_profile = new AutoFillProfile(string16(), 0);
965  autofill_unittest::SetProfileInfo(native_profile,
966      "Billing", "Josephine", "Alicia", "Saenz",
967      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
968      "32801", "US", "19482937549", "13502849239");
969  std::vector<AutoFillProfile*> native_profiles;
970  native_profiles.push_back(native_profile);
971  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true));
972  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
973      WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true)));
974  EXPECT_CALL(*personal_data_manager_, Refresh());
975  CreateRootTask task(this, syncable::AUTOFILL);
976  StartSyncService(&task, false);
977  ASSERT_TRUE(task.success());
978
979  AutoFillProfile update_profile(string16(), 0);
980  autofill_unittest::SetProfileInfo(&update_profile,
981      "TRYIN 2 FOOL U", "Josephine", "Alicia", "Saenz",
982      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
983      "32801", "US", "19482937549", "13502849239");
984
985  AutofillProfileChange change(AutofillProfileChange::UPDATE,
986                               update_profile.Label(), &update_profile,
987                               ASCIIToUTF16("Billing"));
988  scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
989  notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED,
990                   Source<WebDataService>(web_data_service_.get()),
991                   Details<AutofillProfileChange>(&change));
992
993  std::vector<AutofillEntry> new_sync_entries;
994  std::vector<AutoFillProfile> new_sync_profiles;
995  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
996                                           &new_sync_profiles));
997  ASSERT_EQ(1U, new_sync_profiles.size());
998  EXPECT_TRUE(update_profile == new_sync_profiles[0]);
999}
1000
1001TEST_F(ProfileSyncServiceAutofillTest,
1002       ProcessUserChangeUpdateProfileRelabelConflict) {
1003  std::vector<AutoFillProfile*> native_profiles;
1004  native_profiles.push_back(new AutoFillProfile(string16(), 0));
1005  native_profiles.push_back(new AutoFillProfile(string16(), 0));
1006  autofill_unittest::SetProfileInfo(native_profiles[0],
1007      "Billing", "Josephine", "Alicia", "Saenz",
1008      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
1009      "32801", "US", "19482937549", "13502849239");
1010  autofill_unittest::SetProfileInfo(native_profiles[1],
1011      "ExistingLabel", "Marion", "Mitchell", "Morrison",
1012      "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
1013      "91601", "US", "12345678910", "01987654321");
1014  AutoFillProfile marion(*native_profiles[1]);
1015  AutoFillProfile josephine(*native_profiles[0]);
1016
1017  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true));
1018  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
1019      WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true)));
1020  EXPECT_CALL(*personal_data_manager_, Refresh());
1021  CreateRootTask task(this, syncable::AUTOFILL);
1022  StartSyncService(&task, false);
1023  ASSERT_TRUE(task.success());
1024  MessageLoop::current()->RunAllPending();
1025  Mock::VerifyAndClearExpectations(&web_database_);
1026  native_profiles.clear();  // Contents freed.
1027
1028  // Update josephine twice with marion's label.  The second time ought to be
1029  // idempotent, settling on the same name and not triggering a sync upload.
1030  for (int pass = 0; pass < 2; ++pass) {
1031    AutoFillProfile josephine_update(josephine);
1032    josephine_update.set_label(ASCIIToUTF16("ExistingLabel"));
1033
1034    AutoFillProfile relabelled_profile;
1035    EXPECT_CALL(web_database_, UpdateAutoFillProfile(
1036        ProfileMatchesExceptLabel(josephine_update))).
1037        WillOnce(DoAll(SaveArg<0>(&relabelled_profile), Return(true)));
1038    EXPECT_CALL(*personal_data_manager_, Refresh());
1039
1040    AutofillProfileChange change(AutofillProfileChange::UPDATE,
1041                                 josephine_update.Label(), &josephine_update,
1042                                 josephine.Label());
1043    scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
1044    notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED,
1045                     Source<WebDataService>(web_data_service_.get()),
1046                     Details<AutofillProfileChange>(&change));
1047    MessageLoop::current()->RunAllPending();  // Run the Refresh task.
1048    Mock::VerifyAndClearExpectations(&web_database_);
1049
1050    std::vector<AutofillEntry> new_sync_entries;
1051    std::vector<AutoFillProfile> new_sync_profiles;
1052    ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
1053                                             &new_sync_profiles));
1054    ASSERT_EQ(2U, new_sync_profiles.size());
1055    marion.set_unique_id(0);  // The sync DB doesn't store IDs.
1056    EXPECT_EQ(marion, new_sync_profiles[1]);
1057    EXPECT_TRUE(ProfilesMatchExceptLabelImpl(josephine_update,
1058                                             new_sync_profiles[0]));
1059    EXPECT_EQ(ASCIIToUTF16("ExistingLabel2"), new_sync_profiles[0].Label());
1060    EXPECT_EQ(ASCIIToUTF16("ExistingLabel2"), relabelled_profile.Label());
1061    josephine = relabelled_profile;
1062  }
1063}
1064
1065TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeRemoveEntry) {
1066  AutofillEntry original_entry(MakeAutofillEntry("my", "entry", 1));
1067  std::vector<AutofillEntry> original_entries;
1068  original_entries.push_back(original_entry);
1069
1070  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).
1071      WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true)));
1072  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
1073  EXPECT_CALL(*personal_data_manager_, Refresh());
1074  CreateRootTask task(this, syncable::AUTOFILL);
1075  StartSyncService(&task, false);
1076  ASSERT_TRUE(task.success());
1077
1078  AutofillChangeList changes;
1079  changes.push_back(AutofillChange(AutofillChange::REMOVE,
1080                                   original_entry.key()));
1081  scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
1082  notifier->Notify(NotificationType::AUTOFILL_ENTRIES_CHANGED,
1083                   Source<WebDataService>(web_data_service_.get()),
1084                   Details<AutofillChangeList>(&changes));
1085
1086  std::vector<AutofillEntry> new_sync_entries;
1087  std::vector<AutoFillProfile> new_sync_profiles;
1088  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
1089                                           &new_sync_profiles));
1090  ASSERT_EQ(0U, new_sync_entries.size());
1091}
1092
1093TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeRemoveProfile) {
1094  AutoFillProfile sync_profile(string16(), 0);
1095  autofill_unittest::SetProfileInfo(&sync_profile,
1096      "Billing", "Josephine", "Alicia", "Saenz",
1097      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
1098      "32801", "US", "19482937549", "13502849239");
1099  AutoFillProfile* native_profile = new AutoFillProfile(string16(), 0);
1100  autofill_unittest::SetProfileInfo(native_profile,
1101      "Billing", "Josephine", "Alicia", "Saenz",
1102      "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
1103      "32801", "US", "19482937549", "13502849239");
1104
1105  std::vector<AutoFillProfile*> native_profiles;
1106  native_profiles.push_back(native_profile);
1107  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true));
1108  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
1109      WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true)));
1110
1111  std::vector<AutofillEntry> sync_entries;
1112  std::vector<AutoFillProfile> sync_profiles;
1113  sync_profiles.push_back(sync_profile);
1114  AddAutofillEntriesTask task(this, sync_entries, sync_profiles);
1115  EXPECT_CALL(*personal_data_manager_, Refresh());
1116  StartSyncService(&task, false);
1117  ASSERT_TRUE(task.success());
1118
1119  AutofillProfileChange change(AutofillProfileChange::REMOVE,
1120                               sync_profile.Label(), NULL, string16());
1121  scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
1122  notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED,
1123                   Source<WebDataService>(web_data_service_.get()),
1124                   Details<AutofillProfileChange>(&change));
1125
1126  std::vector<AutofillEntry> new_sync_entries;
1127  std::vector<AutoFillProfile> new_sync_profiles;
1128  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
1129                                           &new_sync_profiles));
1130  ASSERT_EQ(0U, new_sync_entries.size());
1131}
1132
1133TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeError) {
1134  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
1135  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
1136  EXPECT_CALL(*personal_data_manager_, Refresh());
1137  CreateRootTask task(this, syncable::AUTOFILL);
1138  StartSyncService(&task, false);
1139  ASSERT_TRUE(task.success());
1140
1141  // Inject an evil entry into the sync db to conflict with the same
1142  // entry added by the user.
1143  AutofillEntry evil_entry(MakeAutofillEntry("evil", "entry", 1));
1144  ASSERT_TRUE(AddAutofillSyncNode(evil_entry));
1145
1146  AutofillChangeList changes;
1147  changes.push_back(AutofillChange(AutofillChange::ADD,
1148                                   evil_entry.key()));
1149  scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
1150  notifier->Notify(NotificationType::AUTOFILL_ENTRIES_CHANGED,
1151                   Source<WebDataService>(web_data_service_.get()),
1152                   Details<AutofillChangeList>(&changes));
1153
1154  // Wait for the PPS to shut everything down and signal us.
1155  ProfileSyncServiceObserverMock observer;
1156  service_->AddObserver(&observer);
1157  EXPECT_CALL(observer, OnStateChanged()).WillOnce(QuitUIMessageLoop());
1158  MessageLoop::current()->Run();
1159  EXPECT_TRUE(service_->unrecoverable_error_detected());
1160
1161  // Ensure future autofill notifications don't crash.
1162  notifier->Notify(NotificationType::AUTOFILL_ENTRIES_CHANGED,
1163                   Source<WebDataService>(web_data_service_.get()),
1164                   Details<AutofillChangeList>(&changes));
1165}
1166
1167TEST_F(ProfileSyncServiceAutofillTest, ServerChangeRace) {
1168  EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
1169  EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
1170  EXPECT_CALL(web_database_, UpdateAutofillEntries(_)).
1171      WillRepeatedly(Return(true));
1172  EXPECT_CALL(*personal_data_manager_, Refresh()).Times(3);
1173  CreateRootTask task(this, syncable::AUTOFILL);
1174  StartSyncService(&task, false);
1175  ASSERT_TRUE(task.success());
1176
1177  // (true, false) means we have to reset after |Signal|, init to unsignaled.
1178  scoped_ptr<WaitableEvent> wait_for_start(new WaitableEvent(true, false));
1179  scoped_ptr<WaitableEvent> wait_for_syncapi(new WaitableEvent(true, false));
1180  scoped_refptr<FakeServerUpdater> updater = new FakeServerUpdater(
1181      service_.get(), &wait_for_start, &wait_for_syncapi);
1182
1183  // This server side update will stall waiting for CommitWaiter.
1184  updater->CreateNewEntry(MakeAutofillEntry("server", "entry", 1));
1185  wait_for_start->Wait();
1186
1187  AutofillEntry syncapi_entry(MakeAutofillEntry("syncapi", "entry", 2));
1188  ASSERT_TRUE(AddAutofillSyncNode(syncapi_entry));
1189  LOG(INFO) << "Syncapi update finished.";
1190
1191  // If we reach here, it means syncapi succeeded and we didn't deadlock. Yay!
1192  // Signal FakeServerUpdater that it can complete.
1193  wait_for_syncapi->Signal();
1194
1195  // Make another entry to ensure nothing broke afterwards and wait for finish
1196  // to clean up.
1197  updater->CreateNewEntryAndWait(MakeAutofillEntry("server2", "entry2", 3));
1198
1199  std::vector<AutofillEntry> sync_entries;
1200  std::vector<AutoFillProfile> sync_profiles;
1201  ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
1202  EXPECT_EQ(3U, sync_entries.size());
1203  EXPECT_EQ(0U, sync_profiles.size());
1204  for (size_t i = 0; i < sync_entries.size(); i++) {
1205    LOG(INFO) << "Entry " << i << ": " << sync_entries[i].key().name() << ", "
1206              << sync_entries[i].key().value();
1207  }
1208}
1209