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
38using base::ASCIIToUTF16;
39using base::Time;
40using base::TimeDelta;
41using base::WaitableEvent;
42using testing::_;
43using testing::DoDefault;
44using testing::ElementsAreArray;
45using testing::Pointee;
46using testing::Property;
47
48namespace {
49
50template <class T>
51class AutofillWebDataServiceConsumer: public WebDataServiceConsumer {
52 public:
53  AutofillWebDataServiceConsumer() : handle_(0) {}
54  virtual ~AutofillWebDataServiceConsumer() {}
55
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
66  WebDataServiceBase::Handle handle() { return handle_; }
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
77namespace autofill {
78
79static const int kWebDataServiceTimeoutSeconds = 8;
80
81ACTION_P(SignalEvent, event) {
82  event->Signal();
83}
84
85class 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
94class WebDataServiceTest : public testing::Test {
95 public:
96  WebDataServiceTest() : db_thread_("DBThread") {}
97
98 protected:
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
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
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
148class WebDataServiceAutofillTest : public WebDataServiceTest {
149 public:
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:
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
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
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
203TEST_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
237TEST_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
262TEST_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
292TEST_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
314TEST_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
350TEST_F(WebDataServiceAutofillTest, ProfileUpdate) {
351  // The GUIDs are alphabetical for easier testing.
352  AutofillProfile profile1("087151C8-6AB1-487C-9095-28E80BE5DA15",
353                           "http://example.com");
354  profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Abe"));
355  AutofillProfile profile2("6141084B-72D7-4B73-90CF-3D6AC154673B",
356                           "http://example.com");
357  profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Alice"));
358
359  EXPECT_CALL(observer_, AutofillProfileChanged(_))
360      .WillOnce(DoDefault())
361      .WillOnce(SignalEvent(&done_event_));
362
363  wds_->AddAutofillProfile(profile1);
364  wds_->AddAutofillProfile(profile2);
365  done_event_.TimedWait(test_timeout_);
366
367  // Check that they were added.
368  AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer;
369  WebDataServiceBase::Handle handle = wds_->GetAutofillProfiles(&consumer);
370  base::MessageLoop::current()->Run();
371  EXPECT_EQ(handle, consumer.handle());
372  ASSERT_EQ(2U, consumer.result().size());
373  EXPECT_EQ(profile1, *consumer.result()[0]);
374  EXPECT_EQ(profile2, *consumer.result()[1]);
375  STLDeleteElements(&consumer.result());
376
377  AutofillProfile profile2_changed(profile2);
378  profile2_changed.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bill"));
379  const AutofillProfileChange expected_change(
380      AutofillProfileChange::UPDATE, profile2.guid(), &profile2_changed);
381
382  EXPECT_CALL(observer_, AutofillProfileChanged(expected_change))
383      .WillOnce(SignalEvent(&done_event_));
384
385  // Update the profile.
386  wds_->UpdateAutofillProfile(profile2_changed);
387  done_event_.TimedWait(test_timeout_);
388
389  // Check that the updates were made.
390  AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer2;
391  WebDataServiceBase::Handle handle2 = wds_->GetAutofillProfiles(&consumer2);
392  base::MessageLoop::current()->Run();
393  EXPECT_EQ(handle2, consumer2.handle());
394  ASSERT_EQ(2U, consumer2.result().size());
395  EXPECT_EQ(profile1, *consumer2.result()[0]);
396  EXPECT_EQ(profile2_changed, *consumer2.result()[1]);
397  EXPECT_NE(profile2, *consumer2.result()[1]);
398  STLDeleteElements(&consumer2.result());
399}
400
401TEST_F(WebDataServiceAutofillTest, CreditAdd) {
402  CreditCard card;
403  wds_->AddCreditCard(card);
404  WaitForDatabaseThread();
405
406  // Check that it was added.
407  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer;
408  WebDataServiceBase::Handle handle = wds_->GetCreditCards(&consumer);
409  base::MessageLoop::current()->Run();
410  EXPECT_EQ(handle, consumer.handle());
411  ASSERT_EQ(1U, consumer.result().size());
412  EXPECT_EQ(card, *consumer.result()[0]);
413  STLDeleteElements(&consumer.result());
414}
415
416TEST_F(WebDataServiceAutofillTest, CreditCardRemove) {
417  CreditCard credit_card;
418
419  // Add a credit card.
420  wds_->AddCreditCard(credit_card);
421  WaitForDatabaseThread();
422
423  // Check that it was added.
424  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer;
425  WebDataServiceBase::Handle handle = wds_->GetCreditCards(&consumer);
426  base::MessageLoop::current()->Run();
427  EXPECT_EQ(handle, consumer.handle());
428  ASSERT_EQ(1U, consumer.result().size());
429  EXPECT_EQ(credit_card, *consumer.result()[0]);
430  STLDeleteElements(&consumer.result());
431
432  // Remove the credit card.
433  wds_->RemoveCreditCard(credit_card.guid());
434  WaitForDatabaseThread();
435
436  // Check that it was removed.
437  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer2;
438  WebDataServiceBase::Handle handle2 = wds_->GetCreditCards(&consumer2);
439  base::MessageLoop::current()->Run();
440  EXPECT_EQ(handle2, consumer2.handle());
441  ASSERT_EQ(0U, consumer2.result().size());
442}
443
444TEST_F(WebDataServiceAutofillTest, CreditUpdate) {
445  CreditCard card1("B9C52112-BD5F-4080-84E1-C651D2CB90E2",
446                   "https://ejemplo.mx");
447  card1.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Abe"));
448  CreditCard card2("E4D2662E-5E16-44F3-AF5A-5A77FAE4A6F3",
449                   "https://example.com");
450  card2.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Alice"));
451
452  wds_->AddCreditCard(card1);
453  wds_->AddCreditCard(card2);
454  WaitForDatabaseThread();
455
456  // Check that they got added.
457  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer;
458  WebDataServiceBase::Handle handle = wds_->GetCreditCards(&consumer);
459  base::MessageLoop::current()->Run();
460  EXPECT_EQ(handle, consumer.handle());
461  ASSERT_EQ(2U, consumer.result().size());
462  EXPECT_EQ(card1, *consumer.result()[0]);
463  EXPECT_EQ(card2, *consumer.result()[1]);
464  STLDeleteElements(&consumer.result());
465
466  CreditCard card1_changed(card1);
467  card1_changed.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Bill"));
468
469  wds_->UpdateCreditCard(card1_changed);
470  WaitForDatabaseThread();
471
472  // Check that the updates were made.
473  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer2;
474  WebDataServiceBase::Handle handle2 = wds_->GetCreditCards(&consumer2);
475  base::MessageLoop::current()->Run();
476  EXPECT_EQ(handle2, consumer2.handle());
477  ASSERT_EQ(2U, consumer2.result().size());
478  EXPECT_NE(card1, *consumer2.result()[0]);
479  EXPECT_EQ(card1_changed, *consumer2.result()[0]);
480  EXPECT_EQ(card2, *consumer2.result()[1]);
481  STLDeleteElements(&consumer2.result());
482}
483
484TEST_F(WebDataServiceAutofillTest, AutofillRemoveModifiedBetween) {
485  // Add a profile.
486  EXPECT_CALL(observer_, AutofillProfileChanged(_))
487      .WillOnce(SignalEvent(&done_event_));
488  AutofillProfile profile;
489  wds_->AddAutofillProfile(profile);
490  done_event_.TimedWait(test_timeout_);
491
492  // Check that it was added.
493  AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> >
494      profile_consumer;
495  WebDataServiceBase::Handle handle =
496      wds_->GetAutofillProfiles(&profile_consumer);
497  base::MessageLoop::current()->Run();
498  EXPECT_EQ(handle, profile_consumer.handle());
499  ASSERT_EQ(1U, profile_consumer.result().size());
500  EXPECT_EQ(profile, *profile_consumer.result()[0]);
501  STLDeleteElements(&profile_consumer.result());
502
503  // Add a credit card.
504  CreditCard credit_card;
505  wds_->AddCreditCard(credit_card);
506  WaitForDatabaseThread();
507
508  // Check that it was added.
509  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > card_consumer;
510  handle = wds_->GetCreditCards(&card_consumer);
511  base::MessageLoop::current()->Run();
512  EXPECT_EQ(handle, card_consumer.handle());
513  ASSERT_EQ(1U, card_consumer.result().size());
514  EXPECT_EQ(credit_card, *card_consumer.result()[0]);
515  STLDeleteElements(&card_consumer.result());
516
517  // Check that GUID-based notification was sent for the profile.
518  const AutofillProfileChange expected_profile_change(
519      AutofillProfileChange::REMOVE, profile.guid(), NULL);
520  EXPECT_CALL(observer_, AutofillProfileChanged(expected_profile_change))
521      .WillOnce(SignalEvent(&done_event_));
522
523  // Remove the profile using time range of "all time".
524  wds_->RemoveAutofillDataModifiedBetween(Time(), Time());
525  done_event_.TimedWait(test_timeout_);
526  WaitForDatabaseThread();
527
528  // Check that the profile was removed.
529  AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> >
530      profile_consumer2;
531  WebDataServiceBase::Handle handle2 =
532      wds_->GetAutofillProfiles(&profile_consumer2);
533  base::MessageLoop::current()->Run();
534  EXPECT_EQ(handle2, profile_consumer2.handle());
535  ASSERT_EQ(0U, profile_consumer2.result().size());
536
537  // Check that the credit card was removed.
538  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > card_consumer2;
539  handle2 = wds_->GetCreditCards(&card_consumer2);
540  base::MessageLoop::current()->Run();
541  EXPECT_EQ(handle2, card_consumer2.handle());
542  ASSERT_EQ(0U, card_consumer2.result().size());
543}
544
545}  // namespace autofill
546