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