autofill_helper.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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/profiles/profile.h"
9#include "chrome/browser/sync/profile_sync_service.h"
10#include "chrome/browser/sync/profile_sync_test_util.h"
11#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
12#include "chrome/browser/sync/test/integration/sync_test.h"
13#include "chrome/common/chrome_notification_types.h"
14#include "components/autofill/core/browser/autofill_common_test.h"
15#include "components/autofill/core/browser/autofill_profile.h"
16#include "components/autofill/core/browser/autofill_type.h"
17#include "components/autofill/core/browser/personal_data_manager.h"
18#include "components/autofill/core/browser/personal_data_manager_observer.h"
19#include "components/autofill/core/browser/webdata/autofill_entry.h"
20#include "components/autofill/core/browser/webdata/autofill_table.h"
21#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
22#include "components/autofill/core/common/form_field_data.h"
23#include "components/webdata/common/web_database.h"
24
25using autofill::AutofillChangeList;
26using autofill::AutofillEntry;
27using autofill::AutofillKey;
28using autofill::AutofillProfile;
29using autofill::AutofillTable;
30using autofill::AutofillType;
31using autofill::AutofillWebDataService;
32using autofill::AutofillWebDataServiceObserverOnDBThread;
33using autofill::CreditCard;
34using autofill::FormFieldData;
35using autofill::PersonalDataManager;
36using autofill::PersonalDataManagerObserver;
37using base::WaitableEvent;
38using content::BrowserThread;
39using sync_datatype_helper::test;
40using testing::_;
41
42namespace {
43
44ACTION_P(SignalEvent, event) {
45  event->Signal();
46}
47
48class MockWebDataServiceObserver
49    : public AutofillWebDataServiceObserverOnDBThread {
50 public:
51  MOCK_METHOD1(AutofillEntriesChanged,
52               void(const AutofillChangeList& changes));
53};
54
55class MockPersonalDataManagerObserver : public PersonalDataManagerObserver {
56 public:
57  MOCK_METHOD0(OnPersonalDataChanged, void());
58};
59
60void RunOnDBThreadAndSignal(base::Closure task,
61                            base::WaitableEvent* done_event) {
62  if (!task.is_null()) {
63    task.Run();
64  }
65  done_event->Signal();
66}
67
68void RunOnDBThreadAndBlock(base::Closure task) {
69  WaitableEvent done_event(false, false);
70  BrowserThread::PostTask(BrowserThread::DB,
71                          FROM_HERE,
72                          Bind(&RunOnDBThreadAndSignal, task, &done_event));
73  done_event.Wait();
74}
75
76void RemoveKeyDontBlockForSync(int profile, const AutofillKey& key) {
77  WaitableEvent done_event(false, false);
78
79  MockWebDataServiceObserver mock_observer;
80  EXPECT_CALL(mock_observer, AutofillEntriesChanged(_))
81      .WillOnce(SignalEvent(&done_event));
82
83  scoped_refptr<AutofillWebDataService> wds =
84      autofill_helper::GetWebDataService(profile);
85
86  void(AutofillWebDataService::*add_observer_func)(
87      AutofillWebDataServiceObserverOnDBThread*) =
88      &AutofillWebDataService::AddObserver;
89  RunOnDBThreadAndBlock(Bind(add_observer_func, wds, &mock_observer));
90
91  wds->RemoveFormValueForElementName(key.name(), key.value());
92  done_event.Wait();
93
94  void(AutofillWebDataService::*remove_observer_func)(
95      AutofillWebDataServiceObserverOnDBThread*) =
96      &AutofillWebDataService::RemoveObserver;
97  RunOnDBThreadAndBlock(Bind(remove_observer_func, wds, &mock_observer));
98}
99
100void GetAllAutofillEntriesOnDBThread(AutofillWebDataService* wds,
101                                     std::vector<AutofillEntry>* entries) {
102  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
103  AutofillTable::FromWebDatabase(
104      wds->GetDatabase())->GetAllAutofillEntries(entries);
105}
106
107std::vector<AutofillEntry> GetAllAutofillEntries(AutofillWebDataService* wds) {
108  std::vector<AutofillEntry> entries;
109  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
110  RunOnDBThreadAndBlock(Bind(&GetAllAutofillEntriesOnDBThread,
111                             Unretained(wds),
112                             &entries));
113  return entries;
114}
115
116// UI thread returns from the update operations on the DB thread and schedules
117// the sync. This function blocks until after this scheduled sync is complete by
118// scheduling additional empty task on DB Thread. Call after AddKeys/RemoveKey.
119void BlockForPendingDBThreadTasks() {
120  // The order of the notifications is undefined, so sync change sometimes is
121  // posted after the notification for observer_helper. Post new task to db
122  // thread that guaranteed to be after sync and would be blocking until
123  // completion.
124  RunOnDBThreadAndBlock(base::Closure());
125}
126
127}  // namespace
128
129namespace autofill_helper {
130
131AutofillProfile CreateAutofillProfile(ProfileType type) {
132  AutofillProfile profile;
133  switch (type) {
134    case PROFILE_MARION:
135      autofill::test::SetProfileInfoWithGuid(&profile,
136          "C837507A-6C3B-4872-AC14-5113F157D668",
137          "Marion", "Mitchell", "Morrison",
138          "johnwayne@me.xyz", "Fox",
139          "123 Zoo St.", "unit 5", "Hollywood", "CA",
140          "91601", "US", "12345678910");
141      break;
142    case PROFILE_HOMER:
143      autofill::test::SetProfileInfoWithGuid(&profile,
144          "137DE1C3-6A30-4571-AC86-109B1ECFBE7F",
145          "Homer", "J.", "Simpson",
146          "homer@abc.com", "SNPP",
147          "1 Main St", "PO Box 1", "Springfield", "MA",
148          "94101", "US", "14155551212");
149      break;
150    case PROFILE_FRASIER:
151      autofill::test::SetProfileInfoWithGuid(&profile,
152          "9A5E6872-6198-4688-BF75-0016E781BB0A",
153          "Frasier", "Winslow", "Crane",
154          "", "randomness", "", "Apt. 4", "Seattle", "WA",
155          "99121", "US", "0000000000");
156      break;
157    case PROFILE_NULL:
158      autofill::test::SetProfileInfoWithGuid(&profile,
159          "FE461507-7E13-4198-8E66-74C7DB6D8322",
160          "", "", "", "", "", "", "", "", "", "", "", "");
161      break;
162  }
163  return profile;
164}
165
166scoped_refptr<AutofillWebDataService> GetWebDataService(int index) {
167  return AutofillWebDataService::FromBrowserContext(test()->GetProfile(index));
168}
169
170PersonalDataManager* GetPersonalDataManager(int index) {
171  return autofill::PersonalDataManagerFactory::GetForProfile(
172      test()->GetProfile(index));
173}
174
175void AddKeys(int profile, const std::set<AutofillKey>& keys) {
176  std::vector<FormFieldData> form_fields;
177  for (std::set<AutofillKey>::const_iterator i = keys.begin();
178       i != keys.end();
179       ++i) {
180    FormFieldData field;
181    field.name = i->name();
182    field.value = i->value();
183    form_fields.push_back(field);
184  }
185
186  WaitableEvent done_event(false, false);
187  MockWebDataServiceObserver mock_observer;
188  EXPECT_CALL(mock_observer, AutofillEntriesChanged(_))
189      .WillOnce(SignalEvent(&done_event));
190
191  scoped_refptr<AutofillWebDataService> wds = GetWebDataService(profile);
192
193  void(AutofillWebDataService::*add_observer_func)(
194      AutofillWebDataServiceObserverOnDBThread*) =
195      &AutofillWebDataService::AddObserver;
196  RunOnDBThreadAndBlock(Bind(add_observer_func, wds, &mock_observer));
197
198  wds->AddFormFields(form_fields);
199  done_event.Wait();
200  BlockForPendingDBThreadTasks();
201
202  void(AutofillWebDataService::*remove_observer_func)(
203      AutofillWebDataServiceObserverOnDBThread*) =
204      &AutofillWebDataService::RemoveObserver;
205  RunOnDBThreadAndBlock(Bind(remove_observer_func, wds, &mock_observer));
206}
207
208void RemoveKey(int profile, const AutofillKey& key) {
209  RemoveKeyDontBlockForSync(profile, key);
210  BlockForPendingDBThreadTasks();
211}
212
213void RemoveKeys(int profile) {
214  std::set<AutofillEntry> keys = GetAllKeys(profile);
215  for (std::set<AutofillEntry>::const_iterator it = keys.begin();
216       it != keys.end(); ++it) {
217    RemoveKeyDontBlockForSync(profile, it->key());
218  }
219  BlockForPendingDBThreadTasks();
220}
221
222std::set<AutofillEntry> GetAllKeys(int profile) {
223  scoped_refptr<AutofillWebDataService> wds = GetWebDataService(profile);
224  std::vector<AutofillEntry> all_entries = GetAllAutofillEntries(wds.get());
225  std::set<AutofillEntry> all_keys;
226  for (std::vector<AutofillEntry>::const_iterator it = all_entries.begin();
227       it != all_entries.end(); ++it) {
228    all_keys.insert(*it);
229  }
230  return all_keys;
231}
232
233bool KeysMatch(int profile_a, int profile_b) {
234  return GetAllKeys(profile_a) == GetAllKeys(profile_b);
235}
236
237void SetProfiles(int profile, std::vector<AutofillProfile>* autofill_profiles) {
238  MockPersonalDataManagerObserver observer;
239  EXPECT_CALL(observer, OnPersonalDataChanged()).
240      WillOnce(QuitUIMessageLoop());
241  PersonalDataManager* pdm = GetPersonalDataManager(profile);
242  pdm->AddObserver(&observer);
243  pdm->SetProfiles(autofill_profiles);
244  base::MessageLoop::current()->Run();
245  pdm->RemoveObserver(&observer);
246}
247
248void SetCreditCards(int profile, std::vector<CreditCard>* credit_cards) {
249  MockPersonalDataManagerObserver observer;
250  EXPECT_CALL(observer, OnPersonalDataChanged()).
251      WillOnce(QuitUIMessageLoop());
252  PersonalDataManager* pdm = GetPersonalDataManager(profile);
253  pdm->AddObserver(&observer);
254  pdm->SetCreditCards(credit_cards);
255  base::MessageLoop::current()->Run();
256  pdm->RemoveObserver(&observer);
257}
258
259void AddProfile(int profile, const AutofillProfile& autofill_profile) {
260  const std::vector<AutofillProfile*>& all_profiles = GetAllProfiles(profile);
261  std::vector<AutofillProfile> autofill_profiles;
262  for (size_t i = 0; i < all_profiles.size(); ++i)
263    autofill_profiles.push_back(*all_profiles[i]);
264  autofill_profiles.push_back(autofill_profile);
265  autofill_helper::SetProfiles(profile, &autofill_profiles);
266}
267
268void RemoveProfile(int profile, const std::string& guid) {
269  const std::vector<AutofillProfile*>& all_profiles = GetAllProfiles(profile);
270  std::vector<AutofillProfile> autofill_profiles;
271  for (size_t i = 0; i < all_profiles.size(); ++i) {
272    if (all_profiles[i]->guid() != guid)
273      autofill_profiles.push_back(*all_profiles[i]);
274  }
275  autofill_helper::SetProfiles(profile, &autofill_profiles);
276}
277
278void UpdateProfile(int profile,
279                   const std::string& guid,
280                   const AutofillType& type,
281                   const string16& value) {
282  const std::vector<AutofillProfile*>& all_profiles = GetAllProfiles(profile);
283  std::vector<AutofillProfile> profiles;
284  for (size_t i = 0; i < all_profiles.size(); ++i) {
285    profiles.push_back(*all_profiles[i]);
286    if (all_profiles[i]->guid() == guid)
287      profiles.back().SetRawInfo(type.field_type(), value);
288  }
289  autofill_helper::SetProfiles(profile, &profiles);
290}
291
292const std::vector<AutofillProfile*>& GetAllProfiles(
293    int profile) {
294  MockPersonalDataManagerObserver observer;
295  EXPECT_CALL(observer, OnPersonalDataChanged()).
296      WillOnce(QuitUIMessageLoop());
297  PersonalDataManager* pdm = GetPersonalDataManager(profile);
298  pdm->AddObserver(&observer);
299  pdm->Refresh();
300  base::MessageLoop::current()->Run();
301  pdm->RemoveObserver(&observer);
302  return pdm->web_profiles();
303}
304
305int GetProfileCount(int profile) {
306  return GetAllProfiles(profile).size();
307}
308
309int GetKeyCount(int profile) {
310  return GetAllKeys(profile).size();
311}
312
313bool ProfilesMatch(int profile_a, int profile_b) {
314  const std::vector<AutofillProfile*>& autofill_profiles_a =
315      GetAllProfiles(profile_a);
316  std::map<std::string, AutofillProfile> autofill_profiles_a_map;
317  for (size_t i = 0; i < autofill_profiles_a.size(); ++i) {
318    const AutofillProfile* p = autofill_profiles_a[i];
319    autofill_profiles_a_map[p->guid()] = *p;
320  }
321
322  const std::vector<AutofillProfile*>& autofill_profiles_b =
323      GetAllProfiles(profile_b);
324  for (size_t i = 0; i < autofill_profiles_b.size(); ++i) {
325    const AutofillProfile* p = autofill_profiles_b[i];
326    if (!autofill_profiles_a_map.count(p->guid())) {
327      LOG(ERROR) << "GUID " << p->guid() << " not found in profile "
328                 << profile_b << ".";
329      return false;
330    }
331    AutofillProfile* expected_profile = &autofill_profiles_a_map[p->guid()];
332    expected_profile->set_guid(p->guid());
333    if (*expected_profile != *p) {
334      LOG(ERROR) << "Mismatch in profile with GUID " << p->guid() << ".";
335      return false;
336    }
337    autofill_profiles_a_map.erase(p->guid());
338  }
339
340  if (autofill_profiles_a_map.size()) {
341    LOG(ERROR) << "Entries present in Profile " << profile_a
342               << " but not in " << profile_b << ".";
343    return false;
344  }
345  return true;
346}
347
348bool AllProfilesMatch() {
349  for (int i = 1; i < test()->num_clients(); ++i) {
350    if (!ProfilesMatch(0, i)) {
351      LOG(ERROR) << "Profile " << i << "does not contain the same autofill "
352                                       "profiles as profile 0.";
353      return false;
354    }
355  }
356  return true;
357}
358
359}  // namespace autofill_helper
360