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/sync_datatype_helper.h"
     13 #include "chrome/browser/sync/test/integration/sync_test.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 
     25 using autofill::AutofillChangeList;
     26 using autofill::AutofillEntry;
     27 using autofill::AutofillKey;
     28 using autofill::AutofillProfile;
     29 using autofill::AutofillTable;
     30 using autofill::AutofillType;
     31 using autofill::AutofillWebDataService;
     32 using autofill::AutofillWebDataServiceObserverOnDBThread;
     33 using autofill::CreditCard;
     34 using autofill::FormFieldData;
     35 using autofill::PersonalDataManager;
     36 using autofill::PersonalDataManagerObserver;
     37 using base::WaitableEvent;
     38 using content::BrowserThread;
     39 using sync_datatype_helper::test;
     40 using testing::_;
     41 
     42 namespace {
     43 
     44 ACTION_P(SignalEvent, event) {
     45   event->Signal();
     46 }
     47 
     48 class MockWebDataServiceObserver
     49     : public AutofillWebDataServiceObserverOnDBThread {
     50  public:
     51   MOCK_METHOD1(AutofillEntriesChanged,
     52                void(const AutofillChangeList& changes));
     53 };
     54 
     55 class MockPersonalDataManagerObserver : public PersonalDataManagerObserver {
     56  public:
     57   MOCK_METHOD0(OnPersonalDataChanged, void());
     58 };
     59 
     60 void RunOnDBThreadAndSignal(base::Closure task,
     61                             base::WaitableEvent* done_event) {
     62   if (!task.is_null()) {
     63     task.Run();
     64   }
     65   done_event->Signal();
     66 }
     67 
     68 void 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 
     76 void 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 
    100 void GetAllAutofillEntriesOnDBThread(AutofillWebDataService* wds,
    101                                      std::vector<AutofillEntry>* entries) {
    102   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
    103   AutofillTable::FromWebDatabase(
    104       wds->GetDatabase())->GetAllAutofillEntries(entries);
    105 }
    106 
    107 std::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.
    119 void 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 
    129 namespace autofill_helper {
    130 
    131 AutofillProfile 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 (at) 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 (at) 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 
    166 scoped_refptr<AutofillWebDataService> GetWebDataService(int index) {
    167   return AutofillWebDataService::FromBrowserContext(test()->GetProfile(index));
    168 }
    169 
    170 PersonalDataManager* GetPersonalDataManager(int index) {
    171   return autofill::PersonalDataManagerFactory::GetForProfile(
    172       test()->GetProfile(index));
    173 }
    174 
    175 void 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 
    208 void RemoveKey(int profile, const AutofillKey& key) {
    209   RemoveKeyDontBlockForSync(profile, key);
    210   BlockForPendingDBThreadTasks();
    211 }
    212 
    213 void 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 
    222 std::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 
    233 bool KeysMatch(int profile_a, int profile_b) {
    234   return GetAllKeys(profile_a) == GetAllKeys(profile_b);
    235 }
    236 
    237 void 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 
    248 void 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 
    259 void 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 
    268 void 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 
    278 void 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.GetStorableType(), value);
    288   }
    289   autofill_helper::SetProfiles(profile, &profiles);
    290 }
    291 
    292 const 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 
    305 int GetProfileCount(int profile) {
    306   return GetAllProfiles(profile).size();
    307 }
    308 
    309 int GetKeyCount(int profile) {
    310   return GetAllKeys(profile).size();
    311 }
    312 
    313 bool 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 
    348 bool 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