web_data_service_unittest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2011 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/file_util.h"
10#include "base/message_loop.h"
11#include "base/path_service.h"
12#include "base/ref_counted.h"
13#include "base/scoped_ptr.h"
14#include "base/scoped_vector.h"
15#include "base/stl_util-inl.h"
16#include "base/string16.h"
17#include "base/string_util.h"
18#include "base/synchronization/waitable_event.h"
19#include "base/time.h"
20#include "base/utf_string_conversions.h"
21#include "chrome/browser/autofill/autofill_profile.h"
22#include "chrome/browser/autofill/credit_card.h"
23#include "chrome/browser/webdata/autofill_change.h"
24#include "chrome/browser/webdata/autofill_entry.h"
25#include "chrome/browser/webdata/web_data_service.h"
26#include "chrome/browser/webdata/web_data_service_test_util.h"
27#include "chrome/common/chrome_paths.h"
28#include "chrome/common/guid.h"
29#include "chrome/common/notification_details.h"
30#include "chrome/common/notification_service.h"
31#include "chrome/common/notification_type.h"
32#include "chrome/test/thread_observer_helper.h"
33#include "content/browser/browser_thread.h"
34#include "testing/gmock/include/gmock/gmock.h"
35#include "testing/gtest/include/gtest/gtest.h"
36#include "webkit/glue/form_field.h"
37
38using base::Time;
39using base::TimeDelta;
40using base::WaitableEvent;
41using testing::_;
42using testing::DoDefault;
43using testing::ElementsAreArray;
44using testing::Pointee;
45using testing::Property;
46
47typedef std::vector<AutofillChange> AutofillChangeList;
48
49static const int kWebDataServiceTimeoutSeconds = 8;
50
51ACTION_P(SignalEvent, event) {
52  event->Signal();
53}
54
55class AutofillDBThreadObserverHelper : public DBThreadObserverHelper {
56 protected:
57  virtual void RegisterObservers() {
58    registrar_.Add(&observer_,
59                   NotificationType::AUTOFILL_ENTRIES_CHANGED,
60                   NotificationService::AllSources());
61    registrar_.Add(&observer_,
62                   NotificationType::AUTOFILL_PROFILE_CHANGED,
63                   NotificationService::AllSources());
64    registrar_.Add(&observer_,
65                   NotificationType::AUTOFILL_CREDIT_CARD_CHANGED,
66                   NotificationService::AllSources());
67  }
68};
69
70class WebDataServiceTest : public testing::Test {
71 public:
72  WebDataServiceTest()
73      : ui_thread_(BrowserThread::UI, &message_loop_),
74        db_thread_(BrowserThread::DB) {}
75
76 protected:
77  virtual void SetUp() {
78    db_thread_.Start();
79
80    PathService::Get(chrome::DIR_TEST_DATA, &profile_dir_);
81    const std::string test_profile = "WebDataServiceTest";
82    profile_dir_ = profile_dir_.AppendASCII(test_profile);
83    file_util::Delete(profile_dir_, true);
84    file_util::CreateDirectory(profile_dir_);
85    wds_ = new WebDataService();
86    wds_->Init(profile_dir_);
87  }
88
89  virtual void TearDown() {
90    if (wds_.get())
91      wds_->Shutdown();
92    file_util::Delete(profile_dir_, true);
93
94    db_thread_.Stop();
95    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
96    MessageLoop::current()->Run();
97  }
98
99  MessageLoopForUI message_loop_;
100  BrowserThread ui_thread_;
101  BrowserThread db_thread_;
102  FilePath profile_dir_;
103  scoped_refptr<WebDataService> wds_;
104};
105
106class WebDataServiceAutofillTest : public WebDataServiceTest {
107 public:
108  WebDataServiceAutofillTest()
109      : WebDataServiceTest(),
110        unique_id1_(1),
111        unique_id2_(2),
112        test_timeout_(TimeDelta::FromSeconds(kWebDataServiceTimeoutSeconds)),
113        done_event_(false, false) {}
114
115 protected:
116  virtual void SetUp() {
117    WebDataServiceTest::SetUp();
118    name1_ = ASCIIToUTF16("name1");
119    name2_ = ASCIIToUTF16("name2");
120    value1_ = ASCIIToUTF16("value1");
121    value2_ = ASCIIToUTF16("value2");
122    observer_helper_ = new AutofillDBThreadObserverHelper();
123    observer_helper_->Init();
124  }
125
126  virtual void TearDown() {
127    // Release this first so it can get destructed on the db thread.
128    observer_helper_ = NULL;
129    WebDataServiceTest::TearDown();
130  }
131
132  void AppendFormField(const string16& name,
133                       const string16& value,
134                       std::vector<webkit_glue::FormField>* form_fields) {
135    form_fields->push_back(
136        webkit_glue::FormField(string16(),
137                               name,
138                               value,
139                               string16(),
140                               0,
141                               false));
142  }
143
144  string16 name1_;
145  string16 name2_;
146  string16 value1_;
147  string16 value2_;
148  int unique_id1_, unique_id2_;
149  const TimeDelta test_timeout_;
150  scoped_refptr<AutofillDBThreadObserverHelper> observer_helper_;
151  WaitableEvent done_event_;
152};
153
154TEST_F(WebDataServiceAutofillTest, FormFillAdd) {
155  const AutofillChange expected_changes[] = {
156    AutofillChange(AutofillChange::ADD, AutofillKey(name1_, value1_)),
157    AutofillChange(AutofillChange::ADD, AutofillKey(name2_, value2_))
158  };
159
160  // This will verify that the correct notification is triggered,
161  // passing the correct list of autofill keys in the details.
162  EXPECT_CALL(
163      *observer_helper_->observer(),
164      Observe(NotificationType(NotificationType::AUTOFILL_ENTRIES_CHANGED),
165              Source<WebDataService>(wds_.get()),
166              Property(&Details<const AutofillChangeList>::ptr,
167                       Pointee(ElementsAreArray(expected_changes))))).
168      WillOnce(SignalEvent(&done_event_));
169
170  std::vector<webkit_glue::FormField> form_fields;
171  AppendFormField(name1_, value1_, &form_fields);
172  AppendFormField(name2_, value2_, &form_fields);
173  wds_->AddFormFields(form_fields);
174
175  // The event will be signaled when the mock observer is notified.
176  done_event_.TimedWait(test_timeout_);
177
178  AutofillWebDataServiceConsumer<std::vector<string16> > consumer;
179  WebDataService::Handle handle;
180  static const int limit = 10;
181  handle = wds_->GetFormValuesForElementName(
182      name1_, string16(), limit, &consumer);
183
184  // The message loop will exit when the consumer is called.
185  MessageLoop::current()->Run();
186
187  EXPECT_EQ(handle, consumer.handle());
188  ASSERT_EQ(1U, consumer.result().size());
189  EXPECT_EQ(value1_, consumer.result()[0]);
190}
191
192TEST_F(WebDataServiceAutofillTest, FormFillRemoveOne) {
193  // First add some values to autofill.
194  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
195      WillOnce(SignalEvent(&done_event_));
196  std::vector<webkit_glue::FormField> form_fields;
197  AppendFormField(name1_, value1_, &form_fields);
198  wds_->AddFormFields(form_fields);
199
200  // The event will be signaled when the mock observer is notified.
201  done_event_.TimedWait(test_timeout_);
202
203  // This will verify that the correct notification is triggered,
204  // passing the correct list of autofill keys in the details.
205  const AutofillChange expected_changes[] = {
206    AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_))
207  };
208  EXPECT_CALL(
209      *observer_helper_->observer(),
210      Observe(NotificationType(NotificationType::AUTOFILL_ENTRIES_CHANGED),
211              Source<WebDataService>(wds_.get()),
212              Property(&Details<const AutofillChangeList>::ptr,
213                       Pointee(ElementsAreArray(expected_changes))))).
214      WillOnce(SignalEvent(&done_event_));
215  wds_->RemoveFormValueForElementName(name1_, value1_);
216
217  // The event will be signaled when the mock observer is notified.
218  done_event_.TimedWait(test_timeout_);
219}
220
221TEST_F(WebDataServiceAutofillTest, FormFillRemoveMany) {
222  TimeDelta one_day(TimeDelta::FromDays(1));
223  Time t = Time::Now();
224
225  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
226      WillOnce(SignalEvent(&done_event_));
227  std::vector<webkit_glue::FormField> form_fields;
228  AppendFormField(name1_, value1_, &form_fields);
229  AppendFormField(name2_, value2_, &form_fields);
230  wds_->AddFormFields(form_fields);
231
232  // The event will be signaled when the mock observer is notified.
233  done_event_.TimedWait(test_timeout_);
234
235  // This will verify that the correct notification is triggered,
236  // passing the correct list of autofill keys in the details.
237  const AutofillChange expected_changes[] = {
238    AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_)),
239    AutofillChange(AutofillChange::REMOVE, AutofillKey(name2_, value2_))
240  };
241  EXPECT_CALL(
242      *observer_helper_->observer(),
243      Observe(NotificationType(NotificationType::AUTOFILL_ENTRIES_CHANGED),
244              Source<WebDataService>(wds_.get()),
245              Property(&Details<const AutofillChangeList>::ptr,
246                       Pointee(ElementsAreArray(expected_changes))))).
247      WillOnce(SignalEvent(&done_event_));
248  wds_->RemoveFormElementsAddedBetween(t, t + one_day);
249
250  // The event will be signaled when the mock observer is notified.
251  done_event_.TimedWait(test_timeout_);
252}
253
254TEST_F(WebDataServiceAutofillTest, ProfileAdd) {
255  AutoFillProfile profile;
256
257  // Check that GUID-based notification was sent.
258  const AutofillProfileChange expected_change(
259      AutofillProfileChange::ADD, profile.guid(), &profile);
260  EXPECT_CALL(
261      *observer_helper_->observer(),
262      Observe(NotificationType(NotificationType::AUTOFILL_PROFILE_CHANGED),
263              Source<WebDataService>(wds_.get()),
264              Property(&Details<const AutofillProfileChange>::ptr,
265                       Pointee(expected_change)))).
266      WillOnce(SignalEvent(&done_event_));
267
268  wds_->AddAutoFillProfile(profile);
269  done_event_.TimedWait(test_timeout_);
270
271  // Check that it was added.
272  AutofillWebDataServiceConsumer<std::vector<AutoFillProfile*> > consumer;
273  WebDataService::Handle handle = wds_->GetAutoFillProfiles(&consumer);
274  MessageLoop::current()->Run();
275  EXPECT_EQ(handle, consumer.handle());
276  ASSERT_EQ(1U, consumer.result().size());
277  EXPECT_EQ(profile, *consumer.result()[0]);
278  STLDeleteElements(&consumer.result());
279}
280
281TEST_F(WebDataServiceAutofillTest, ProfileRemove) {
282  AutoFillProfile profile;
283
284  // Add a profile.
285  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
286      Times(1).
287      WillOnce(SignalEvent(&done_event_));
288  wds_->AddAutoFillProfile(profile);
289  done_event_.TimedWait(test_timeout_);
290
291  // Check that it was added.
292  AutofillWebDataServiceConsumer<std::vector<AutoFillProfile*> > consumer;
293  WebDataService::Handle handle = wds_->GetAutoFillProfiles(&consumer);
294  MessageLoop::current()->Run();
295  EXPECT_EQ(handle, consumer.handle());
296  ASSERT_EQ(1U, consumer.result().size());
297  EXPECT_EQ(profile, *consumer.result()[0]);
298  STLDeleteElements(&consumer.result());
299
300  // Check that GUID-based notification was sent.
301  const AutofillProfileChange expected_change(
302      AutofillProfileChange::REMOVE, profile.guid(), NULL);
303  EXPECT_CALL(
304      *observer_helper_->observer(),
305      Observe(NotificationType(NotificationType::AUTOFILL_PROFILE_CHANGED),
306              Source<WebDataService>(wds_.get()),
307              Property(&Details<const AutofillProfileChange>::ptr,
308                       Pointee(expected_change)))).
309      WillOnce(SignalEvent(&done_event_));
310
311  // Remove the profile.
312  wds_->RemoveAutoFillProfile(profile.guid());
313  done_event_.TimedWait(test_timeout_);
314
315  // Check that it was removed.
316  AutofillWebDataServiceConsumer<std::vector<AutoFillProfile*> > consumer2;
317  WebDataService::Handle handle2 = wds_->GetAutoFillProfiles(&consumer2);
318  MessageLoop::current()->Run();
319  EXPECT_EQ(handle2, consumer2.handle());
320  ASSERT_EQ(0U, consumer2.result().size());
321}
322
323TEST_F(WebDataServiceAutofillTest, ProfileUpdate) {
324  AutoFillProfile profile1;
325  profile1.SetInfo(AutofillType(NAME_FIRST), ASCIIToUTF16("Abe"));
326  AutoFillProfile profile2;
327  profile2.SetInfo(AutofillType(NAME_FIRST), ASCIIToUTF16("Alice"));
328
329  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
330      WillOnce(DoDefault()).
331      WillOnce(SignalEvent(&done_event_));
332  wds_->AddAutoFillProfile(profile1);
333  wds_->AddAutoFillProfile(profile2);
334  done_event_.TimedWait(test_timeout_);
335
336  // Check that they were added.
337  AutofillWebDataServiceConsumer<std::vector<AutoFillProfile*> > consumer;
338  WebDataService::Handle handle = wds_->GetAutoFillProfiles(&consumer);
339  MessageLoop::current()->Run();
340  EXPECT_EQ(handle, consumer.handle());
341  ASSERT_EQ(2U, consumer.result().size());
342  EXPECT_EQ(profile1, *consumer.result()[0]);
343  EXPECT_EQ(profile2, *consumer.result()[1]);
344  STLDeleteElements(&consumer.result());
345
346  AutoFillProfile profile1_changed(profile1);
347  profile1_changed.SetInfo(AutofillType(NAME_FIRST), ASCIIToUTF16("Bill"));
348  const AutofillProfileChange expected_change(
349      AutofillProfileChange::UPDATE, profile1.guid(), &profile1_changed);
350
351  EXPECT_CALL(
352      *observer_helper_->observer(),
353      Observe(NotificationType(NotificationType::AUTOFILL_PROFILE_CHANGED),
354              Source<WebDataService>(wds_.get()),
355              Property(&Details<const AutofillProfileChange>::ptr,
356                       Pointee(expected_change)))).
357      WillOnce(SignalEvent(&done_event_));
358
359  // Update the profile.
360  wds_->UpdateAutoFillProfile(profile1_changed);
361  done_event_.TimedWait(test_timeout_);
362
363  // Check that the updates were made.
364  AutofillWebDataServiceConsumer<std::vector<AutoFillProfile*> > consumer2;
365  WebDataService::Handle handle2 = wds_->GetAutoFillProfiles(&consumer2);
366  MessageLoop::current()->Run();
367  EXPECT_EQ(handle2, consumer2.handle());
368  ASSERT_EQ(2U, consumer2.result().size());
369  EXPECT_NE(profile1, *consumer2.result()[0]);
370  EXPECT_EQ(profile1_changed, *consumer2.result()[0]);
371  EXPECT_EQ(profile2, *consumer2.result()[1]);
372  STLDeleteElements(&consumer2.result());
373}
374
375TEST_F(WebDataServiceAutofillTest, CreditAdd) {
376  CreditCard card;
377  const AutofillCreditCardChange expected_change(
378      AutofillCreditCardChange::ADD, card.guid(), &card);
379
380  EXPECT_CALL(
381      *observer_helper_->observer(),
382      Observe(
383          NotificationType(NotificationType::AUTOFILL_CREDIT_CARD_CHANGED),
384              Source<WebDataService>(wds_.get()),
385              Property(&Details<const AutofillCreditCardChange>::ptr,
386                       Pointee(expected_change)))).
387      WillOnce(SignalEvent(&done_event_));
388
389  wds_->AddCreditCard(card);
390  done_event_.TimedWait(test_timeout_);
391
392  // Check that it was added.
393  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer;
394  WebDataService::Handle handle = wds_->GetCreditCards(&consumer);
395  MessageLoop::current()->Run();
396  EXPECT_EQ(handle, consumer.handle());
397  ASSERT_EQ(1U, consumer.result().size());
398  EXPECT_EQ(card, *consumer.result()[0]);
399  STLDeleteElements(&consumer.result());
400}
401
402TEST_F(WebDataServiceAutofillTest, CreditCardRemove) {
403  CreditCard credit_card;
404
405  // Add a credit card.
406  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
407      WillOnce(SignalEvent(&done_event_));
408  wds_->AddCreditCard(credit_card);
409  done_event_.TimedWait(test_timeout_);
410
411  // Check that it was added.
412  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer;
413  WebDataService::Handle handle = wds_->GetCreditCards(&consumer);
414  MessageLoop::current()->Run();
415  EXPECT_EQ(handle, consumer.handle());
416  ASSERT_EQ(1U, consumer.result().size());
417  EXPECT_EQ(credit_card, *consumer.result()[0]);
418  STLDeleteElements(&consumer.result());
419
420  // Remove the credit card.
421  const AutofillCreditCardChange expected_change(
422      AutofillCreditCardChange::REMOVE, credit_card.guid(), NULL);
423  EXPECT_CALL(
424      *observer_helper_->observer(),
425      Observe(
426          NotificationType(NotificationType::AUTOFILL_CREDIT_CARD_CHANGED),
427              Source<WebDataService>(wds_.get()),
428              Property(&Details<const AutofillCreditCardChange>::ptr,
429                       Pointee(expected_change)))).
430      WillOnce(SignalEvent(&done_event_));
431  wds_->RemoveCreditCard(credit_card.guid());
432  done_event_.TimedWait(test_timeout_);
433
434  // Check that it was removed.
435  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer2;
436  WebDataService::Handle handle2 = wds_->GetCreditCards(&consumer2);
437  MessageLoop::current()->Run();
438  EXPECT_EQ(handle2, consumer2.handle());
439  ASSERT_EQ(0U, consumer2.result().size());
440}
441
442TEST_F(WebDataServiceAutofillTest, CreditUpdate) {
443  CreditCard card1;
444  card1.SetInfo(AutofillType(CREDIT_CARD_NAME), ASCIIToUTF16("Abe"));
445  CreditCard card2;
446  card2.SetInfo(AutofillType(CREDIT_CARD_NAME), ASCIIToUTF16("Alice"));
447
448  EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)).
449      Times(2).
450      WillOnce(DoDefault()).
451      WillOnce(SignalEvent(&done_event_));
452  wds_->AddCreditCard(card1);
453  wds_->AddCreditCard(card2);
454  done_event_.TimedWait(test_timeout_);
455
456  // Check that they got added.
457  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer;
458  WebDataService::Handle handle = wds_->GetCreditCards(&consumer);
459  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.SetInfo(AutofillType(CREDIT_CARD_NAME), ASCIIToUTF16("Bill"));
468  const AutofillCreditCardChange expected_change(
469      AutofillCreditCardChange::UPDATE, card1.guid(), &card1_changed);
470
471  EXPECT_CALL(
472      *observer_helper_->observer(),
473      Observe(
474          NotificationType(NotificationType::AUTOFILL_CREDIT_CARD_CHANGED),
475              Source<WebDataService>(wds_.get()),
476              Property(&Details<const AutofillCreditCardChange>::ptr,
477                       Pointee(expected_change)))).
478      WillOnce(SignalEvent(&done_event_));
479
480  wds_->UpdateCreditCard(card1_changed);
481  done_event_.TimedWait(test_timeout_);
482
483  // Check that the updates were made.
484  AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer2;
485  WebDataService::Handle handle2 = wds_->GetCreditCards(&consumer2);
486  MessageLoop::current()->Run();
487  EXPECT_EQ(handle2, consumer2.handle());
488  ASSERT_EQ(2U, consumer2.result().size());
489  EXPECT_NE(card1, *consumer2.result()[0]);
490  EXPECT_EQ(card1_changed, *consumer2.result()[0]);
491  EXPECT_EQ(card2, *consumer2.result()[1]);
492  STLDeleteElements(&consumer2.result());
493}
494