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
27 using autofill::AutofillChangeList;
28 using autofill::AutofillEntry;
29 using autofill::AutofillKey;
30 using autofill::AutofillProfile;
31 using autofill::AutofillTable;
32 using autofill::AutofillType;
33 using autofill::AutofillWebDataService;
34 using autofill::AutofillWebDataServiceObserverOnDBThread;
35 using autofill::CreditCard;
36 using autofill::FormFieldData;
37 using autofill::PersonalDataManager;
38 using autofill::PersonalDataManagerObserver;
39 using base::WaitableEvent;
40 using content::BrowserThread;
41 using sync_datatype_helper::test;
42 using testing::_;
43
44 namespace {
45
ACTION_P(SignalEvent,event)46 ACTION_P(SignalEvent, event) {
47 event->Signal();
48 }
49
50 class MockWebDataServiceObserver
51 : public AutofillWebDataServiceObserverOnDBThread {
52 public:
53 MOCK_METHOD1(AutofillEntriesChanged,
54 void(const AutofillChangeList& changes));
55 };
56
57 class MockPersonalDataManagerObserver : public PersonalDataManagerObserver {
58 public:
59 MOCK_METHOD0(OnPersonalDataChanged, void());
60 };
61
RunOnDBThreadAndSignal(base::Closure task,base::WaitableEvent * done_event)62 void RunOnDBThreadAndSignal(base::Closure task,
63 base::WaitableEvent* done_event) {
64 if (!task.is_null()) {
65 task.Run();
66 }
67 done_event->Signal();
68 }
69
RunOnDBThreadAndBlock(base::Closure task)70 void 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
RemoveKeyDontBlockForSync(int profile,const AutofillKey & key)78 void 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
GetAllAutofillEntriesOnDBThread(AutofillWebDataService * wds,std::vector<AutofillEntry> * entries)102 void GetAllAutofillEntriesOnDBThread(AutofillWebDataService* wds,
103 std::vector<AutofillEntry>* entries) {
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
105 AutofillTable::FromWebDatabase(
106 wds->GetDatabase())->GetAllAutofillEntries(entries);
107 }
108
GetAllAutofillEntries(AutofillWebDataService * wds)109 std::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.
BlockForPendingDBThreadTasks()121 void 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
131 namespace autofill_helper {
132
CreateAutofillProfile(ProfileType type)133 AutofillProfile 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
GetWebDataService(int index)168 scoped_refptr<AutofillWebDataService> GetWebDataService(int index) {
169 return WebDataServiceFactory::GetAutofillWebDataForProfile(
170 test()->GetProfile(index), Profile::EXPLICIT_ACCESS);
171 }
172
GetPersonalDataManager(int index)173 PersonalDataManager* GetPersonalDataManager(int index) {
174 return autofill::PersonalDataManagerFactory::GetForProfile(
175 test()->GetProfile(index));
176 }
177
AddKeys(int profile,const std::set<AutofillKey> & keys)178 void 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
RemoveKey(int profile,const AutofillKey & key)211 void RemoveKey(int profile, const AutofillKey& key) {
212 RemoveKeyDontBlockForSync(profile, key);
213 BlockForPendingDBThreadTasks();
214 }
215
RemoveKeys(int profile)216 void 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
GetAllKeys(int profile)225 std::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
KeysMatch(int profile_a,int profile_b)236 bool KeysMatch(int profile_a, int profile_b) {
237 return GetAllKeys(profile_a) == GetAllKeys(profile_b);
238 }
239
240 namespace {
241
242 class 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
KeysMatchStatusChecker(int profile_a,int profile_b)255 KeysMatchStatusChecker::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
~KeysMatchStatusChecker()262 KeysMatchStatusChecker::~KeysMatchStatusChecker() {
263 }
264
IsExitConditionSatisfied()265 bool KeysMatchStatusChecker::IsExitConditionSatisfied() {
266 return KeysMatch(profile_a_, profile_b_);
267 }
268
GetDebugMessage() const269 std::string KeysMatchStatusChecker::GetDebugMessage() const {
270 return "Waiting for matching autofill keys";
271 }
272
273 } // namespace
274
AwaitKeysMatch(int a,int b)275 bool AwaitKeysMatch(int a, int b) {
276 KeysMatchStatusChecker checker(a, b);
277 checker.Wait();
278 return !checker.TimedOut();
279 }
280
SetProfiles(int profile,std::vector<AutofillProfile> * autofill_profiles)281 void 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
SetCreditCards(int profile,std::vector<CreditCard> * credit_cards)292 void 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
AddProfile(int profile,const AutofillProfile & autofill_profile)303 void 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
RemoveProfile(int profile,const std::string & guid)312 void 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
UpdateProfile(int profile,const std::string & guid,const AutofillType & type,const base::string16 & value)322 void 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
GetAllProfiles(int profile)336 const 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
GetProfileCount(int profile)349 int GetProfileCount(int profile) {
350 return GetAllProfiles(profile).size();
351 }
352
GetKeyCount(int profile)353 int GetKeyCount(int profile) {
354 return GetAllKeys(profile).size();
355 }
356
357 namespace {
358
ProfilesMatchImpl(int profile_a,const std::vector<AutofillProfile * > & autofill_profiles_a,int profile_b,const std::vector<AutofillProfile * > & autofill_profiles_b)359 bool 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
ProfilesMatch(int profile_a,int profile_b)396 bool 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
AllProfilesMatch()405 bool 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
416 namespace {
417
418 class 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
ProfilesMatchStatusChecker(int profile_a,int profile_b)440 ProfilesMatchStatusChecker::ProfilesMatchStatusChecker(int profile_a,
441 int profile_b)
442 : profile_a_(profile_a), profile_b_(profile_b), registered_(false) {
443 }
444
~ProfilesMatchStatusChecker()445 ProfilesMatchStatusChecker::~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
IsExitConditionSatisfied()454 bool 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
Wait()467 void 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
GetDebugMessage() const482 std::string ProfilesMatchStatusChecker::GetDebugMessage() const {
483 return "Waiting for matching autofill profiles";
484 }
485
OnPersonalDataChanged()486 void ProfilesMatchStatusChecker::OnPersonalDataChanged() {
487 CheckExitCondition();
488 }
489
490 } // namespace
491
AwaitProfilesMatch(int a,int b)492 bool AwaitProfilesMatch(int a, int b) {
493 ProfilesMatchStatusChecker checker(a, b);
494 checker.Wait();
495 return !checker.TimedOut();
496 }
497
498 } // namespace autofill_helper
499