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