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/message_loop/message_loop.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/test/test_timeouts.h"
14 #include "components/autofill/core/browser/autofill_field.h"
15 #include "components/autofill/core/browser/autofill_metrics.h"
16 #include "components/autofill/core/browser/autofill_test_utils.h"
17 #include "components/autofill/core/browser/autofill_type.h"
18 #include "components/autofill/core/browser/form_structure.h"
19 #include "components/autofill/core/browser/test_autofill_driver.h"
20 #include "components/autofill/core/common/form_data.h"
21 #include "net/url_request/test_url_fetcher_factory.h"
22 #include "net/url_request/url_request_status.h"
23 #include "net/url_request/url_request_test_util.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 using base::ASCIIToUTF16;
33 class MockAutofillMetrics : public AutofillMetrics {
35 MockAutofillMetrics() {}
36 MOCK_CONST_METHOD1(LogServerQueryMetric, void(ServerQueryMetric metric));
39 DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
42 // Call |fetcher->OnURLFetchComplete()| as the URLFetcher would when
43 // a response is received. Params allow caller to set fake status.
44 void FakeOnURLFetchComplete(net::TestURLFetcher* fetcher,
46 const std::string& response_body) {
47 fetcher->set_url(GURL());
48 fetcher->set_status(net::URLRequestStatus());
49 fetcher->set_response_code(response_code);
50 fetcher->SetResponseString(response_body);
52 fetcher->delegate()->OnURLFetchComplete(fetcher);
57 // This tests AutofillDownloadManager. AutofillDownloadTest implements
58 // AutofillDownloadManager::Observer and creates an instance of
59 // AutofillDownloadManager. Then it records responses to different initiated
60 // requests, which are verified later. To mock network requests
61 // TestURLFetcherFactory is used, which creates URLFetchers that do not
62 // go over the wire, but allow calling back HTTP responses directly.
63 // The responses in test are out of order and verify: successful query request,
64 // successful upload request, failed upload request.
65 class AutofillDownloadTest : public AutofillDownloadManager::Observer,
66 public testing::Test {
68 AutofillDownloadTest()
69 : prefs_(test::PrefServiceForTesting()),
70 request_context_(new net::TestURLRequestContextGetter(
71 base::MessageLoopProxy::current())),
72 download_manager_(&driver_, prefs_.get(), this) {
73 driver_.SetURLRequestContext(request_context_.get());
76 void LimitCache(size_t cache_size) {
77 download_manager_.set_max_form_cache_size(cache_size);
80 // AutofillDownloadManager::Observer implementation.
81 void OnLoadedServerPredictions(const std::string& response_xml) override {
82 ResponseData response;
83 response.response = response_xml;
84 response.type_of_response = QUERY_SUCCESSFULL;
85 responses_.push_back(response);
88 void OnUploadedPossibleFieldTypes() override {
89 ResponseData response;
90 response.type_of_response = UPLOAD_SUCCESSFULL;
91 responses_.push_back(response);
94 void OnServerRequestError(const std::string& form_signature,
95 AutofillDownloadManager::RequestType request_type,
96 int http_error) override {
97 ResponseData response;
98 response.signature = form_signature;
99 response.error = http_error;
100 response.type_of_response =
101 request_type == AutofillDownloadManager::REQUEST_QUERY ?
102 REQUEST_QUERY_FAILED : REQUEST_UPLOAD_FAILED;
103 responses_.push_back(response);
109 REQUEST_QUERY_FAILED,
110 REQUEST_UPLOAD_FAILED,
113 struct ResponseData {
114 ResponseType type_of_response;
116 std::string signature;
117 std::string response;
119 ResponseData() : type_of_response(REQUEST_QUERY_FAILED), error(0) {}
122 base::MessageLoop message_loop_;
123 std::list<ResponseData> responses_;
124 scoped_ptr<PrefService> prefs_;
125 scoped_refptr<net::TestURLRequestContextGetter> request_context_;
126 TestAutofillDriver driver_;
127 AutofillDownloadManager download_manager_;
130 TEST_F(AutofillDownloadTest, QueryAndUploadTest) {
131 // Create and register factory.
132 net::TestURLFetcherFactory factory;
137 field.label = ASCIIToUTF16("username");
138 field.name = ASCIIToUTF16("username");
139 field.form_control_type = "text";
140 form.fields.push_back(field);
142 field.label = ASCIIToUTF16("First Name");
143 field.name = ASCIIToUTF16("firstname");
144 field.form_control_type = "text";
145 form.fields.push_back(field);
147 field.label = ASCIIToUTF16("Last Name");
148 field.name = ASCIIToUTF16("lastname");
149 field.form_control_type = "text";
150 form.fields.push_back(field);
152 field.label = ASCIIToUTF16("email");
153 field.name = ASCIIToUTF16("email");
154 field.form_control_type = "text";
155 form.fields.push_back(field);
157 field.label = ASCIIToUTF16("email2");
158 field.name = ASCIIToUTF16("email2");
159 field.form_control_type = "text";
160 form.fields.push_back(field);
162 field.label = ASCIIToUTF16("password");
163 field.name = ASCIIToUTF16("password");
164 field.form_control_type = "password";
165 form.fields.push_back(field);
167 field.label = base::string16();
168 field.name = ASCIIToUTF16("Submit");
169 field.form_control_type = "submit";
170 form.fields.push_back(field);
172 FormStructure *form_structure = new FormStructure(form);
173 ScopedVector<FormStructure> form_structures;
174 form_structures.push_back(form_structure);
178 field.label = ASCIIToUTF16("address");
179 field.name = ASCIIToUTF16("address");
180 field.form_control_type = "text";
181 form.fields.push_back(field);
183 field.label = ASCIIToUTF16("address2");
184 field.name = ASCIIToUTF16("address2");
185 field.form_control_type = "text";
186 form.fields.push_back(field);
188 field.label = ASCIIToUTF16("city");
189 field.name = ASCIIToUTF16("city");
190 field.form_control_type = "text";
191 form.fields.push_back(field);
193 field.label = base::string16();
194 field.name = ASCIIToUTF16("Submit");
195 field.form_control_type = "submit";
196 form.fields.push_back(field);
198 form_structure = new FormStructure(form);
199 form_structures.push_back(form_structure);
201 // Request with id 0.
202 MockAutofillMetrics mock_metric_logger;
203 EXPECT_CALL(mock_metric_logger,
204 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
205 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get(),
206 mock_metric_logger));
207 // Set upload to 100% so requests happen.
208 download_manager_.SetPositiveUploadRate(1.0);
209 download_manager_.SetNegativeUploadRate(1.0);
210 // Request with id 1.
211 EXPECT_TRUE(download_manager_.StartUploadRequest(
212 *(form_structures[0]), true, ServerFieldTypeSet()));
213 // Request with id 2.
214 EXPECT_TRUE(download_manager_.StartUploadRequest(
215 *(form_structures[1]), false, ServerFieldTypeSet()));
217 const char *responses[] = {
218 "<autofillqueryresponse>"
219 "<field autofilltype=\"0\" />"
220 "<field autofilltype=\"3\" />"
221 "<field autofilltype=\"5\" />"
222 "<field autofilltype=\"9\" />"
223 "<field autofilltype=\"0\" />"
224 "<field autofilltype=\"30\" />"
225 "<field autofilltype=\"31\" />"
226 "<field autofilltype=\"33\" />"
227 "</autofillqueryresponse>",
228 "<autofilluploadresponse positiveuploadrate=\"0.5\" "
229 "negativeuploadrate=\"0.3\"/>",
233 // Return them out of sequence.
234 net::TestURLFetcher* fetcher = factory.GetFetcherByID(1);
235 ASSERT_TRUE(fetcher);
236 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1]));
238 // After that upload rates would be adjusted to 0.5/0.3
239 EXPECT_DOUBLE_EQ(0.5, download_manager_.GetPositiveUploadRate());
240 EXPECT_DOUBLE_EQ(0.3, download_manager_.GetNegativeUploadRate());
242 fetcher = factory.GetFetcherByID(2);
243 ASSERT_TRUE(fetcher);
244 FakeOnURLFetchComplete(fetcher, 404, std::string(responses[2]));
246 fetcher = factory.GetFetcherByID(0);
247 ASSERT_TRUE(fetcher);
248 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
249 EXPECT_EQ(static_cast<size_t>(3), responses_.size());
251 EXPECT_EQ(AutofillDownloadTest::UPLOAD_SUCCESSFULL,
252 responses_.front().type_of_response);
253 EXPECT_EQ(0, responses_.front().error);
254 EXPECT_EQ(std::string(), responses_.front().signature);
255 // Expected response on non-query request is an empty string.
256 EXPECT_EQ(std::string(), responses_.front().response);
257 responses_.pop_front();
259 EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED,
260 responses_.front().type_of_response);
261 EXPECT_EQ(404, responses_.front().error);
262 EXPECT_EQ(form_structures[1]->FormSignature(),
263 responses_.front().signature);
264 // Expected response on non-query request is an empty string.
265 EXPECT_EQ(std::string(), responses_.front().response);
266 responses_.pop_front();
268 EXPECT_EQ(responses_.front().type_of_response,
269 AutofillDownloadTest::QUERY_SUCCESSFULL);
270 EXPECT_EQ(0, responses_.front().error);
271 EXPECT_EQ(std::string(), responses_.front().signature);
272 EXPECT_EQ(responses[0], responses_.front().response);
273 responses_.pop_front();
275 // Set upload to 0% so no new requests happen.
276 download_manager_.SetPositiveUploadRate(0.0);
277 download_manager_.SetNegativeUploadRate(0.0);
278 // No actual requests for the next two calls, as we set upload rate to 0%.
279 EXPECT_FALSE(download_manager_.StartUploadRequest(
280 *(form_structures[0]), true, ServerFieldTypeSet()));
281 EXPECT_FALSE(download_manager_.StartUploadRequest(
282 *(form_structures[1]), false, ServerFieldTypeSet()));
283 fetcher = factory.GetFetcherByID(3);
284 EXPECT_EQ(NULL, fetcher);
286 // Modify form structures to miss the cache.
287 field.label = ASCIIToUTF16("Address line 2");
288 field.name = ASCIIToUTF16("address2");
289 field.form_control_type = "text";
290 form.fields.push_back(field);
291 form_structure = new FormStructure(form);
292 form_structures.push_back(form_structure);
294 // Request with id 3.
295 EXPECT_CALL(mock_metric_logger,
296 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
297 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get(),
298 mock_metric_logger));
299 fetcher = factory.GetFetcherByID(3);
300 ASSERT_TRUE(fetcher);
301 fetcher->set_backoff_delay(TestTimeouts::action_max_timeout());
302 FakeOnURLFetchComplete(fetcher, 500, std::string(responses[0]));
304 EXPECT_EQ(AutofillDownloadTest::REQUEST_QUERY_FAILED,
305 responses_.front().type_of_response);
306 EXPECT_EQ(500, responses_.front().error);
307 // Expected response on non-query request is an empty string.
308 EXPECT_EQ(std::string(), responses_.front().response);
309 responses_.pop_front();
311 // Query requests should be ignored for the next 10 seconds.
312 EXPECT_CALL(mock_metric_logger,
313 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(0);
314 EXPECT_FALSE(download_manager_.StartQueryRequest(form_structures.get(),
315 mock_metric_logger));
316 fetcher = factory.GetFetcherByID(4);
317 EXPECT_EQ(NULL, fetcher);
319 // Set upload required to true so requests happen.
320 form_structures[0]->upload_required_ = UPLOAD_REQUIRED;
321 // Request with id 4.
322 EXPECT_TRUE(download_manager_.StartUploadRequest(
323 *(form_structures[0]), true, ServerFieldTypeSet()));
324 fetcher = factory.GetFetcherByID(4);
325 ASSERT_TRUE(fetcher);
326 fetcher->set_backoff_delay(TestTimeouts::action_max_timeout());
327 FakeOnURLFetchComplete(fetcher, 503, std::string(responses[2]));
328 EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED,
329 responses_.front().type_of_response);
330 EXPECT_EQ(503, responses_.front().error);
331 responses_.pop_front();
333 // Upload requests should be ignored for the next 10 seconds.
334 EXPECT_FALSE(download_manager_.StartUploadRequest(
335 *(form_structures[0]), true, ServerFieldTypeSet()));
336 fetcher = factory.GetFetcherByID(5);
337 EXPECT_EQ(NULL, fetcher);
340 TEST_F(AutofillDownloadTest, CacheQueryTest) {
341 // Create and register factory.
342 net::TestURLFetcherFactory factory;
347 field.form_control_type = "text";
349 field.label = ASCIIToUTF16("username");
350 field.name = ASCIIToUTF16("username");
351 form.fields.push_back(field);
353 field.label = ASCIIToUTF16("First Name");
354 field.name = ASCIIToUTF16("firstname");
355 form.fields.push_back(field);
357 field.label = ASCIIToUTF16("Last Name");
358 field.name = ASCIIToUTF16("lastname");
359 form.fields.push_back(field);
361 FormStructure *form_structure = new FormStructure(form);
362 ScopedVector<FormStructure> form_structures0;
363 form_structures0.push_back(form_structure);
365 // Add a slightly different form, which should result in a different request.
366 field.label = ASCIIToUTF16("email");
367 field.name = ASCIIToUTF16("email");
368 form.fields.push_back(field);
369 form_structure = new FormStructure(form);
370 ScopedVector<FormStructure> form_structures1;
371 form_structures1.push_back(form_structure);
373 // Add another slightly different form, which should also result in a
374 // different request.
375 field.label = ASCIIToUTF16("email2");
376 field.name = ASCIIToUTF16("email2");
377 form.fields.push_back(field);
378 form_structure = new FormStructure(form);
379 ScopedVector<FormStructure> form_structures2;
380 form_structures2.push_back(form_structure);
382 // Limit cache to two forms.
385 const char *responses[] = {
386 "<autofillqueryresponse>"
387 "<field autofilltype=\"0\" />"
388 "<field autofilltype=\"3\" />"
389 "<field autofilltype=\"5\" />"
390 "</autofillqueryresponse>",
391 "<autofillqueryresponse>"
392 "<field autofilltype=\"0\" />"
393 "<field autofilltype=\"3\" />"
394 "<field autofilltype=\"5\" />"
395 "<field autofilltype=\"9\" />"
396 "</autofillqueryresponse>",
397 "<autofillqueryresponse>"
398 "<field autofilltype=\"0\" />"
399 "<field autofilltype=\"3\" />"
400 "<field autofilltype=\"5\" />"
401 "<field autofilltype=\"9\" />"
402 "<field autofilltype=\"0\" />"
403 "</autofillqueryresponse>",
406 // Request with id 0.
407 MockAutofillMetrics mock_metric_logger;
408 EXPECT_CALL(mock_metric_logger,
409 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
410 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
411 mock_metric_logger));
413 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
415 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
416 ASSERT_TRUE(fetcher);
417 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
418 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
419 EXPECT_EQ(responses[0], responses_.front().response);
423 // No actual request - should be a cache hit.
424 EXPECT_CALL(mock_metric_logger,
425 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
426 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
427 mock_metric_logger));
428 // Data is available immediately from cache - no over-the-wire trip.
429 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
430 EXPECT_EQ(responses[0], responses_.front().response);
433 // Request with id 1.
434 EXPECT_CALL(mock_metric_logger,
435 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
436 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(),
437 mock_metric_logger));
439 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
441 fetcher = factory.GetFetcherByID(1);
442 ASSERT_TRUE(fetcher);
443 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1]));
444 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
445 EXPECT_EQ(responses[1], responses_.front().response);
449 // Request with id 2.
450 EXPECT_CALL(mock_metric_logger,
451 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
452 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(),
453 mock_metric_logger));
455 fetcher = factory.GetFetcherByID(2);
456 ASSERT_TRUE(fetcher);
457 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[2]));
458 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
459 EXPECT_EQ(responses[2], responses_.front().response);
463 // No actual requests - should be a cache hit.
464 EXPECT_CALL(mock_metric_logger,
465 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
466 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(),
467 mock_metric_logger));
469 EXPECT_CALL(mock_metric_logger,
470 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
471 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(),
472 mock_metric_logger));
474 ASSERT_EQ(static_cast<size_t>(2), responses_.size());
475 EXPECT_EQ(responses[1], responses_.front().response);
476 EXPECT_EQ(responses[2], responses_.back().response);
479 // The first structure should've expired.
480 // Request with id 3.
481 EXPECT_CALL(mock_metric_logger,
482 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
483 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
484 mock_metric_logger));
486 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
488 fetcher = factory.GetFetcherByID(3);
489 ASSERT_TRUE(fetcher);
490 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
491 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
492 EXPECT_EQ(responses[0], responses_.front().response);
495 } // namespace autofill