Home | History | Annotate | Download | only in integration
      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 
     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 
     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 
     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 
     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 
    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 
    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.
    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 
    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 (at) 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 (at) 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 
    168 scoped_refptr<AutofillWebDataService> GetWebDataService(int index) {
    169   return WebDataServiceFactory::GetAutofillWebDataForProfile(
    170       test()->GetProfile(index), Profile::EXPLICIT_ACCESS);
    171 }
    172 
    173 PersonalDataManager* GetPersonalDataManager(int index) {
    174   return autofill::PersonalDataManagerFactory::GetForProfile(
    175       test()->GetProfile(index));
    176 }
    177 
    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 
    211 void RemoveKey(int profile, const AutofillKey& key) {
    212   RemoveKeyDontBlockForSync(profile, key);
    213   BlockForPendingDBThreadTasks();
    214 }
    215 
    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 
    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 
    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 
    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 
    262 KeysMatchStatusChecker::~KeysMatchStatusChecker() {
    263 }
    264 
    265 bool KeysMatchStatusChecker::IsExitConditionSatisfied() {
    266   return KeysMatch(profile_a_, profile_b_);
    267 }
    268 
    269 std::string KeysMatchStatusChecker::GetDebugMessage() const {
    270   return "Waiting for matching autofill keys";
    271 }
    272 
    273 }  // namespace
    274 
    275 bool AwaitKeysMatch(int a, int b) {
    276   KeysMatchStatusChecker checker(a, b);
    277   checker.Wait();
    278   return !checker.TimedOut();
    279 }
    280 
    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 
    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 
    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 
    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 
    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 
    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 
    349 int GetProfileCount(int profile) {
    350   return GetAllProfiles(profile).size();
    351 }
    352 
    353 int GetKeyCount(int profile) {
    354   return GetAllKeys(profile).size();
    355 }
    356 
    357 namespace {
    358 
    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 
    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 
    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 
    440 ProfilesMatchStatusChecker::ProfilesMatchStatusChecker(int profile_a,
    441                                                        int profile_b)
    442     : profile_a_(profile_a), profile_b_(profile_b), registered_(false) {
    443 }
    444 
    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 
    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 
    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 
    482 std::string ProfilesMatchStatusChecker::GetDebugMessage() const {
    483   return "Waiting for matching autofill profiles";
    484 }
    485 
    486 void ProfilesMatchStatusChecker::OnPersonalDataChanged() {
    487   CheckExitCondition();
    488 }
    489 
    490 }  // namespace
    491 
    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