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_);
76 void LimitCache(size_t cache_size) {
77 download_manager_.set_max_form_cache_size(cache_size);
80 // AutofillDownloadManager::Observer implementation.
81 virtual void OnLoadedServerPredictions(
82 const std::string& response_xml) OVERRIDE {
83 ResponseData response;
84 response.response = response_xml;
85 response.type_of_response = QUERY_SUCCESSFULL;
86 responses_.push_back(response);
89 virtual void OnUploadedPossibleFieldTypes() OVERRIDE {
90 ResponseData response;
91 response.type_of_response = UPLOAD_SUCCESSFULL;
92 responses_.push_back(response);
95 virtual void OnServerRequestError(
96 const std::string& form_signature,
97 AutofillDownloadManager::RequestType request_type,
98 int http_error) OVERRIDE {
99 ResponseData response;
100 response.signature = form_signature;
101 response.error = http_error;
102 response.type_of_response =
103 request_type == AutofillDownloadManager::REQUEST_QUERY ?
104 REQUEST_QUERY_FAILED : REQUEST_UPLOAD_FAILED;
105 responses_.push_back(response);
111 REQUEST_QUERY_FAILED,
112 REQUEST_UPLOAD_FAILED,
115 struct ResponseData {
116 ResponseType type_of_response;
118 std::string signature;
119 std::string response;
121 ResponseData() : type_of_response(REQUEST_QUERY_FAILED), error(0) {}
124 base::MessageLoop message_loop_;
125 std::list<ResponseData> responses_;
126 scoped_ptr<PrefService> prefs_;
127 scoped_refptr<net::TestURLRequestContextGetter> request_context_;
128 TestAutofillDriver driver_;
129 AutofillDownloadManager download_manager_;
132 TEST_F(AutofillDownloadTest, QueryAndUploadTest) {
133 // Create and register factory.
134 net::TestURLFetcherFactory factory;
139 field.label = ASCIIToUTF16("username");
140 field.name = ASCIIToUTF16("username");
141 field.form_control_type = "text";
142 form.fields.push_back(field);
144 field.label = ASCIIToUTF16("First Name");
145 field.name = ASCIIToUTF16("firstname");
146 field.form_control_type = "text";
147 form.fields.push_back(field);
149 field.label = ASCIIToUTF16("Last Name");
150 field.name = ASCIIToUTF16("lastname");
151 field.form_control_type = "text";
152 form.fields.push_back(field);
154 field.label = ASCIIToUTF16("email");
155 field.name = ASCIIToUTF16("email");
156 field.form_control_type = "text";
157 form.fields.push_back(field);
159 field.label = ASCIIToUTF16("email2");
160 field.name = ASCIIToUTF16("email2");
161 field.form_control_type = "text";
162 form.fields.push_back(field);
164 field.label = ASCIIToUTF16("password");
165 field.name = ASCIIToUTF16("password");
166 field.form_control_type = "password";
167 form.fields.push_back(field);
169 field.label = base::string16();
170 field.name = ASCIIToUTF16("Submit");
171 field.form_control_type = "submit";
172 form.fields.push_back(field);
174 FormStructure *form_structure = new FormStructure(form);
175 ScopedVector<FormStructure> form_structures;
176 form_structures.push_back(form_structure);
180 field.label = ASCIIToUTF16("address");
181 field.name = ASCIIToUTF16("address");
182 field.form_control_type = "text";
183 form.fields.push_back(field);
185 field.label = ASCIIToUTF16("address2");
186 field.name = ASCIIToUTF16("address2");
187 field.form_control_type = "text";
188 form.fields.push_back(field);
190 field.label = ASCIIToUTF16("city");
191 field.name = ASCIIToUTF16("city");
192 field.form_control_type = "text";
193 form.fields.push_back(field);
195 field.label = base::string16();
196 field.name = ASCIIToUTF16("Submit");
197 field.form_control_type = "submit";
198 form.fields.push_back(field);
200 form_structure = new FormStructure(form);
201 form_structures.push_back(form_structure);
203 // Request with id 0.
204 MockAutofillMetrics mock_metric_logger;
205 EXPECT_CALL(mock_metric_logger,
206 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
207 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get(),
208 mock_metric_logger));
209 // Set upload to 100% so requests happen.
210 download_manager_.SetPositiveUploadRate(1.0);
211 download_manager_.SetNegativeUploadRate(1.0);
212 // Request with id 1.
213 EXPECT_TRUE(download_manager_.StartUploadRequest(
214 *(form_structures[0]), true, ServerFieldTypeSet()));
215 // Request with id 2.
216 EXPECT_TRUE(download_manager_.StartUploadRequest(
217 *(form_structures[1]), false, ServerFieldTypeSet()));
219 const char *responses[] = {
220 "<autofillqueryresponse>"
221 "<field autofilltype=\"0\" />"
222 "<field autofilltype=\"3\" />"
223 "<field autofilltype=\"5\" />"
224 "<field autofilltype=\"9\" />"
225 "<field autofilltype=\"0\" />"
226 "<field autofilltype=\"30\" />"
227 "<field autofilltype=\"31\" />"
228 "<field autofilltype=\"33\" />"
229 "</autofillqueryresponse>",
230 "<autofilluploadresponse positiveuploadrate=\"0.5\" "
231 "negativeuploadrate=\"0.3\"/>",
235 // Return them out of sequence.
236 net::TestURLFetcher* fetcher = factory.GetFetcherByID(1);
237 ASSERT_TRUE(fetcher);
238 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1]));
240 // After that upload rates would be adjusted to 0.5/0.3
241 EXPECT_DOUBLE_EQ(0.5, download_manager_.GetPositiveUploadRate());
242 EXPECT_DOUBLE_EQ(0.3, download_manager_.GetNegativeUploadRate());
244 fetcher = factory.GetFetcherByID(2);
245 ASSERT_TRUE(fetcher);
246 FakeOnURLFetchComplete(fetcher, 404, std::string(responses[2]));
248 fetcher = factory.GetFetcherByID(0);
249 ASSERT_TRUE(fetcher);
250 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
251 EXPECT_EQ(static_cast<size_t>(3), responses_.size());
253 EXPECT_EQ(AutofillDownloadTest::UPLOAD_SUCCESSFULL,
254 responses_.front().type_of_response);
255 EXPECT_EQ(0, responses_.front().error);
256 EXPECT_EQ(std::string(), responses_.front().signature);
257 // Expected response on non-query request is an empty string.
258 EXPECT_EQ(std::string(), responses_.front().response);
259 responses_.pop_front();
261 EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED,
262 responses_.front().type_of_response);
263 EXPECT_EQ(404, responses_.front().error);
264 EXPECT_EQ(form_structures[1]->FormSignature(),
265 responses_.front().signature);
266 // Expected response on non-query request is an empty string.
267 EXPECT_EQ(std::string(), responses_.front().response);
268 responses_.pop_front();
270 EXPECT_EQ(responses_.front().type_of_response,
271 AutofillDownloadTest::QUERY_SUCCESSFULL);
272 EXPECT_EQ(0, responses_.front().error);
273 EXPECT_EQ(std::string(), responses_.front().signature);
274 EXPECT_EQ(responses[0], responses_.front().response);
275 responses_.pop_front();
277 // Set upload to 0% so no new requests happen.
278 download_manager_.SetPositiveUploadRate(0.0);
279 download_manager_.SetNegativeUploadRate(0.0);
280 // No actual requests for the next two calls, as we set upload rate to 0%.
281 EXPECT_FALSE(download_manager_.StartUploadRequest(
282 *(form_structures[0]), true, ServerFieldTypeSet()));
283 EXPECT_FALSE(download_manager_.StartUploadRequest(
284 *(form_structures[1]), false, ServerFieldTypeSet()));
285 fetcher = factory.GetFetcherByID(3);
286 EXPECT_EQ(NULL, fetcher);
288 // Modify form structures to miss the cache.
289 field.label = ASCIIToUTF16("Address line 2");
290 field.name = ASCIIToUTF16("address2");
291 field.form_control_type = "text";
292 form.fields.push_back(field);
293 form_structure = new FormStructure(form);
294 form_structures.push_back(form_structure);
296 // Request with id 3.
297 EXPECT_CALL(mock_metric_logger,
298 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
299 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get(),
300 mock_metric_logger));
301 fetcher = factory.GetFetcherByID(3);
302 ASSERT_TRUE(fetcher);
303 fetcher->set_backoff_delay(TestTimeouts::action_max_timeout());
304 FakeOnURLFetchComplete(fetcher, 500, std::string(responses[0]));
306 EXPECT_EQ(AutofillDownloadTest::REQUEST_QUERY_FAILED,
307 responses_.front().type_of_response);
308 EXPECT_EQ(500, responses_.front().error);
309 // Expected response on non-query request is an empty string.
310 EXPECT_EQ(std::string(), responses_.front().response);
311 responses_.pop_front();
313 // Query requests should be ignored for the next 10 seconds.
314 EXPECT_CALL(mock_metric_logger,
315 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(0);
316 EXPECT_FALSE(download_manager_.StartQueryRequest(form_structures.get(),
317 mock_metric_logger));
318 fetcher = factory.GetFetcherByID(4);
319 EXPECT_EQ(NULL, fetcher);
321 // Set upload required to true so requests happen.
322 form_structures[0]->upload_required_ = UPLOAD_REQUIRED;
323 // Request with id 4.
324 EXPECT_TRUE(download_manager_.StartUploadRequest(
325 *(form_structures[0]), true, ServerFieldTypeSet()));
326 fetcher = factory.GetFetcherByID(4);
327 ASSERT_TRUE(fetcher);
328 fetcher->set_backoff_delay(TestTimeouts::action_max_timeout());
329 FakeOnURLFetchComplete(fetcher, 503, std::string(responses[2]));
330 EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED,
331 responses_.front().type_of_response);
332 EXPECT_EQ(503, responses_.front().error);
333 responses_.pop_front();
335 // Upload requests should be ignored for the next 10 seconds.
336 EXPECT_FALSE(download_manager_.StartUploadRequest(
337 *(form_structures[0]), true, ServerFieldTypeSet()));
338 fetcher = factory.GetFetcherByID(5);
339 EXPECT_EQ(NULL, fetcher);
342 TEST_F(AutofillDownloadTest, CacheQueryTest) {
343 // Create and register factory.
344 net::TestURLFetcherFactory factory;
349 field.form_control_type = "text";
351 field.label = ASCIIToUTF16("username");
352 field.name = ASCIIToUTF16("username");
353 form.fields.push_back(field);
355 field.label = ASCIIToUTF16("First Name");
356 field.name = ASCIIToUTF16("firstname");
357 form.fields.push_back(field);
359 field.label = ASCIIToUTF16("Last Name");
360 field.name = ASCIIToUTF16("lastname");
361 form.fields.push_back(field);
363 FormStructure *form_structure = new FormStructure(form);
364 ScopedVector<FormStructure> form_structures0;
365 form_structures0.push_back(form_structure);
367 // Add a slightly different form, which should result in a different request.
368 field.label = ASCIIToUTF16("email");
369 field.name = ASCIIToUTF16("email");
370 form.fields.push_back(field);
371 form_structure = new FormStructure(form);
372 ScopedVector<FormStructure> form_structures1;
373 form_structures1.push_back(form_structure);
375 // Add another slightly different form, which should also result in a
376 // different request.
377 field.label = ASCIIToUTF16("email2");
378 field.name = ASCIIToUTF16("email2");
379 form.fields.push_back(field);
380 form_structure = new FormStructure(form);
381 ScopedVector<FormStructure> form_structures2;
382 form_structures2.push_back(form_structure);
384 // Limit cache to two forms.
387 const char *responses[] = {
388 "<autofillqueryresponse>"
389 "<field autofilltype=\"0\" />"
390 "<field autofilltype=\"3\" />"
391 "<field autofilltype=\"5\" />"
392 "</autofillqueryresponse>",
393 "<autofillqueryresponse>"
394 "<field autofilltype=\"0\" />"
395 "<field autofilltype=\"3\" />"
396 "<field autofilltype=\"5\" />"
397 "<field autofilltype=\"9\" />"
398 "</autofillqueryresponse>",
399 "<autofillqueryresponse>"
400 "<field autofilltype=\"0\" />"
401 "<field autofilltype=\"3\" />"
402 "<field autofilltype=\"5\" />"
403 "<field autofilltype=\"9\" />"
404 "<field autofilltype=\"0\" />"
405 "</autofillqueryresponse>",
408 // Request with id 0.
409 MockAutofillMetrics mock_metric_logger;
410 EXPECT_CALL(mock_metric_logger,
411 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
412 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
413 mock_metric_logger));
415 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
417 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
418 ASSERT_TRUE(fetcher);
419 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
420 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
421 EXPECT_EQ(responses[0], responses_.front().response);
425 // No actual request - should be a cache hit.
426 EXPECT_CALL(mock_metric_logger,
427 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
428 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
429 mock_metric_logger));
430 // Data is available immediately from cache - no over-the-wire trip.
431 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
432 EXPECT_EQ(responses[0], responses_.front().response);
435 // Request with id 1.
436 EXPECT_CALL(mock_metric_logger,
437 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
438 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(),
439 mock_metric_logger));
441 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
443 fetcher = factory.GetFetcherByID(1);
444 ASSERT_TRUE(fetcher);
445 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1]));
446 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
447 EXPECT_EQ(responses[1], responses_.front().response);
451 // Request with id 2.
452 EXPECT_CALL(mock_metric_logger,
453 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
454 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(),
455 mock_metric_logger));
457 fetcher = factory.GetFetcherByID(2);
458 ASSERT_TRUE(fetcher);
459 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[2]));
460 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
461 EXPECT_EQ(responses[2], responses_.front().response);
465 // No actual requests - should be a cache hit.
466 EXPECT_CALL(mock_metric_logger,
467 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
468 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(),
469 mock_metric_logger));
471 EXPECT_CALL(mock_metric_logger,
472 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
473 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(),
474 mock_metric_logger));
476 ASSERT_EQ(static_cast<size_t>(2), responses_.size());
477 EXPECT_EQ(responses[1], responses_.front().response);
478 EXPECT_EQ(responses[2], responses_.back().response);
481 // The first structure should've expired.
482 // Request with id 3.
483 EXPECT_CALL(mock_metric_logger,
484 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
485 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
486 mock_metric_logger));
488 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
490 fetcher = factory.GetFetcherByID(3);
491 ASSERT_TRUE(fetcher);
492 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
493 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
494 EXPECT_EQ(responses[0], responses_.front().response);
497 } // namespace autofill