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 <vector>
6
7#include "base/memory/ref_counted.h"
8#include "base/message_loop/message_loop_proxy.h"
9#include "base/prefs/pref_service.h"
10#include "base/run_loop.h"
11#include "base/strings/string16.h"
12#include "base/strings/utf_string_conversions.h"
13#include "base/synchronization/waitable_event.h"
14#include "components/autofill/core/browser/autocomplete_history_manager.h"
15#include "components/autofill/core/browser/autofill_external_delegate.h"
16#include "components/autofill/core/browser/autofill_manager.h"
17#include "components/autofill/core/browser/autofill_test_utils.h"
18#include "components/autofill/core/browser/test_autofill_client.h"
19#include "components/autofill/core/browser/test_autofill_driver.h"
20#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
21#include "components/autofill/core/common/form_data.h"
22#include "components/webdata/common/web_data_service_test_util.h"
23#include "testing/gmock/include/gmock/gmock.h"
24#include "testing/gtest/include/gtest/gtest.h"
25#include "ui/gfx/rect.h"
26
27using base::ASCIIToUTF16;
28using testing::_;
29
30namespace autofill {
31
32namespace {
33
34class MockWebDataService : public AutofillWebDataService {
35 public:
36  MockWebDataService()
37      : AutofillWebDataService(base::MessageLoopProxy::current(),
38                               base::MessageLoopProxy::current()) {}
39
40  MOCK_METHOD1(AddFormFields, void(const std::vector<FormFieldData>&));
41
42 protected:
43  virtual ~MockWebDataService() {}
44};
45
46class MockAutofillClient : public TestAutofillClient {
47 public:
48  MockAutofillClient(scoped_refptr<MockWebDataService> web_data_service)
49      : web_data_service_(web_data_service),
50        prefs_(test::PrefServiceForTesting()) {}
51  virtual ~MockAutofillClient() {}
52  virtual scoped_refptr<AutofillWebDataService>
53      GetDatabase() OVERRIDE { return web_data_service_; }
54  virtual PrefService* GetPrefs() OVERRIDE { return prefs_.get(); }
55
56 private:
57  scoped_refptr<MockWebDataService> web_data_service_;
58  scoped_ptr<PrefService> prefs_;
59
60  DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
61};
62
63}  // namespace
64
65class AutocompleteHistoryManagerTest : public testing::Test {
66 protected:
67  AutocompleteHistoryManagerTest() {}
68
69  virtual void SetUp() OVERRIDE {
70    web_data_service_ = new MockWebDataService();
71    autofill_client_.reset(new MockAutofillClient(web_data_service_));
72    autofill_driver_.reset(new TestAutofillDriver());
73    autocomplete_manager_.reset(new AutocompleteHistoryManager(
74        autofill_driver_.get(), autofill_client_.get()));
75  }
76
77  virtual void TearDown() OVERRIDE {
78    autocomplete_manager_.reset();
79  }
80
81  base::MessageLoop message_loop_;
82  scoped_refptr<MockWebDataService> web_data_service_;
83  scoped_ptr<AutocompleteHistoryManager> autocomplete_manager_;
84  scoped_ptr<AutofillDriver> autofill_driver_;
85  scoped_ptr<MockAutofillClient> autofill_client_;
86};
87
88// Tests that credit card numbers are not sent to the WebDatabase to be saved.
89TEST_F(AutocompleteHistoryManagerTest, CreditCardNumberValue) {
90  FormData form;
91  form.name = ASCIIToUTF16("MyForm");
92  form.origin = GURL("http://myform.com/form.html");
93  form.action = GURL("http://myform.com/submit.html");
94  form.user_submitted = true;
95
96  // Valid Visa credit card number pulled from the paypal help site.
97  FormFieldData valid_cc;
98  valid_cc.label = ASCIIToUTF16("Credit Card");
99  valid_cc.name = ASCIIToUTF16("ccnum");
100  valid_cc.value = ASCIIToUTF16("4012888888881881");
101  valid_cc.form_control_type = "text";
102  form.fields.push_back(valid_cc);
103
104  EXPECT_CALL(*web_data_service_.get(), AddFormFields(_)).Times(0);
105  autocomplete_manager_->OnFormSubmitted(form);
106}
107
108// Contrary test to AutocompleteHistoryManagerTest.CreditCardNumberValue.  The
109// value being submitted is not a valid credit card number, so it will be sent
110// to the WebDatabase to be saved.
111TEST_F(AutocompleteHistoryManagerTest, NonCreditCardNumberValue) {
112  FormData form;
113  form.name = ASCIIToUTF16("MyForm");
114  form.origin = GURL("http://myform.com/form.html");
115  form.action = GURL("http://myform.com/submit.html");
116  form.user_submitted = true;
117
118  // Invalid credit card number.
119  FormFieldData invalid_cc;
120  invalid_cc.label = ASCIIToUTF16("Credit Card");
121  invalid_cc.name = ASCIIToUTF16("ccnum");
122  invalid_cc.value = ASCIIToUTF16("4580123456789012");
123  invalid_cc.form_control_type = "text";
124  form.fields.push_back(invalid_cc);
125
126  EXPECT_CALL(*(web_data_service_.get()), AddFormFields(_)).Times(1);
127  autocomplete_manager_->OnFormSubmitted(form);
128}
129
130// Tests that SSNs are not sent to the WebDatabase to be saved.
131TEST_F(AutocompleteHistoryManagerTest, SSNValue) {
132  FormData form;
133  form.name = ASCIIToUTF16("MyForm");
134  form.origin = GURL("http://myform.com/form.html");
135  form.action = GURL("http://myform.com/submit.html");
136  form.user_submitted = true;
137
138  FormFieldData ssn;
139  ssn.label = ASCIIToUTF16("Social Security Number");
140  ssn.name = ASCIIToUTF16("ssn");
141  ssn.value = ASCIIToUTF16("078-05-1120");
142  ssn.form_control_type = "text";
143  form.fields.push_back(ssn);
144
145  EXPECT_CALL(*web_data_service_.get(), AddFormFields(_)).Times(0);
146  autocomplete_manager_->OnFormSubmitted(form);
147}
148
149// Verify that autocomplete text is saved for search fields.
150TEST_F(AutocompleteHistoryManagerTest, SearchField) {
151  FormData form;
152  form.name = ASCIIToUTF16("MyForm");
153  form.origin = GURL("http://myform.com/form.html");
154  form.action = GURL("http://myform.com/submit.html");
155  form.user_submitted = true;
156
157  // Search field.
158  FormFieldData search_field;
159  search_field.label = ASCIIToUTF16("Search");
160  search_field.name = ASCIIToUTF16("search");
161  search_field.value = ASCIIToUTF16("my favorite query");
162  search_field.form_control_type = "search";
163  form.fields.push_back(search_field);
164
165  EXPECT_CALL(*(web_data_service_.get()), AddFormFields(_)).Times(1);
166  autocomplete_manager_->OnFormSubmitted(form);
167}
168
169namespace {
170
171class MockAutofillExternalDelegate : public AutofillExternalDelegate {
172 public:
173  MockAutofillExternalDelegate(AutofillManager* autofill_manager,
174                               AutofillDriver* autofill_driver)
175      : AutofillExternalDelegate(autofill_manager, autofill_driver) {}
176  virtual ~MockAutofillExternalDelegate() {}
177
178  MOCK_METHOD5(OnSuggestionsReturned,
179               void(int query_id,
180                    const std::vector<base::string16>& autofill_values,
181                    const std::vector<base::string16>& autofill_labels,
182                    const std::vector<base::string16>& autofill_icons,
183                    const std::vector<int>& autofill_unique_ids));
184
185 private:
186  DISALLOW_COPY_AND_ASSIGN(MockAutofillExternalDelegate);
187};
188
189class TestAutocompleteHistoryManager : public AutocompleteHistoryManager {
190 public:
191  TestAutocompleteHistoryManager(AutofillDriver* driver, AutofillClient* client)
192      : AutocompleteHistoryManager(driver, client) {}
193
194  using AutocompleteHistoryManager::SendSuggestions;
195};
196
197}  // namespace
198
199// Make sure our external delegate is called at the right time.
200TEST_F(AutocompleteHistoryManagerTest, ExternalDelegate) {
201  TestAutocompleteHistoryManager autocomplete_history_manager(
202      autofill_driver_.get(), autofill_client_.get());
203
204  scoped_ptr<AutofillManager> autofill_manager(
205      new AutofillManager(autofill_driver_.get(),
206                          autofill_client_.get(),
207                          "en-US",
208                          AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER));
209
210  MockAutofillExternalDelegate external_delegate(autofill_manager.get(),
211                                                 autofill_driver_.get());
212  autocomplete_history_manager.SetExternalDelegate(&external_delegate);
213
214  // Should trigger a call to OnSuggestionsReturned, verified by the mock.
215  EXPECT_CALL(external_delegate, OnSuggestionsReturned(_, _, _, _, _));
216  autocomplete_history_manager.SendSuggestions(NULL);
217}
218
219// Verify that no autocomplete suggestion is returned for textarea.
220TEST_F(AutocompleteHistoryManagerTest, NoAutocompleteSuggestionsForTextarea) {
221  TestAutocompleteHistoryManager autocomplete_history_manager(
222      autofill_driver_.get(), autofill_client_.get());
223
224  scoped_ptr<AutofillManager> autofill_manager(
225      new AutofillManager(autofill_driver_.get(),
226                          autofill_client_.get(),
227                          "en-US",
228                          AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER));
229
230  MockAutofillExternalDelegate external_delegate(autofill_manager.get(),
231                                                 autofill_driver_.get());
232  autocomplete_history_manager.SetExternalDelegate(&external_delegate);
233
234  FormData form;
235  form.name = ASCIIToUTF16("MyForm");
236  form.origin = GURL("http://myform.com/form.html");
237  form.action = GURL("http://myform.com/submit.html");
238  form.user_submitted = true;
239
240  FormFieldData field;
241  test::CreateTestFormField("Address", "address", "", "textarea", &field);
242
243  EXPECT_CALL(external_delegate,
244              OnSuggestionsReturned(0,
245                                    std::vector<base::string16>(),
246                                    std::vector<base::string16>(),
247                                    std::vector<base::string16>(),
248                                    std::vector<int>()));
249  autocomplete_history_manager.OnGetAutocompleteSuggestions(
250      0,
251      field.name,
252      field.value,
253      field.form_control_type,
254      std::vector<base::string16>(),
255      std::vector<base::string16>(),
256      std::vector<base::string16>(),
257      std::vector<int>());
258}
259
260}  // namespace autofill
261