1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/sync/test/integration/autofill_helper.h"
6
7#include "chrome/browser/autofill/personal_data_manager_factory.h"
8#include "chrome/browser/chrome_notification_types.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/sync/profile_sync_service.h"
11#include "chrome/browser/sync/profile_sync_test_util.h"
12#include "chrome/browser/sync/test/integration/multi_client_status_change_checker.h"
13#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
14#include "chrome/browser/sync/test/integration/sync_test.h"
15#include "chrome/browser/webdata/web_data_service_factory.h"
16#include "components/autofill/core/browser/autofill_profile.h"
17#include "components/autofill/core/browser/autofill_test_utils.h"
18#include "components/autofill/core/browser/autofill_type.h"
19#include "components/autofill/core/browser/personal_data_manager.h"
20#include "components/autofill/core/browser/personal_data_manager_observer.h"
21#include "components/autofill/core/browser/webdata/autofill_entry.h"
22#include "components/autofill/core/browser/webdata/autofill_table.h"
23#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
24#include "components/autofill/core/common/form_field_data.h"
25#include "components/webdata/common/web_database.h"
26
27using autofill::AutofillChangeList;
28using autofill::AutofillEntry;
29using autofill::AutofillKey;
30using autofill::AutofillProfile;
31using autofill::AutofillTable;
32using autofill::AutofillType;
33using autofill::AutofillWebDataService;
34using autofill::AutofillWebDataServiceObserverOnDBThread;
35using autofill::CreditCard;
36using autofill::FormFieldData;
37using autofill::PersonalDataManager;
38using autofill::PersonalDataManagerObserver;
39using base::WaitableEvent;
40using content::BrowserThread;
41using sync_datatype_helper::test;
42using testing::_;
43
44namespace {
45
46ACTION_P(SignalEvent, event) {
47  event->Signal();
48}
49
50class MockWebDataServiceObserver
51    : public AutofillWebDataServiceObserverOnDBThread {
52 public:
53  MOCK_METHOD1(AutofillEntriesChanged,
54               void(const AutofillChangeList& changes));
55};
56
57class MockPersonalDataManagerObserver : public PersonalDataManagerObserver {
58 public:
59  MOCK_METHOD0(OnPersonalDataChanged, void());
60};
61
62void RunOnDBThreadAndSignal(base::Closure task,
63                            base::WaitableEvent* done_event) {
64  if (!task.is_null()) {
65    task.Run();
66  }
67  done_event->Signal();
68}
69
70void RunOnDBThreadAndBlock(base::Closure task) {
71  WaitableEvent done_event(false, false);
72  BrowserThread::PostTask(BrowserThread::DB,
73                          FROM_HERE,
74                          Bind(&RunOnDBThreadAndSignal, task, &done_event));
75  done_event.Wait();
76}
77
78void RemoveKeyDontBlockForSync(int profile, const AutofillKey& key) {
79  WaitableEvent done_event(false, false);
80
81  MockWebDataServiceObserver mock_observer;
82  EXPECT_CALL(mock_observer, AutofillEntriesChanged(_))
83      .WillOnce(SignalEvent(&done_event));
84
85  scoped_refptr<AutofillWebDataService> wds =
86      autofill_helper::GetWebDataService(profile);
87
88  void(AutofillWebDataService::*add_observer_func)(
89      AutofillWebDataServiceObserverOnDBThread*) =
90      &AutofillWebDataService::AddObserver;
91  RunOnDBThreadAndBlock(Bind(add_observer_func, wds, &mock_observer));
92
93  wds->RemoveFormValueForElementName(key.name(), key.value());
94  done_event.Wait();
95
96  void(AutofillWebDataService::*remove_observer_func)(
97      AutofillWebDataServiceObserverOnDBThread*) =
98      &AutofillWebDataService::RemoveObserver;
99  RunOnDBThreadAndBlock(Bind(remove_observer_func, wds, &mock_observer));
100}
101
102void GetAllAutofillEntriesOnDBThread(AutofillWebDataService* wds,
103                                     std::vector<AutofillEntry>* entries) {
104  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
105  AutofillTable::FromWebDatabase(
106      wds->GetDatabase())->GetAllAutofillEntries(entries);
107}
108
109std::vector<AutofillEntry> GetAllAutofillEntries(AutofillWebDataService* wds) {
110  std::vector<AutofillEntry> entries;
111  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
112  RunOnDBThreadAndBlock(Bind(&GetAllAutofillEntriesOnDBThread,
113                             Unretained(wds),
114                             &entries));
115  return entries;
116}
117
118// UI thread returns from the update operations on the DB thread and schedules
119// the sync. This function blocks until after this scheduled sync is complete by
120// scheduling additional empty task on DB Thread. Call after AddKeys/RemoveKey.
121void BlockForPendingDBThreadTasks() {
122  // The order of the notifications is undefined, so sync change sometimes is
123  // posted after the notification for observer_helper. Post new task to db
124  // thread that guaranteed to be after sync and would be blocking until
125  // completion.
126  RunOnDBThreadAndBlock(base::Closure());
127}
128
129}  // namespace
130
131namespace autofill_helper {
132
133AutofillProfile CreateAutofillProfile(ProfileType type) {
134  AutofillProfile profile;
135  switch (type) {
136    case PROFILE_MARION:
137      autofill::test::SetProfileInfoWithGuid(&profile,
138          "C837507A-6C3B-4872-AC14-5113F157D668",
139          "Marion", "Mitchell", "Morrison",
140          "johnwayne@me.xyz", "Fox",
141          "123 Zoo St.", "unit 5", "Hollywood", "CA",
142          "91601", "US", "12345678910");
143      break;
144    case PROFILE_HOMER:
145      autofill::test::SetProfileInfoWithGuid(&profile,
146          "137DE1C3-6A30-4571-AC86-109B1ECFBE7F",
147          "Homer", "J.", "Simpson",
148          "homer@abc.com", "SNPP",
149          "1 Main St", "PO Box 1", "Springfield", "MA",
150          "94101", "US", "14155551212");
151      break;
152    case PROFILE_FRASIER:
153      autofill::test::SetProfileInfoWithGuid(&profile,
154          "9A5E6872-6198-4688-BF75-0016E781BB0A",
155          "Frasier", "Winslow", "Crane",
156          "", "randomness", "", "Apt. 4", "Seattle", "WA",
157          "99121", "US", "0000000000");
158      break;
159    case PROFILE_NULL:
160      autofill::test::SetProfileInfoWithGuid(&profile,
161          "FE461507-7E13-4198-8E66-74C7DB6D8322",
162          "", "", "", "", "", "", "", "", "", "", "", "");
163      break;
164  }
165  return profile;
166}
167
168scoped_refptr<AutofillWebDataService> GetWebDataService(int index) {
169  return WebDataServiceFactory::GetAutofillWebDataForProfile(
170      test()->GetProfile(index), Profile::EXPLICIT_ACCESS);
171}
172
173PersonalDataManager* GetPersonalDataManager(int index) {
174  return autofill::PersonalDataManagerFactory::GetForProfile(
175      test()->GetProfile(index));
176}
177
178void AddKeys(int profile, const std::set<AutofillKey>& keys) {
179  std::vector<FormFieldData> form_fields;
180  for (std::set<AutofillKey>::const_iterator i = keys.begin();
181       i != keys.end();
182       ++i) {
183    FormFieldData field;
184    field.name = i->name();
185    field.value = i->value();
186    form_fields.push_back(field);
187  }
188
189  WaitableEvent done_event(false, false);
190  MockWebDataServiceObserver mock_observer;
191  EXPECT_CALL(mock_observer, AutofillEntriesChanged(_))
192      .WillOnce(SignalEvent(&done_event));
193
194  scoped_refptr<AutofillWebDataService> wds = GetWebDataService(profile);
195
196  void(AutofillWebDataService::*add_observer_func)(
197      AutofillWebDataServiceObserverOnDBThread*) =
198      &AutofillWebDataService::AddObserver;
199  RunOnDBThreadAndBlock(Bind(add_observer_func, wds, &mock_observer));
200
201  wds->AddFormFields(form_fields);
202  done_event.Wait();
203  BlockForPendingDBThreadTasks();
204
205  void(AutofillWebDataService::*remove_observer_func)(
206      AutofillWebDataServiceObserverOnDBThread*) =
207      &AutofillWebDataService::RemoveObserver;
208  RunOnDBThreadAndBlock(Bind(remove_observer_func, wds, &mock_observer));
209}
210
211void RemoveKey(int profile, const AutofillKey& key) {
212  RemoveKeyDontBlockForSync(profile, key);
213  BlockForPendingDBThreadTasks();
214}
215
216void RemoveKeys(int profile) {
217  std::set<AutofillEntry> keys = GetAllKeys(profile);
218  for (std::set<AutofillEntry>::const_iterator it = keys.begin();
219       it != keys.end(); ++it) {
220    RemoveKeyDontBlockForSync(profile, it->key());
221  }
222  BlockForPendingDBThreadTasks();
223}
224
225std::set<AutofillEntry> GetAllKeys(int profile) {
226  scoped_refptr<AutofillWebDataService> wds = GetWebDataService(profile);
227  std::vector<AutofillEntry> all_entries = GetAllAutofillEntries(wds.get());
228  std::set<AutofillEntry> all_keys;
229  for (std::vector<AutofillEntry>::const_iterator it = all_entries.begin();
230       it != all_entries.end(); ++it) {
231    all_keys.insert(*it);
232  }
233  return all_keys;
234}
235
236bool KeysMatch(int profile_a, int profile_b) {
237  return GetAllKeys(profile_a) == GetAllKeys(profile_b);
238}
239
240namespace {
241
242class KeysMatchStatusChecker : public MultiClientStatusChangeChecker {
243 public:
244  KeysMatchStatusChecker(int profile_a, int profile_b);
245  virtual ~KeysMatchStatusChecker();
246
247  virtual bool IsExitConditionSatisfied() OVERRIDE;
248  virtual std::string GetDebugMessage() const OVERRIDE;
249
250 private:
251  const int profile_a_;
252  const int profile_b_;
253};
254
255KeysMatchStatusChecker::KeysMatchStatusChecker(int profile_a, int profile_b)
256    : MultiClientStatusChangeChecker(
257          sync_datatype_helper::test()->GetSyncServices()),
258      profile_a_(profile_a),
259      profile_b_(profile_b) {
260}
261
262KeysMatchStatusChecker::~KeysMatchStatusChecker() {
263}
264
265bool KeysMatchStatusChecker::IsExitConditionSatisfied() {
266  return KeysMatch(profile_a_, profile_b_);
267}
268
269std::string KeysMatchStatusChecker::GetDebugMessage() const {
270  return "Waiting for matching autofill keys";
271}
272
273}  // namespace
274
275bool AwaitKeysMatch(int a, int b) {
276  KeysMatchStatusChecker checker(a, b);
277  checker.Wait();
278  return !checker.TimedOut();
279}
280
281void SetProfiles(int profile, std::vector<AutofillProfile>* autofill_profiles) {
282  MockPersonalDataManagerObserver observer;
283  EXPECT_CALL(observer, OnPersonalDataChanged()).
284      WillOnce(QuitUIMessageLoop());
285  PersonalDataManager* pdm = GetPersonalDataManager(profile);
286  pdm->AddObserver(&observer);
287  pdm->SetProfiles(autofill_profiles);
288  base::MessageLoop::current()->Run();
289  pdm->RemoveObserver(&observer);
290}
291
292void SetCreditCards(int profile, std::vector<CreditCard>* credit_cards) {
293  MockPersonalDataManagerObserver observer;
294  EXPECT_CALL(observer, OnPersonalDataChanged()).
295      WillOnce(QuitUIMessageLoop());
296  PersonalDataManager* pdm = GetPersonalDataManager(profile);
297  pdm->AddObserver(&observer);
298  pdm->SetCreditCards(credit_cards);
299  base::MessageLoop::current()->Run();
300  pdm->RemoveObserver(&observer);
301}
302
303void AddProfile(int profile, const AutofillProfile& autofill_profile) {
304  const std::vector<AutofillProfile*>& all_profiles = GetAllProfiles(profile);
305  std::vector<AutofillProfile> autofill_profiles;
306  for (size_t i = 0; i < all_profiles.size(); ++i)
307    autofill_profiles.push_back(*all_profiles[i]);
308  autofill_profiles.push_back(autofill_profile);
309  autofill_helper::SetProfiles(profile, &autofill_profiles);
310}
311
312void RemoveProfile(int profile, const std::string& guid) {
313  const std::vector<AutofillProfile*>& all_profiles = GetAllProfiles(profile);
314  std::vector<AutofillProfile> autofill_profiles;
315  for (size_t i = 0; i < all_profiles.size(); ++i) {
316    if (all_profiles[i]->guid() != guid)
317      autofill_profiles.push_back(*all_profiles[i]);
318  }
319  autofill_helper::SetProfiles(profile, &autofill_profiles);
320}
321
322void UpdateProfile(int profile,
323                   const std::string& guid,
324                   const AutofillType& type,
325                   const base::string16& value) {
326  const std::vector<AutofillProfile*>& all_profiles = GetAllProfiles(profile);
327  std::vector<AutofillProfile> profiles;
328  for (size_t i = 0; i < all_profiles.size(); ++i) {
329    profiles.push_back(*all_profiles[i]);
330    if (all_profiles[i]->guid() == guid)
331      profiles.back().SetRawInfo(type.GetStorableType(), value);
332  }
333  autofill_helper::SetProfiles(profile, &profiles);
334}
335
336const std::vector<AutofillProfile*>& GetAllProfiles(
337    int profile) {
338  MockPersonalDataManagerObserver observer;
339  EXPECT_CALL(observer, OnPersonalDataChanged()).
340      WillOnce(QuitUIMessageLoop());
341  PersonalDataManager* pdm = GetPersonalDataManager(profile);
342  pdm->AddObserver(&observer);
343  pdm->Refresh();
344  base::MessageLoop::current()->Run();
345  pdm->RemoveObserver(&observer);
346  return pdm->web_profiles();
347}
348
349int GetProfileCount(int profile) {
350  return GetAllProfiles(profile).size();
351}
352
353int GetKeyCount(int profile) {
354  return GetAllKeys(profile).size();
355}
356
357namespace {
358
359bool ProfilesMatchImpl(
360    int profile_a,
361    const std::vector<AutofillProfile*>& autofill_profiles_a,
362    int profile_b,
363    const std::vector<AutofillProfile*>& autofill_profiles_b) {
364  std::map<std::string, AutofillProfile> autofill_profiles_a_map;
365  for (size_t i = 0; i < autofill_profiles_a.size(); ++i) {
366    const AutofillProfile* p = autofill_profiles_a[i];
367    autofill_profiles_a_map[p->guid()] = *p;
368  }
369
370  for (size_t i = 0; i < autofill_profiles_b.size(); ++i) {
371    const AutofillProfile* p = autofill_profiles_b[i];
372    if (!autofill_profiles_a_map.count(p->guid())) {
373      DVLOG(1) << "GUID " << p->guid() << " not found in profile " << profile_b
374               << ".";
375      return false;
376    }
377    AutofillProfile* expected_profile = &autofill_profiles_a_map[p->guid()];
378    expected_profile->set_guid(p->guid());
379    if (*expected_profile != *p) {
380      DVLOG(1) << "Mismatch in profile with GUID " << p->guid() << ".";
381      return false;
382    }
383    autofill_profiles_a_map.erase(p->guid());
384  }
385
386  if (autofill_profiles_a_map.size()) {
387    DVLOG(1) << "Entries present in Profile " << profile_a << " but not in "
388             << profile_b << ".";
389    return false;
390  }
391  return true;
392}
393
394}  // namespace
395
396bool ProfilesMatch(int profile_a, int profile_b) {
397  const std::vector<AutofillProfile*>& autofill_profiles_a =
398      GetAllProfiles(profile_a);
399  const std::vector<AutofillProfile*>& autofill_profiles_b =
400      GetAllProfiles(profile_b);
401  return ProfilesMatchImpl(
402      profile_a, autofill_profiles_a, profile_b, autofill_profiles_b);
403}
404
405bool AllProfilesMatch() {
406  for (int i = 1; i < test()->num_clients(); ++i) {
407    if (!ProfilesMatch(0, i)) {
408      DVLOG(1) << "Profile " << i << "does not contain the same autofill "
409                                     "profiles as profile 0.";
410      return false;
411    }
412  }
413  return true;
414}
415
416namespace {
417
418class ProfilesMatchStatusChecker : public StatusChangeChecker,
419                                   public PersonalDataManagerObserver {
420 public:
421  ProfilesMatchStatusChecker(int profile_a, int profile_b);
422  virtual ~ProfilesMatchStatusChecker();
423
424  // StatusChangeChecker implementation.
425  virtual bool IsExitConditionSatisfied() OVERRIDE;
426  virtual std::string GetDebugMessage() const OVERRIDE;
427
428  // PersonalDataManager implementation.
429  virtual void OnPersonalDataChanged() OVERRIDE;
430
431  // Wait for conidtion to beome true.
432  void Wait();
433
434 private:
435  const int profile_a_;
436  const int profile_b_;
437  bool registered_;
438};
439
440ProfilesMatchStatusChecker::ProfilesMatchStatusChecker(int profile_a,
441                                                       int profile_b)
442    : profile_a_(profile_a), profile_b_(profile_b), registered_(false) {
443}
444
445ProfilesMatchStatusChecker::~ProfilesMatchStatusChecker() {
446  PersonalDataManager* pdm_a = GetPersonalDataManager(profile_a_);
447  PersonalDataManager* pdm_b = GetPersonalDataManager(profile_b_);
448  if (registered_) {
449    pdm_a->RemoveObserver(this);
450    pdm_b->RemoveObserver(this);
451  }
452}
453
454bool ProfilesMatchStatusChecker::IsExitConditionSatisfied() {
455  PersonalDataManager* pdm_a = GetPersonalDataManager(profile_a_);
456  PersonalDataManager* pdm_b = GetPersonalDataManager(profile_b_);
457
458  const std::vector<AutofillProfile*>& autofill_profiles_a =
459      pdm_a->web_profiles();
460  const std::vector<AutofillProfile*>& autofill_profiles_b =
461      pdm_b->web_profiles();
462
463  return ProfilesMatchImpl(
464      profile_a_, autofill_profiles_a, profile_b_, autofill_profiles_b);
465}
466
467void ProfilesMatchStatusChecker::Wait() {
468  PersonalDataManager* pdm_a = GetPersonalDataManager(profile_a_);
469  PersonalDataManager* pdm_b = GetPersonalDataManager(profile_b_);
470
471  pdm_a->AddObserver(this);
472  pdm_b->AddObserver(this);
473
474  pdm_a->Refresh();
475  pdm_b->Refresh();
476
477  registered_ = true;
478
479  StartBlockingWait();
480}
481
482std::string ProfilesMatchStatusChecker::GetDebugMessage() const {
483  return "Waiting for matching autofill profiles";
484}
485
486void ProfilesMatchStatusChecker::OnPersonalDataChanged() {
487  CheckExitCondition();
488}
489
490}  // namespace
491
492bool AwaitProfilesMatch(int a, int b) {
493  ProfilesMatchStatusChecker checker(a, b);
494  checker.Wait();
495  return !checker.TimedOut();
496}
497
498}  // namespace autofill_helper
499