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