1 // Copyright 2013 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 <string>
6 #include <vector>
7
8 #include "base/basictypes.h"
9 #include "base/bind.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/synchronization/waitable_event.h"
20 #include "base/threading/thread.h"
21 #include "base/time/time.h"
22 #include "components/autofill/core/browser/autofill_country.h"
23 #include "components/autofill/core/browser/autofill_profile.h"
24 #include "components/autofill/core/browser/credit_card.h"
25 #include "components/autofill/core/browser/webdata/autofill_change.h"
26 #include "components/autofill/core/browser/webdata/autofill_entry.h"
27 #include "components/autofill/core/browser/webdata/autofill_table.h"
28 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
29 #include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
30 #include "components/autofill/core/common/form_field_data.h"
31 #include "components/webdata/common/web_data_results.h"
32 #include "components/webdata/common/web_data_service_base.h"
33 #include "components/webdata/common/web_data_service_consumer.h"
34 #include "components/webdata/common/web_database_service.h"
35 #include "testing/gmock/include/gmock/gmock.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37
38 using base::ASCIIToUTF16;
39 using base::Time;
40 using base::TimeDelta;
41 using base::WaitableEvent;
42 using testing::_;
43 using testing::DoDefault;
44 using testing::ElementsAreArray;
45 using testing::Pointee;
46 using testing::Property;
47
48 namespace {
49
50 template <class T>
51 class AutofillWebDataServiceConsumer: public WebDataServiceConsumer {
52 public:
AutofillWebDataServiceConsumer()53 AutofillWebDataServiceConsumer() : handle_(0) {}
~AutofillWebDataServiceConsumer()54 virtual ~AutofillWebDataServiceConsumer() {}
55
OnWebDataServiceRequestDone(WebDataServiceBase::Handle handle,const WDTypedResult * result)56 virtual void OnWebDataServiceRequestDone(WebDataServiceBase::Handle handle,
57 const WDTypedResult* result) {
58 handle_ = handle;
59 const WDResult<T>* wrapped_result =
60 static_cast<const WDResult<T>*>(result);
61 result_ = wrapped_result->GetValue();
62
63 base::MessageLoop::current()->Quit();
64 }
65
handle()66 WebDataServiceBase::Handle handle() { return handle_; }
result()67 T& result() { return result_; }
68
69 private:
70 WebDataServiceBase::Handle handle_;
71 T result_;
72 DISALLOW_COPY_AND_ASSIGN(AutofillWebDataServiceConsumer);
73 };
74
75 } // namespace
76
77 namespace autofill {
78
79 static const int kWebDataServiceTimeoutSeconds = 8;
80
ACTION_P(SignalEvent,event)81 ACTION_P(SignalEvent, event) {
82 event->Signal();
83 }
84
85 class MockAutofillWebDataServiceObserver
86 : public AutofillWebDataServiceObserverOnDBThread {
87 public:
88 MOCK_METHOD1(AutofillEntriesChanged,
89 void(const AutofillChangeList& changes));
90 MOCK_METHOD1(AutofillProfileChanged,
91 void(const AutofillProfileChange& change));
92 };
93
94 class WebDataServiceTest : public testing::Test {
95 public:
WebDataServiceTest()96 WebDataServiceTest() : db_thread_("DBThread") {}
97
98 protected:
SetUp()99 virtual void SetUp() {
100 db_thread_.Start();
101
102 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
103 base::FilePath path = temp_dir_.path().AppendASCII("TestWebDB");
104
105 wdbs_ = new WebDatabaseService(path,
106 base::MessageLoopProxy::current(),
107 db_thread_.message_loop_proxy());
108 wdbs_->AddTable(scoped_ptr<WebDatabaseTable>(new AutofillTable("en-US")));
109 wdbs_->LoadDatabase();
110
111 wds_ =
112 new AutofillWebDataService(wdbs_,
113 base::MessageLoopProxy::current(),
114 db_thread_.message_loop_proxy(),
115 WebDataServiceBase::ProfileErrorCallback());
116 wds_->Init();
117 }
118
TearDown()119 virtual void TearDown() {
120 wds_->ShutdownOnUIThread();
121 wdbs_->ShutdownDatabase();
122 wds_ = NULL;
123 wdbs_ = NULL;
124 WaitForDatabaseThread();
125
126 base::MessageLoop::current()->PostTask(FROM_HERE,
127 base::MessageLoop::QuitClosure());
128 base::MessageLoop::current()->Run();
129 db_thread_.Stop();
130 }
131
WaitForDatabaseThread()132 void WaitForDatabaseThread() {
133 base::WaitableEvent done(false, false);
134 db_thread_.message_loop()->PostTask(
135 FROM_HERE,
136 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
137 done.Wait();
138 }
139
140 base::MessageLoopForUI message_loop_;
141 base::Thread db_thread_;
142 base::FilePath profile_dir_;
143 scoped_refptr<AutofillWebDataService> wds_;
144 scoped_refptr<WebDatabaseService> wdbs_;
145 base::ScopedTempDir temp_dir_;
146 };
147
148 class WebDataServiceAutofillTest : public WebDataServiceTest {
149 public:
WebDataServiceAutofillTest()150 WebDataServiceAutofillTest()
151 : WebDataServiceTest(),
152 unique_id1_(1),
153 unique_id2_(2),
154 test_timeout_(TimeDelta::FromSeconds(kWebDataServiceTimeoutSeconds)),
155 done_event_(false, false) {}
156
157 protected:
SetUp()158 virtual void SetUp() {
159 WebDataServiceTest::SetUp();
160 name1_ = ASCIIToUTF16("name1");
161 name2_ = ASCIIToUTF16("name2");
162 value1_ = ASCIIToUTF16("value1");
163 value2_ = ASCIIToUTF16("value2");
164
165 void(AutofillWebDataService::*add_observer_func)(
166 AutofillWebDataServiceObserverOnDBThread*) =
167 &AutofillWebDataService::AddObserver;
168 db_thread_.message_loop()->PostTask(
169 FROM_HERE, base::Bind(add_observer_func, wds_, &observer_));
170 WaitForDatabaseThread();
171 }
172
TearDown()173 virtual void TearDown() {
174 void(AutofillWebDataService::*remove_observer_func)(
175 AutofillWebDataServiceObserverOnDBThread*) =
176 &AutofillWebDataService::RemoveObserver;
177 db_thread_.message_loop()->PostTask(
178 FROM_HERE, base::Bind(remove_observer_func, wds_, &observer_));
179 WaitForDatabaseThread();
180
181 WebDataServiceTest::TearDown();
182 }
183
AppendFormField(const base::string16 & name,const base::string16 & value,std::vector<FormFieldData> * form_fields)184 void AppendFormField(const base::string16& name,
185 const base::string16& value,
186 std::vector<FormFieldData>* form_fields) {
187 FormFieldData field;
188 field.name = name;
189 field.value = value;
190 form_fields->push_back(field);
191 }
192
193 base::string16 name1_;
194 base::string16 name2_;
195 base::string16 value1_;
196 base::string16 value2_;
197 int unique_id1_, unique_id2_;
198 const TimeDelta test_timeout_;
199 testing::NiceMock<MockAutofillWebDataServiceObserver> observer_;
200 WaitableEvent done_event_;
201 };
202
TEST_F(WebDataServiceAutofillTest,FormFillAdd)203 TEST_F(WebDataServiceAutofillTest, FormFillAdd) {
204 const AutofillChange expected_changes[] = {
205 AutofillChange(AutofillChange::ADD, AutofillKey(name1_, value1_)),
206 AutofillChange(AutofillChange::ADD, AutofillKey(name2_, value2_))
207 };
208
209 // This will verify that the correct notification is triggered,
210 // passing the correct list of autofill keys in the details.
211 EXPECT_CALL(observer_,
212 AutofillEntriesChanged(ElementsAreArray(expected_changes)))
213 .WillOnce(SignalEvent(&done_event_));
214
215 std::vector<FormFieldData> form_fields;
216 AppendFormField(name1_, value1_, &form_fields);
217 AppendFormField(name2_, value2_, &form_fields);
218 wds_->AddFormFields(form_fields);
219
220 // The event will be signaled when the mock observer is notified.
221 done_event_.TimedWait(test_timeout_);
222
223 AutofillWebDataServiceConsumer<std::vector<base::string16> > consumer;
224 WebDataServiceBase::Handle handle;
225 static const int limit = 10;
226 handle = wds_->GetFormValuesForElementName(
227 name1_, base::string16(), limit, &consumer);
228
229 // The message loop will exit when the consumer is called.
230 base::MessageLoop::current()->Run();
231
232 EXPECT_EQ(handle, consumer.handle());
233 ASSERT_EQ(1U, consumer.result().size());
234 EXPECT_EQ(value1_, consumer.result()[0]);
235 }
236
TEST_F(WebDataServiceAutofillTest,FormFillRemoveOne)237 TEST_F(WebDataServiceAutofillTest, FormFillRemoveOne) {
238 // First add some values to autofill.
239 EXPECT_CALL(observer_, AutofillEntriesChanged(_))
240 .WillOnce(SignalEvent(&done_event_));
241 std::vector<FormFieldData> form_fields;
242 AppendFormField(name1_, value1_, &form_fields);
243 wds_->AddFormFields(form_fields);
244
245 // The event will be signaled when the mock observer is notified.
246 done_event_.TimedWait(test_timeout_);
247
248 // This will verify that the correct notification is triggered,
249 // passing the correct list of autofill keys in the details.
250 const AutofillChange expected_changes[] = {
251 AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_))
252 };
253 EXPECT_CALL(observer_,
254 AutofillEntriesChanged(ElementsAreArray(expected_changes)))
255 .WillOnce(SignalEvent(&done_event_));
256 wds_->RemoveFormValueForElementName(name1_, value1_);
257
258 // The event will be signaled when the mock observer is notified.
259 done_event_.TimedWait(test_timeout_);
260 }
261
TEST_F(WebDataServiceAutofillTest,FormFillRemoveMany)262 TEST_F(WebDataServiceAutofillTest, FormFillRemoveMany) {
263 TimeDelta one_day(TimeDelta::FromDays(1));
264 Time t = Time::Now();
265
266 EXPECT_CALL(observer_, AutofillEntriesChanged(_))
267 .WillOnce(SignalEvent(&done_event_));
268
269 std::vector<FormFieldData> form_fields;
270 AppendFormField(name1_, value1_, &form_fields);
271 AppendFormField(name2_, value2_, &form_fields);
272 wds_->AddFormFields(form_fields);
273
274 // The event will be signaled when the mock observer is notified.
275 done_event_.TimedWait(test_timeout_);
276
277 // This will verify that the correct notification is triggered,
278 // passing the correct list of autofill keys in the details.
279 const AutofillChange expected_changes[] = {
280 AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_)),
281 AutofillChange(AutofillChange::REMOVE, AutofillKey(name2_, value2_))
282 };
283 EXPECT_CALL(observer_,
284 AutofillEntriesChanged(ElementsAreArray(expected_changes)))
285 .WillOnce(SignalEvent(&done_event_));
286 wds_->RemoveFormElementsAddedBetween(t, t + one_day);
287
288 // The event will be signaled when the mock observer is notified.
289 done_event_.TimedWait(test_timeout_);
290 }
291
TEST_F(WebDataServiceAutofillTest,ProfileAdd)292 TEST_F(WebDataServiceAutofillTest, ProfileAdd) {
293 AutofillProfile profile;
294
295 // Check that GUID-based notification was sent.
296 const AutofillProfileChange expected_change(
297 AutofillProfileChange::ADD, profile.guid(), &profile);
298 EXPECT_CALL(observer_, AutofillProfileChanged(expected_change))
299 .WillOnce(SignalEvent(&done_event_));
300
301 wds_->AddAutofillProfile(profile);
302 done_event_.TimedWait(test_timeout_);
303
304 // Check that it was added.
305 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer;
306 WebDataServiceBase::Handle handle = wds_->GetAutofillProfiles(&consumer);
307 base::MessageLoop::current()->Run();
308 EXPECT_EQ(handle, consumer.handle());
309 ASSERT_EQ(1U, consumer.result().size());
310 EXPECT_EQ(profile, *consumer.result()[0]);
311 STLDeleteElements(&consumer.result());
312 }
313
TEST_F(WebDataServiceAutofillTest,ProfileRemove)314 TEST_F(WebDataServiceAutofillTest, ProfileRemove) {
315 AutofillProfile profile;
316
317 // Add a profile.
318 EXPECT_CALL(observer_, AutofillProfileChanged(_))
319 .WillOnce(SignalEvent(&done_event_));
320 wds_->AddAutofillProfile(profile);
321 done_event_.TimedWait(test_timeout_);
322
323 // Check that it was added.
324 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer;
325 WebDataServiceBase::Handle handle = wds_->GetAutofillProfiles(&consumer);
326 base::MessageLoop::current()->Run();
327 EXPECT_EQ(handle, consumer.handle());
328 ASSERT_EQ(1U, consumer.result().size());
329 EXPECT_EQ(profile, *consumer.result()[0]);
330 STLDeleteElements(&consumer.result());
331
332 // Check that GUID-based notification was sent.
333 const AutofillProfileChange expected_change(
334 AutofillProfileChange::REMOVE, profile.guid(), NULL);
335 EXPECT_CALL(observer_, AutofillProfileChanged(expected_change))
336 .WillOnce(SignalEvent(&done_event_));
337
338 // Remove the profile.
339 wds_->RemoveAutofillProfile(profile.guid());
340 done_event_.TimedWait(test_timeout_);
341
342 // Check that it was removed.
343 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer2;
344 WebDataServiceBase::Handle handle2 = wds_->GetAutofillProfiles(&consumer2);
345 base::MessageLoop::current()->Run();
346 EXPECT_EQ(handle2, consumer2.handle());
347 ASSERT_EQ(0U, consumer2.result().size());
348 }
349
TEST_F(WebDataServiceAutofillTest,ProfileUpdate)350 TEST_F(WebDataServiceAutofillTest, ProfileUpdate) {
351 AutofillProfile profile1;
352 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Abe"));
353 AutofillProfile profile2;
354 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Alice"));
355
356 EXPECT_CALL(observer_, AutofillProfileChanged(_))
357 .WillOnce(DoDefault())
358 .WillOnce(SignalEvent(&done_event_));
359
360 wds_->AddAutofillProfile(profile1);
361 wds_->AddAutofillProfile(profile2);
362 done_event_.TimedWait(test_timeout_);
363
364 // Check that they were added.
365 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer;
366 WebDataServiceBase::Handle handle = wds_->GetAutofillProfiles(&consumer);
367 base::MessageLoop::current()->Run();
368 EXPECT_EQ(handle, consumer.handle());
369 ASSERT_EQ(2U, consumer.result().size());
370 EXPECT_EQ(profile1, *consumer.result()[0]);
371 EXPECT_EQ(profile2, *consumer.result()[1]);
372 STLDeleteElements(&consumer.result());
373
374 AutofillProfile profile1_changed(profile1);
375 profile1_changed.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bill"));
376 const AutofillProfileChange expected_change(
377 AutofillProfileChange::UPDATE, profile1.guid(), &profile1_changed);
378
379 EXPECT_CALL(observer_, AutofillProfileChanged(expected_change))
380 .WillOnce(SignalEvent(&done_event_));
381
382 // Update the profile.
383 wds_->UpdateAutofillProfile(profile1_changed);
384 done_event_.TimedWait(test_timeout_);
385
386 // Check that the updates were made.
387 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer2;
388 WebDataServiceBase::Handle handle2 = wds_->GetAutofillProfiles(&consumer2);
389 base::MessageLoop::current()->Run();
390 EXPECT_EQ(handle2, consumer2.handle());
391 ASSERT_EQ(2U, consumer2.result().size());
392 EXPECT_NE(profile1, *consumer2.result()[0]);
393 EXPECT_EQ(profile1_changed, *consumer2.result()[0]);
394 EXPECT_EQ(profile2, *consumer2.result()[1]);
395 STLDeleteElements(&consumer2.result());
396 }
397
TEST_F(WebDataServiceAutofillTest,CreditAdd)398 TEST_F(WebDataServiceAutofillTest, CreditAdd) {
399 CreditCard card;
400 wds_->AddCreditCard(card);
401 WaitForDatabaseThread();
402
403 // Check that it was added.
404 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer;
405 WebDataServiceBase::Handle handle = wds_->GetCreditCards(&consumer);
406 base::MessageLoop::current()->Run();
407 EXPECT_EQ(handle, consumer.handle());
408 ASSERT_EQ(1U, consumer.result().size());
409 EXPECT_EQ(card, *consumer.result()[0]);
410 STLDeleteElements(&consumer.result());
411 }
412
TEST_F(WebDataServiceAutofillTest,CreditCardRemove)413 TEST_F(WebDataServiceAutofillTest, CreditCardRemove) {
414 CreditCard credit_card;
415
416 // Add a credit card.
417 wds_->AddCreditCard(credit_card);
418 WaitForDatabaseThread();
419
420 // Check that it was added.
421 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer;
422 WebDataServiceBase::Handle handle = wds_->GetCreditCards(&consumer);
423 base::MessageLoop::current()->Run();
424 EXPECT_EQ(handle, consumer.handle());
425 ASSERT_EQ(1U, consumer.result().size());
426 EXPECT_EQ(credit_card, *consumer.result()[0]);
427 STLDeleteElements(&consumer.result());
428
429 // Remove the credit card.
430 wds_->RemoveCreditCard(credit_card.guid());
431 WaitForDatabaseThread();
432
433 // Check that it was removed.
434 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer2;
435 WebDataServiceBase::Handle handle2 = wds_->GetCreditCards(&consumer2);
436 base::MessageLoop::current()->Run();
437 EXPECT_EQ(handle2, consumer2.handle());
438 ASSERT_EQ(0U, consumer2.result().size());
439 }
440
TEST_F(WebDataServiceAutofillTest,CreditUpdate)441 TEST_F(WebDataServiceAutofillTest, CreditUpdate) {
442 CreditCard card1;
443 card1.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Abe"));
444 CreditCard card2;
445 card2.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Alice"));
446
447 wds_->AddCreditCard(card1);
448 wds_->AddCreditCard(card2);
449 WaitForDatabaseThread();
450
451 // Check that they got added.
452 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer;
453 WebDataServiceBase::Handle handle = wds_->GetCreditCards(&consumer);
454 base::MessageLoop::current()->Run();
455 EXPECT_EQ(handle, consumer.handle());
456 ASSERT_EQ(2U, consumer.result().size());
457 EXPECT_EQ(card1, *consumer.result()[0]);
458 EXPECT_EQ(card2, *consumer.result()[1]);
459 STLDeleteElements(&consumer.result());
460
461 CreditCard card1_changed(card1);
462 card1_changed.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Bill"));
463
464 wds_->UpdateCreditCard(card1_changed);
465 WaitForDatabaseThread();
466
467 // Check that the updates were made.
468 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer2;
469 WebDataServiceBase::Handle handle2 = wds_->GetCreditCards(&consumer2);
470 base::MessageLoop::current()->Run();
471 EXPECT_EQ(handle2, consumer2.handle());
472 ASSERT_EQ(2U, consumer2.result().size());
473 EXPECT_NE(card1, *consumer2.result()[0]);
474 EXPECT_EQ(card1_changed, *consumer2.result()[0]);
475 EXPECT_EQ(card2, *consumer2.result()[1]);
476 STLDeleteElements(&consumer2.result());
477 }
478
TEST_F(WebDataServiceAutofillTest,AutofillRemoveModifiedBetween)479 TEST_F(WebDataServiceAutofillTest, AutofillRemoveModifiedBetween) {
480 // Add a profile.
481 EXPECT_CALL(observer_, AutofillProfileChanged(_))
482 .WillOnce(SignalEvent(&done_event_));
483 AutofillProfile profile;
484 wds_->AddAutofillProfile(profile);
485 done_event_.TimedWait(test_timeout_);
486
487 // Check that it was added.
488 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> >
489 profile_consumer;
490 WebDataServiceBase::Handle handle =
491 wds_->GetAutofillProfiles(&profile_consumer);
492 base::MessageLoop::current()->Run();
493 EXPECT_EQ(handle, profile_consumer.handle());
494 ASSERT_EQ(1U, profile_consumer.result().size());
495 EXPECT_EQ(profile, *profile_consumer.result()[0]);
496 STLDeleteElements(&profile_consumer.result());
497
498 // Add a credit card.
499 CreditCard credit_card;
500 wds_->AddCreditCard(credit_card);
501 WaitForDatabaseThread();
502
503 // Check that it was added.
504 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > card_consumer;
505 handle = wds_->GetCreditCards(&card_consumer);
506 base::MessageLoop::current()->Run();
507 EXPECT_EQ(handle, card_consumer.handle());
508 ASSERT_EQ(1U, card_consumer.result().size());
509 EXPECT_EQ(credit_card, *card_consumer.result()[0]);
510 STLDeleteElements(&card_consumer.result());
511
512 // Check that GUID-based notification was sent for the profile.
513 const AutofillProfileChange expected_profile_change(
514 AutofillProfileChange::REMOVE, profile.guid(), NULL);
515 EXPECT_CALL(observer_, AutofillProfileChanged(expected_profile_change))
516 .WillOnce(SignalEvent(&done_event_));
517
518 // Remove the profile using time range of "all time".
519 wds_->RemoveAutofillDataModifiedBetween(Time(), Time());
520 done_event_.TimedWait(test_timeout_);
521 WaitForDatabaseThread();
522
523 // Check that the profile was removed.
524 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> >
525 profile_consumer2;
526 WebDataServiceBase::Handle handle2 =
527 wds_->GetAutofillProfiles(&profile_consumer2);
528 base::MessageLoop::current()->Run();
529 EXPECT_EQ(handle2, profile_consumer2.handle());
530 ASSERT_EQ(0U, profile_consumer2.result().size());
531
532 // Check that the credit card was removed.
533 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > card_consumer2;
534 handle2 = wds_->GetCreditCards(&card_consumer2);
535 base::MessageLoop::current()->Run();
536 EXPECT_EQ(handle2, card_consumer2.handle());
537 ASSERT_EQ(0U, card_consumer2.result().size());
538 }
539
540 } // namespace autofill
541