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