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