• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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