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