1 // Copyright 2014 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.
5 #include "components/autofill/core/browser/autofill_download_manager.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/test/histogram_tester.h"
13 #include "base/test/test_timeouts.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "components/autofill/core/browser/autofill_field.h"
16 #include "components/autofill/core/browser/autofill_metrics.h"
17 #include "components/autofill/core/browser/autofill_test_utils.h"
18 #include "components/autofill/core/browser/autofill_type.h"
19 #include "components/autofill/core/browser/form_structure.h"
20 #include "components/autofill/core/browser/test_autofill_driver.h"
21 #include "components/autofill/core/common/form_data.h"
22 #include "net/url_request/test_url_fetcher_factory.h"
23 #include "net/url_request/url_request_status.h"
24 #include "net/url_request/url_request_test_util.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 using base::ASCIIToUTF16
;
34 // Call |fetcher->OnURLFetchComplete()| as the URLFetcher would when
35 // a response is received. Params allow caller to set fake status.
36 void FakeOnURLFetchComplete(net::TestURLFetcher
* fetcher
,
38 const std::string
& response_body
) {
39 fetcher
->set_url(GURL());
40 fetcher
->set_status(net::URLRequestStatus());
41 fetcher
->set_response_code(response_code
);
42 fetcher
->SetResponseString(response_body
);
44 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
49 // This tests AutofillDownloadManager. AutofillDownloadTest implements
50 // AutofillDownloadManager::Observer and creates an instance of
51 // AutofillDownloadManager. Then it records responses to different initiated
52 // requests, which are verified later. To mock network requests
53 // TestURLFetcherFactory is used, which creates URLFetchers that do not
54 // go over the wire, but allow calling back HTTP responses directly.
55 // The responses in test are out of order and verify: successful query request,
56 // successful upload request, failed upload request.
57 class AutofillDownloadTest
: public AutofillDownloadManager::Observer
,
58 public testing::Test
{
60 AutofillDownloadTest()
61 : prefs_(test::PrefServiceForTesting()),
62 request_context_(new net::TestURLRequestContextGetter(
63 base::ThreadTaskRunnerHandle::Get())),
64 download_manager_(&driver_
, prefs_
.get(), this) {
65 driver_
.SetURLRequestContext(request_context_
.get());
68 void LimitCache(size_t cache_size
) {
69 download_manager_
.set_max_form_cache_size(cache_size
);
72 // AutofillDownloadManager::Observer implementation.
73 void OnLoadedServerPredictions(const std::string
& response_xml
) override
{
74 ResponseData response
;
75 response
.response
= response_xml
;
76 response
.type_of_response
= QUERY_SUCCESSFULL
;
77 responses_
.push_back(response
);
80 void OnUploadedPossibleFieldTypes() override
{
81 ResponseData response
;
82 response
.type_of_response
= UPLOAD_SUCCESSFULL
;
83 responses_
.push_back(response
);
86 void OnServerRequestError(const std::string
& form_signature
,
87 AutofillDownloadManager::RequestType request_type
,
88 int http_error
) override
{
89 ResponseData response
;
90 response
.signature
= form_signature
;
91 response
.error
= http_error
;
92 response
.type_of_response
=
93 request_type
== AutofillDownloadManager::REQUEST_QUERY
?
94 REQUEST_QUERY_FAILED
: REQUEST_UPLOAD_FAILED
;
95 responses_
.push_back(response
);
101 REQUEST_QUERY_FAILED
,
102 REQUEST_UPLOAD_FAILED
,
105 struct ResponseData
{
106 ResponseType type_of_response
;
108 std::string signature
;
109 std::string response
;
111 ResponseData() : type_of_response(REQUEST_QUERY_FAILED
), error(0) {}
114 base::MessageLoop message_loop_
;
115 std::list
<ResponseData
> responses_
;
116 scoped_ptr
<PrefService
> prefs_
;
117 scoped_refptr
<net::TestURLRequestContextGetter
> request_context_
;
118 TestAutofillDriver driver_
;
119 AutofillDownloadManager download_manager_
;
122 TEST_F(AutofillDownloadTest
, QueryAndUploadTest
) {
123 // Create and register factory.
124 net::TestURLFetcherFactory factory
;
129 field
.label
= ASCIIToUTF16("username");
130 field
.name
= ASCIIToUTF16("username");
131 field
.form_control_type
= "text";
132 form
.fields
.push_back(field
);
134 field
.label
= ASCIIToUTF16("First Name");
135 field
.name
= ASCIIToUTF16("firstname");
136 field
.form_control_type
= "text";
137 form
.fields
.push_back(field
);
139 field
.label
= ASCIIToUTF16("Last Name");
140 field
.name
= ASCIIToUTF16("lastname");
141 field
.form_control_type
= "text";
142 form
.fields
.push_back(field
);
144 field
.label
= ASCIIToUTF16("email");
145 field
.name
= ASCIIToUTF16("email");
146 field
.form_control_type
= "text";
147 form
.fields
.push_back(field
);
149 field
.label
= ASCIIToUTF16("email2");
150 field
.name
= ASCIIToUTF16("email2");
151 field
.form_control_type
= "text";
152 form
.fields
.push_back(field
);
154 field
.label
= ASCIIToUTF16("password");
155 field
.name
= ASCIIToUTF16("password");
156 field
.form_control_type
= "password";
157 form
.fields
.push_back(field
);
159 field
.label
= base::string16();
160 field
.name
= ASCIIToUTF16("Submit");
161 field
.form_control_type
= "submit";
162 form
.fields
.push_back(field
);
164 FormStructure
*form_structure
= new FormStructure(form
);
165 ScopedVector
<FormStructure
> form_structures
;
166 form_structures
.push_back(form_structure
);
170 field
.label
= ASCIIToUTF16("address");
171 field
.name
= ASCIIToUTF16("address");
172 field
.form_control_type
= "text";
173 form
.fields
.push_back(field
);
175 field
.label
= ASCIIToUTF16("address2");
176 field
.name
= ASCIIToUTF16("address2");
177 field
.form_control_type
= "text";
178 form
.fields
.push_back(field
);
180 field
.label
= ASCIIToUTF16("city");
181 field
.name
= ASCIIToUTF16("city");
182 field
.form_control_type
= "text";
183 form
.fields
.push_back(field
);
185 field
.label
= base::string16();
186 field
.name
= ASCIIToUTF16("Submit");
187 field
.form_control_type
= "submit";
188 form
.fields
.push_back(field
);
190 form_structure
= new FormStructure(form
);
191 form_structures
.push_back(form_structure
);
195 field
.label
= ASCIIToUTF16("username");
196 field
.name
= ASCIIToUTF16("username");
197 field
.form_control_type
= "text";
198 form
.fields
.push_back(field
);
200 field
.label
= ASCIIToUTF16("password");
201 field
.name
= ASCIIToUTF16("password");
202 field
.form_control_type
= "password";
203 form
.fields
.push_back(field
);
205 field
.label
= base::string16();
206 field
.name
= ASCIIToUTF16("Submit");
207 field
.form_control_type
= "submit";
208 form
.fields
.push_back(field
);
210 form_structure
= new FormStructure(form
);
211 form_structures
.push_back(form_structure
);
213 // Request with id 0.
214 base::HistogramTester histogram
;
215 EXPECT_TRUE(download_manager_
.StartQueryRequest(form_structures
.get()));
216 histogram
.ExpectUniqueSample("Autofill.ServerQueryResponse",
217 AutofillMetrics::QUERY_SENT
, 1);
219 // Set upload to 100% so requests happen.
220 download_manager_
.SetPositiveUploadRate(1.0);
221 download_manager_
.SetNegativeUploadRate(1.0);
222 // Request with id 1.
223 EXPECT_TRUE(download_manager_
.StartUploadRequest(
224 *(form_structures
[0]), true, ServerFieldTypeSet(), std::string()));
225 // Request with id 2.
226 EXPECT_TRUE(download_manager_
.StartUploadRequest(
227 *(form_structures
[1]), false, ServerFieldTypeSet(), std::string()));
228 // Request with id 3. Upload request with a non-empty additional password form
230 EXPECT_TRUE(download_manager_
.StartUploadRequest(*(form_structures
[2]), false,
231 ServerFieldTypeSet(), "42"));
233 const char *responses
[] = {
234 "<autofillqueryresponse>"
235 "<field autofilltype=\"0\" />"
236 "<field autofilltype=\"3\" />"
237 "<field autofilltype=\"5\" />"
238 "<field autofilltype=\"9\" />"
239 "<field autofilltype=\"0\" />"
240 "<field autofilltype=\"30\" />"
241 "<field autofilltype=\"31\" />"
242 "<field autofilltype=\"33\" />"
243 "</autofillqueryresponse>",
244 "<autofilluploadresponse positiveuploadrate=\"0.5\" "
245 "negativeuploadrate=\"0.3\"/>",
249 // Return them out of sequence.
250 net::TestURLFetcher
* fetcher
= factory
.GetFetcherByID(1);
251 ASSERT_TRUE(fetcher
);
252 FakeOnURLFetchComplete(fetcher
, 200, std::string(responses
[1]));
254 // After that upload rates would be adjusted to 0.5/0.3
255 EXPECT_DOUBLE_EQ(0.5, download_manager_
.GetPositiveUploadRate());
256 EXPECT_DOUBLE_EQ(0.3, download_manager_
.GetNegativeUploadRate());
258 fetcher
= factory
.GetFetcherByID(2);
259 ASSERT_TRUE(fetcher
);
260 FakeOnURLFetchComplete(fetcher
, 404, std::string(responses
[2]));
262 fetcher
= factory
.GetFetcherByID(0);
263 ASSERT_TRUE(fetcher
);
264 FakeOnURLFetchComplete(fetcher
, 200, std::string(responses
[0]));
265 EXPECT_EQ(3U, responses_
.size());
267 EXPECT_EQ(AutofillDownloadTest::UPLOAD_SUCCESSFULL
,
268 responses_
.front().type_of_response
);
269 EXPECT_EQ(0, responses_
.front().error
);
270 EXPECT_EQ(std::string(), responses_
.front().signature
);
271 // Expected response on non-query request is an empty string.
272 EXPECT_EQ(std::string(), responses_
.front().response
);
273 responses_
.pop_front();
275 EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED
,
276 responses_
.front().type_of_response
);
277 EXPECT_EQ(404, responses_
.front().error
);
278 EXPECT_EQ(form_structures
[1]->FormSignature(),
279 responses_
.front().signature
);
280 // Expected response on non-query request is an empty string.
281 EXPECT_EQ(std::string(), responses_
.front().response
);
282 responses_
.pop_front();
284 EXPECT_EQ(responses_
.front().type_of_response
,
285 AutofillDownloadTest::QUERY_SUCCESSFULL
);
286 EXPECT_EQ(0, responses_
.front().error
);
287 EXPECT_EQ(std::string(), responses_
.front().signature
);
288 EXPECT_EQ(responses
[0], responses_
.front().response
);
289 responses_
.pop_front();
291 // Set upload to 0% so no new requests happen.
292 download_manager_
.SetPositiveUploadRate(0.0);
293 download_manager_
.SetNegativeUploadRate(0.0);
294 // No actual requests for the next two calls, as we set upload rate to 0%.
295 EXPECT_FALSE(download_manager_
.StartUploadRequest(
296 *(form_structures
[0]), true, ServerFieldTypeSet(), std::string()));
297 EXPECT_FALSE(download_manager_
.StartUploadRequest(
298 *(form_structures
[1]), false, ServerFieldTypeSet(), std::string()));
299 fetcher
= factory
.GetFetcherByID(4);
300 EXPECT_EQ(NULL
, fetcher
);
302 // Modify form structures to miss the cache.
303 field
.label
= ASCIIToUTF16("Address line 2");
304 field
.name
= ASCIIToUTF16("address2");
305 field
.form_control_type
= "text";
306 form
.fields
.push_back(field
);
307 form_structure
= new FormStructure(form
);
308 form_structures
.push_back(form_structure
);
310 // Request with id 4.
311 EXPECT_TRUE(download_manager_
.StartQueryRequest(form_structures
.get()));
312 fetcher
= factory
.GetFetcherByID(4);
313 ASSERT_TRUE(fetcher
);
314 histogram
.ExpectUniqueSample("Autofill.ServerQueryResponse",
315 AutofillMetrics::QUERY_SENT
, 2);
316 fetcher
->set_backoff_delay(TestTimeouts::action_max_timeout());
317 FakeOnURLFetchComplete(fetcher
, 500, std::string(responses
[0]));
319 EXPECT_EQ(AutofillDownloadTest::REQUEST_QUERY_FAILED
,
320 responses_
.front().type_of_response
);
321 EXPECT_EQ(500, responses_
.front().error
);
322 // Expected response on non-query request is an empty string.
323 EXPECT_EQ(std::string(), responses_
.front().response
);
324 responses_
.pop_front();
326 // Query requests should be ignored for the next 10 seconds.
327 EXPECT_FALSE(download_manager_
.StartQueryRequest(form_structures
.get()));
328 fetcher
= factory
.GetFetcherByID(5);
329 EXPECT_EQ(NULL
, fetcher
);
330 histogram
.ExpectUniqueSample("Autofill.ServerQueryResponse",
331 AutofillMetrics::QUERY_SENT
, 2);
333 // Set upload required to true so requests happen.
334 form_structures
[0]->upload_required_
= UPLOAD_REQUIRED
;
335 // Request with id 4.
336 EXPECT_TRUE(download_manager_
.StartUploadRequest(
337 *(form_structures
[0]), true, ServerFieldTypeSet(), std::string()));
338 fetcher
= factory
.GetFetcherByID(5);
339 ASSERT_TRUE(fetcher
);
340 fetcher
->set_backoff_delay(TestTimeouts::action_max_timeout());
341 FakeOnURLFetchComplete(fetcher
, 503, std::string(responses
[2]));
342 EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED
,
343 responses_
.front().type_of_response
);
344 EXPECT_EQ(503, responses_
.front().error
);
345 responses_
.pop_front();
347 // Upload requests should be ignored for the next 10 seconds.
348 EXPECT_FALSE(download_manager_
.StartUploadRequest(
349 *(form_structures
[0]), true, ServerFieldTypeSet(), std::string()));
350 fetcher
= factory
.GetFetcherByID(6);
351 EXPECT_EQ(NULL
, fetcher
);
354 TEST_F(AutofillDownloadTest
, CacheQueryTest
) {
355 // Create and register factory.
356 net::TestURLFetcherFactory factory
;
361 field
.form_control_type
= "text";
363 field
.label
= ASCIIToUTF16("username");
364 field
.name
= ASCIIToUTF16("username");
365 form
.fields
.push_back(field
);
367 field
.label
= ASCIIToUTF16("First Name");
368 field
.name
= ASCIIToUTF16("firstname");
369 form
.fields
.push_back(field
);
371 field
.label
= ASCIIToUTF16("Last Name");
372 field
.name
= ASCIIToUTF16("lastname");
373 form
.fields
.push_back(field
);
375 FormStructure
*form_structure
= new FormStructure(form
);
376 ScopedVector
<FormStructure
> form_structures0
;
377 form_structures0
.push_back(form_structure
);
379 // Add a slightly different form, which should result in a different request.
380 field
.label
= ASCIIToUTF16("email");
381 field
.name
= ASCIIToUTF16("email");
382 form
.fields
.push_back(field
);
383 form_structure
= new FormStructure(form
);
384 ScopedVector
<FormStructure
> form_structures1
;
385 form_structures1
.push_back(form_structure
);
387 // Add another slightly different form, which should also result in a
388 // different request.
389 field
.label
= ASCIIToUTF16("email2");
390 field
.name
= ASCIIToUTF16("email2");
391 form
.fields
.push_back(field
);
392 form_structure
= new FormStructure(form
);
393 ScopedVector
<FormStructure
> form_structures2
;
394 form_structures2
.push_back(form_structure
);
396 // Limit cache to two forms.
399 const char *responses
[] = {
400 "<autofillqueryresponse>"
401 "<field autofilltype=\"0\" />"
402 "<field autofilltype=\"3\" />"
403 "<field autofilltype=\"5\" />"
404 "</autofillqueryresponse>",
405 "<autofillqueryresponse>"
406 "<field autofilltype=\"0\" />"
407 "<field autofilltype=\"3\" />"
408 "<field autofilltype=\"5\" />"
409 "<field autofilltype=\"9\" />"
410 "</autofillqueryresponse>",
411 "<autofillqueryresponse>"
412 "<field autofilltype=\"0\" />"
413 "<field autofilltype=\"3\" />"
414 "<field autofilltype=\"5\" />"
415 "<field autofilltype=\"9\" />"
416 "<field autofilltype=\"0\" />"
417 "</autofillqueryresponse>",
420 base::HistogramTester histogram
;
421 // Request with id 0.
422 EXPECT_TRUE(download_manager_
.StartQueryRequest(form_structures0
.get()));
423 histogram
.ExpectUniqueSample("Autofill.ServerQueryResponse",
424 AutofillMetrics::QUERY_SENT
, 1);
427 EXPECT_EQ(0U, responses_
.size());
429 net::TestURLFetcher
* fetcher
= factory
.GetFetcherByID(0);
430 ASSERT_TRUE(fetcher
);
431 FakeOnURLFetchComplete(fetcher
, 200, std::string(responses
[0]));
432 ASSERT_EQ(1U, responses_
.size());
433 EXPECT_EQ(responses
[0], responses_
.front().response
);
437 // No actual request - should be a cache hit.
438 EXPECT_TRUE(download_manager_
.StartQueryRequest(form_structures0
.get()));
439 histogram
.ExpectUniqueSample("Autofill.ServerQueryResponse",
440 AutofillMetrics::QUERY_SENT
, 2);
441 // Data is available immediately from cache - no over-the-wire trip.
442 ASSERT_EQ(1U, responses_
.size());
443 EXPECT_EQ(responses
[0], responses_
.front().response
);
446 // Request with id 1.
447 EXPECT_TRUE(download_manager_
.StartQueryRequest(form_structures1
.get()));
448 histogram
.ExpectUniqueSample("Autofill.ServerQueryResponse",
449 AutofillMetrics::QUERY_SENT
, 3);
451 EXPECT_EQ(0U, responses_
.size());
453 fetcher
= factory
.GetFetcherByID(1);
454 ASSERT_TRUE(fetcher
);
455 FakeOnURLFetchComplete(fetcher
, 200, std::string(responses
[1]));
456 ASSERT_EQ(1U, responses_
.size());
457 EXPECT_EQ(responses
[1], responses_
.front().response
);
461 // Request with id 2.
462 EXPECT_TRUE(download_manager_
.StartQueryRequest(form_structures2
.get()));
463 histogram
.ExpectUniqueSample("Autofill.ServerQueryResponse",
464 AutofillMetrics::QUERY_SENT
, 4);
466 fetcher
= factory
.GetFetcherByID(2);
467 ASSERT_TRUE(fetcher
);
468 FakeOnURLFetchComplete(fetcher
, 200, std::string(responses
[2]));
469 ASSERT_EQ(1U, responses_
.size());
470 EXPECT_EQ(responses
[2], responses_
.front().response
);
474 // No actual requests - should be a cache hit.
475 EXPECT_TRUE(download_manager_
.StartQueryRequest(form_structures1
.get()));
476 histogram
.ExpectUniqueSample("Autofill.ServerQueryResponse",
477 AutofillMetrics::QUERY_SENT
, 5);
479 EXPECT_TRUE(download_manager_
.StartQueryRequest(form_structures2
.get()));
480 histogram
.ExpectUniqueSample("Autofill.ServerQueryResponse",
481 AutofillMetrics::QUERY_SENT
, 6);
483 ASSERT_EQ(2U, responses_
.size());
484 EXPECT_EQ(responses
[1], responses_
.front().response
);
485 EXPECT_EQ(responses
[2], responses_
.back().response
);
488 // The first structure should've expired.
489 // Request with id 3.
490 EXPECT_TRUE(download_manager_
.StartQueryRequest(form_structures0
.get()));
491 histogram
.ExpectUniqueSample("Autofill.ServerQueryResponse",
492 AutofillMetrics::QUERY_SENT
, 7);
494 EXPECT_EQ(0U, responses_
.size());
496 fetcher
= factory
.GetFetcherByID(3);
497 ASSERT_TRUE(fetcher
);
498 FakeOnURLFetchComplete(fetcher
, 200, std::string(responses
[0]));
499 ASSERT_EQ(1U, responses_
.size());
500 EXPECT_EQ(responses
[0], responses_
.front().response
);
503 } // namespace autofill