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