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 <list>
6
7 #include "base/message_loop/message_loop.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/test/test_timeouts.h"
12 #include "components/autofill/core/browser/autofill_download.h"
13 #include "components/autofill/core/browser/autofill_field.h"
14 #include "components/autofill/core/browser/autofill_metrics.h"
15 #include "components/autofill/core/browser/autofill_test_utils.h"
16 #include "components/autofill/core/browser/autofill_type.h"
17 #include "components/autofill/core/browser/form_structure.h"
18 #include "components/autofill/core/browser/test_autofill_driver.h"
19 #include "components/autofill/core/common/form_data.h"
20 #include "net/url_request/test_url_fetcher_factory.h"
21 #include "net/url_request/url_request_status.h"
22 #include "net/url_request/url_request_test_util.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 using base::ASCIIToUTF16;
27
28 namespace autofill {
29
30 namespace {
31
32 class MockAutofillMetrics : public AutofillMetrics {
33 public:
MockAutofillMetrics()34 MockAutofillMetrics() {}
35 MOCK_CONST_METHOD1(LogServerQueryMetric, void(ServerQueryMetric metric));
36
37 private:
38 DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
39 };
40
41 // Call |fetcher->OnURLFetchComplete()| as the URLFetcher would when
42 // a response is received. Params allow caller to set fake status.
FakeOnURLFetchComplete(net::TestURLFetcher * fetcher,int response_code,const std::string & response_body)43 void FakeOnURLFetchComplete(net::TestURLFetcher* fetcher,
44 int response_code,
45 const std::string& response_body) {
46 fetcher->set_url(GURL());
47 fetcher->set_status(net::URLRequestStatus());
48 fetcher->set_response_code(response_code);
49 fetcher->SetResponseString(response_body);
50
51 fetcher->delegate()->OnURLFetchComplete(fetcher);
52 }
53
54 } // namespace
55
56 // This tests AutofillDownloadManager. AutofillDownloadTest implements
57 // AutofillDownloadManager::Observer and creates an instance of
58 // AutofillDownloadManager. Then it records responses to different initiated
59 // requests, which are verified later. To mock network requests
60 // TestURLFetcherFactory is used, which creates URLFetchers that do not
61 // go over the wire, but allow calling back HTTP responses directly.
62 // The responses in test are out of order and verify: successful query request,
63 // successful upload request, failed upload request.
64 class AutofillDownloadTest : public AutofillDownloadManager::Observer,
65 public testing::Test {
66 public:
AutofillDownloadTest()67 AutofillDownloadTest()
68 : prefs_(test::PrefServiceForTesting()),
69 request_context_(new net::TestURLRequestContextGetter(
70 base::MessageLoopProxy::current())),
71 download_manager_(&driver_, prefs_.get(), this) {
72 driver_.SetURLRequestContext(request_context_);
73 }
74
LimitCache(size_t cache_size)75 void LimitCache(size_t cache_size) {
76 download_manager_.set_max_form_cache_size(cache_size);
77 }
78
79 // AutofillDownloadManager::Observer implementation.
OnLoadedServerPredictions(const std::string & response_xml)80 virtual void OnLoadedServerPredictions(
81 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);
86 }
87
OnUploadedPossibleFieldTypes()88 virtual void OnUploadedPossibleFieldTypes() OVERRIDE {
89 ResponseData response;
90 response.type_of_response = UPLOAD_SUCCESSFULL;
91 responses_.push_back(response);
92 }
93
OnServerRequestError(const std::string & form_signature,AutofillDownloadManager::RequestType request_type,int http_error)94 virtual void OnServerRequestError(
95 const std::string& form_signature,
96 AutofillDownloadManager::RequestType request_type,
97 int http_error) OVERRIDE {
98 ResponseData response;
99 response.signature = form_signature;
100 response.error = http_error;
101 response.type_of_response =
102 request_type == AutofillDownloadManager::REQUEST_QUERY ?
103 REQUEST_QUERY_FAILED : REQUEST_UPLOAD_FAILED;
104 responses_.push_back(response);
105 }
106
107 enum ResponseType {
108 QUERY_SUCCESSFULL,
109 UPLOAD_SUCCESSFULL,
110 REQUEST_QUERY_FAILED,
111 REQUEST_UPLOAD_FAILED,
112 };
113
114 struct ResponseData {
115 ResponseType type_of_response;
116 int error;
117 std::string signature;
118 std::string response;
119
ResponseDataautofill::AutofillDownloadTest::ResponseData120 ResponseData() : type_of_response(REQUEST_QUERY_FAILED), error(0) {}
121 };
122
123 base::MessageLoop message_loop_;
124 std::list<ResponseData> responses_;
125 scoped_ptr<PrefService> prefs_;
126 scoped_refptr<net::TestURLRequestContextGetter> request_context_;
127 TestAutofillDriver driver_;
128 AutofillDownloadManager download_manager_;
129 };
130
TEST_F(AutofillDownloadTest,QueryAndUploadTest)131 TEST_F(AutofillDownloadTest, QueryAndUploadTest) {
132 // Create and register factory.
133 net::TestURLFetcherFactory factory;
134
135 FormData form;
136 form.method = ASCIIToUTF16("post");
137
138 FormFieldData field;
139 field.label = ASCIIToUTF16("username");
140 field.name = ASCIIToUTF16("username");
141 field.form_control_type = "text";
142 form.fields.push_back(field);
143
144 field.label = ASCIIToUTF16("First Name");
145 field.name = ASCIIToUTF16("firstname");
146 field.form_control_type = "text";
147 form.fields.push_back(field);
148
149 field.label = ASCIIToUTF16("Last Name");
150 field.name = ASCIIToUTF16("lastname");
151 field.form_control_type = "text";
152 form.fields.push_back(field);
153
154 field.label = ASCIIToUTF16("email");
155 field.name = ASCIIToUTF16("email");
156 field.form_control_type = "text";
157 form.fields.push_back(field);
158
159 field.label = ASCIIToUTF16("email2");
160 field.name = ASCIIToUTF16("email2");
161 field.form_control_type = "text";
162 form.fields.push_back(field);
163
164 field.label = ASCIIToUTF16("password");
165 field.name = ASCIIToUTF16("password");
166 field.form_control_type = "password";
167 form.fields.push_back(field);
168
169 field.label = base::string16();
170 field.name = ASCIIToUTF16("Submit");
171 field.form_control_type = "submit";
172 form.fields.push_back(field);
173
174 FormStructure *form_structure = new FormStructure(form);
175 ScopedVector<FormStructure> form_structures;
176 form_structures.push_back(form_structure);
177
178 form.fields.clear();
179
180 field.label = ASCIIToUTF16("address");
181 field.name = ASCIIToUTF16("address");
182 field.form_control_type = "text";
183 form.fields.push_back(field);
184
185 field.label = ASCIIToUTF16("address2");
186 field.name = ASCIIToUTF16("address2");
187 field.form_control_type = "text";
188 form.fields.push_back(field);
189
190 field.label = ASCIIToUTF16("city");
191 field.name = ASCIIToUTF16("city");
192 field.form_control_type = "text";
193 form.fields.push_back(field);
194
195 field.label = base::string16();
196 field.name = ASCIIToUTF16("Submit");
197 field.form_control_type = "submit";
198 form.fields.push_back(field);
199
200 form_structure = new FormStructure(form);
201 form_structures.push_back(form_structure);
202
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()));
218
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\"/>",
232 "<html></html>",
233 };
234
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]));
239
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());
243
244 fetcher = factory.GetFetcherByID(2);
245 ASSERT_TRUE(fetcher);
246 FakeOnURLFetchComplete(fetcher, 404, std::string(responses[2]));
247
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());
252
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();
260
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();
269
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();
276
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);
287
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);
295
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]));
305
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();
312
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);
320
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();
334
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);
340 }
341
TEST_F(AutofillDownloadTest,CacheQueryTest)342 TEST_F(AutofillDownloadTest, CacheQueryTest) {
343 // Create and register factory.
344 net::TestURLFetcherFactory factory;
345
346 FormData form;
347 form.method = ASCIIToUTF16("post");
348
349 FormFieldData field;
350 field.form_control_type = "text";
351
352 field.label = ASCIIToUTF16("username");
353 field.name = ASCIIToUTF16("username");
354 form.fields.push_back(field);
355
356 field.label = ASCIIToUTF16("First Name");
357 field.name = ASCIIToUTF16("firstname");
358 form.fields.push_back(field);
359
360 field.label = ASCIIToUTF16("Last Name");
361 field.name = ASCIIToUTF16("lastname");
362 form.fields.push_back(field);
363
364 FormStructure *form_structure = new FormStructure(form);
365 ScopedVector<FormStructure> form_structures0;
366 form_structures0.push_back(form_structure);
367
368 // Add a slightly different form, which should result in a different request.
369 field.label = ASCIIToUTF16("email");
370 field.name = ASCIIToUTF16("email");
371 form.fields.push_back(field);
372 form_structure = new FormStructure(form);
373 ScopedVector<FormStructure> form_structures1;
374 form_structures1.push_back(form_structure);
375
376 // Add another slightly different form, which should also result in a
377 // different request.
378 field.label = ASCIIToUTF16("email2");
379 field.name = ASCIIToUTF16("email2");
380 form.fields.push_back(field);
381 form_structure = new FormStructure(form);
382 ScopedVector<FormStructure> form_structures2;
383 form_structures2.push_back(form_structure);
384
385 // Limit cache to two forms.
386 LimitCache(2);
387
388 const char *responses[] = {
389 "<autofillqueryresponse>"
390 "<field autofilltype=\"0\" />"
391 "<field autofilltype=\"3\" />"
392 "<field autofilltype=\"5\" />"
393 "</autofillqueryresponse>",
394 "<autofillqueryresponse>"
395 "<field autofilltype=\"0\" />"
396 "<field autofilltype=\"3\" />"
397 "<field autofilltype=\"5\" />"
398 "<field autofilltype=\"9\" />"
399 "</autofillqueryresponse>",
400 "<autofillqueryresponse>"
401 "<field autofilltype=\"0\" />"
402 "<field autofilltype=\"3\" />"
403 "<field autofilltype=\"5\" />"
404 "<field autofilltype=\"9\" />"
405 "<field autofilltype=\"0\" />"
406 "</autofillqueryresponse>",
407 };
408
409 // Request with id 0.
410 MockAutofillMetrics mock_metric_logger;
411 EXPECT_CALL(mock_metric_logger,
412 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
413 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
414 mock_metric_logger));
415 // No responses yet
416 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
417
418 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
419 ASSERT_TRUE(fetcher);
420 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
421 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
422 EXPECT_EQ(responses[0], responses_.front().response);
423
424 responses_.clear();
425
426 // No actual request - should be a cache hit.
427 EXPECT_CALL(mock_metric_logger,
428 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
429 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
430 mock_metric_logger));
431 // Data is available immediately from cache - no over-the-wire trip.
432 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
433 EXPECT_EQ(responses[0], responses_.front().response);
434 responses_.clear();
435
436 // Request with id 1.
437 EXPECT_CALL(mock_metric_logger,
438 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
439 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(),
440 mock_metric_logger));
441 // No responses yet
442 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
443
444 fetcher = factory.GetFetcherByID(1);
445 ASSERT_TRUE(fetcher);
446 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1]));
447 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
448 EXPECT_EQ(responses[1], responses_.front().response);
449
450 responses_.clear();
451
452 // Request with id 2.
453 EXPECT_CALL(mock_metric_logger,
454 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
455 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(),
456 mock_metric_logger));
457
458 fetcher = factory.GetFetcherByID(2);
459 ASSERT_TRUE(fetcher);
460 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[2]));
461 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
462 EXPECT_EQ(responses[2], responses_.front().response);
463
464 responses_.clear();
465
466 // No actual requests - should be a cache hit.
467 EXPECT_CALL(mock_metric_logger,
468 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
469 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(),
470 mock_metric_logger));
471
472 EXPECT_CALL(mock_metric_logger,
473 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
474 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(),
475 mock_metric_logger));
476
477 ASSERT_EQ(static_cast<size_t>(2), responses_.size());
478 EXPECT_EQ(responses[1], responses_.front().response);
479 EXPECT_EQ(responses[2], responses_.back().response);
480 responses_.clear();
481
482 // The first structure should've expired.
483 // Request with id 3.
484 EXPECT_CALL(mock_metric_logger,
485 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
486 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
487 mock_metric_logger));
488 // No responses yet
489 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
490
491 fetcher = factory.GetFetcherByID(3);
492 ASSERT_TRUE(fetcher);
493 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
494 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
495 EXPECT_EQ(responses[0], responses_.front().response);
496 }
497
498 } // namespace autofill
499