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