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.
5 #include "chrome/browser/sync/test/integration/autofill_helper.h"
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"
26 using autofill::AutofillChangeList
;
27 using autofill::AutofillEntry
;
28 using autofill::AutofillKey
;
29 using autofill::AutofillProfile
;
30 using autofill::AutofillTable
;
31 using autofill::AutofillType
;
32 using autofill::AutofillWebDataService
;
33 using autofill::AutofillWebDataServiceObserverOnDBThread
;
34 using autofill::CreditCard
;
35 using autofill::FormFieldData
;
36 using autofill::PersonalDataManager
;
37 using autofill::PersonalDataManagerObserver
;
38 using base::WaitableEvent
;
39 using content::BrowserThread
;
40 using sync_datatype_helper::test
;
45 ACTION_P(SignalEvent
, event
) {
49 class MockWebDataServiceObserver
50 : public AutofillWebDataServiceObserverOnDBThread
{
52 MOCK_METHOD1(AutofillEntriesChanged
,
53 void(const AutofillChangeList
& changes
));
56 class MockPersonalDataManagerObserver
: public PersonalDataManagerObserver
{
58 MOCK_METHOD0(OnPersonalDataChanged
, void());
61 void RunOnDBThreadAndSignal(base::Closure task
,
62 base::WaitableEvent
* done_event
) {
63 if (!task
.is_null()) {
69 void RunOnDBThreadAndBlock(base::Closure task
) {
70 WaitableEvent
done_event(false, false);
71 BrowserThread::PostTask(BrowserThread::DB
,
73 Bind(&RunOnDBThreadAndSignal
, task
, &done_event
));
77 void RemoveKeyDontBlockForSync(int profile
, const AutofillKey
& key
) {
78 WaitableEvent
done_event(false, false);
80 MockWebDataServiceObserver mock_observer
;
81 EXPECT_CALL(mock_observer
, AutofillEntriesChanged(_
))
82 .WillOnce(SignalEvent(&done_event
));
84 scoped_refptr
<AutofillWebDataService
> wds
=
85 autofill_helper::GetWebDataService(profile
);
87 void(AutofillWebDataService::*add_observer_func
)(
88 AutofillWebDataServiceObserverOnDBThread
*) =
89 &AutofillWebDataService::AddObserver
;
90 RunOnDBThreadAndBlock(Bind(add_observer_func
, wds
, &mock_observer
));
92 wds
->RemoveFormValueForElementName(key
.name(), key
.value());
95 void(AutofillWebDataService::*remove_observer_func
)(
96 AutofillWebDataServiceObserverOnDBThread
*) =
97 &AutofillWebDataService::RemoveObserver
;
98 RunOnDBThreadAndBlock(Bind(remove_observer_func
, wds
, &mock_observer
));
101 void GetAllAutofillEntriesOnDBThread(AutofillWebDataService
* wds
,
102 std::vector
<AutofillEntry
>* entries
) {
103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB
));
104 AutofillTable::FromWebDatabase(
105 wds
->GetDatabase())->GetAllAutofillEntries(entries
);
108 std::vector
<AutofillEntry
> GetAllAutofillEntries(AutofillWebDataService
* wds
) {
109 std::vector
<AutofillEntry
> entries
;
110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
111 RunOnDBThreadAndBlock(Bind(&GetAllAutofillEntriesOnDBThread
,
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.
120 void 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
125 RunOnDBThreadAndBlock(base::Closure());
130 namespace autofill_helper
{
132 AutofillProfile
CreateAutofillProfile(ProfileType type
) {
133 AutofillProfile profile
;
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");
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");
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");
159 autofill::test::SetProfileInfoWithGuid(&profile
,
160 "FE461507-7E13-4198-8E66-74C7DB6D8322",
161 "", "", "", "", "", "", "", "", "", "", "", "");
167 scoped_refptr
<AutofillWebDataService
> GetWebDataService(int index
) {
168 return WebDataServiceFactory::GetAutofillWebDataForProfile(
169 test()->GetProfile(index
), Profile::EXPLICIT_ACCESS
);
172 PersonalDataManager
* GetPersonalDataManager(int index
) {
173 return autofill::PersonalDataManagerFactory::GetForProfile(
174 test()->GetProfile(index
));
177 void AddKeys(int profile
, const std::set
<AutofillKey
>& keys
) {
178 std::vector
<FormFieldData
> form_fields
;
179 for (std::set
<AutofillKey
>::const_iterator i
= keys
.begin();
183 field
.name
= i
->name();
184 field
.value
= i
->value();
185 form_fields
.push_back(field
);
188 WaitableEvent
done_event(false, false);
189 MockWebDataServiceObserver mock_observer
;
190 EXPECT_CALL(mock_observer
, AutofillEntriesChanged(_
))
191 .WillOnce(SignalEvent(&done_event
));
193 scoped_refptr
<AutofillWebDataService
> wds
= GetWebDataService(profile
);
195 void(AutofillWebDataService::*add_observer_func
)(
196 AutofillWebDataServiceObserverOnDBThread
*) =
197 &AutofillWebDataService::AddObserver
;
198 RunOnDBThreadAndBlock(Bind(add_observer_func
, wds
, &mock_observer
));
200 wds
->AddFormFields(form_fields
);
202 BlockForPendingDBThreadTasks();
204 void(AutofillWebDataService::*remove_observer_func
)(
205 AutofillWebDataServiceObserverOnDBThread
*) =
206 &AutofillWebDataService::RemoveObserver
;
207 RunOnDBThreadAndBlock(Bind(remove_observer_func
, wds
, &mock_observer
));
210 void RemoveKey(int profile
, const AutofillKey
& key
) {
211 RemoveKeyDontBlockForSync(profile
, key
);
212 BlockForPendingDBThreadTasks();
215 void 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());
221 BlockForPendingDBThreadTasks();
224 std::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
);
235 bool KeysMatch(int profile_a
, int profile_b
) {
236 return GetAllKeys(profile_a
) == GetAllKeys(profile_b
);
239 void 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
);
250 void 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
);
261 void 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
);
270 void 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
]);
277 autofill_helper::SetProfiles(profile
, &autofill_profiles
);
280 void 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
);
291 autofill_helper::SetProfiles(profile
, &profiles
);
294 const std::vector
<AutofillProfile
*>& GetAllProfiles(
296 MockPersonalDataManagerObserver observer
;
297 EXPECT_CALL(observer
, OnPersonalDataChanged()).
298 WillOnce(QuitUIMessageLoop());
299 PersonalDataManager
* pdm
= GetPersonalDataManager(profile
);
300 pdm
->AddObserver(&observer
);
302 base::MessageLoop::current()->Run();
303 pdm
->RemoveObserver(&observer
);
304 return pdm
->web_profiles();
307 int GetProfileCount(int profile
) {
308 return GetAllProfiles(profile
).size();
311 int GetKeyCount(int profile
) {
312 return GetAllKeys(profile
).size();
315 bool 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
;
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 "
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() << ".";
339 autofill_profiles_a_map
.erase(p
->guid());
342 if (autofill_profiles_a_map
.size()) {
343 LOG(ERROR
) << "Entries present in Profile " << profile_a
344 << " but not in " << profile_b
<< ".";
350 bool 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.";
361 } // namespace autofill_helper