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.
7 #include "base/message_loop/message_loop.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/test/test_timeouts.h"
11 #include "chrome/test/base/testing_profile.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_type.h"
16 #include "components/autofill/core/browser/form_structure.h"
17 #include "components/autofill/core/common/form_data.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "net/url_request/test_url_fetcher_factory.h"
20 #include "net/url_request/url_request_status.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "third_party/WebKit/public/web/WebInputElement.h"
25 using WebKit::WebInputElement;
31 class MockAutofillMetrics : public AutofillMetrics {
33 MockAutofillMetrics() {}
34 MOCK_CONST_METHOD1(LogServerQueryMetric, void(ServerQueryMetric metric));
37 DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
40 // Call |fetcher->OnURLFetchComplete()| as the URLFetcher would when
41 // a response is received. Params allow caller to set fake status.
42 void FakeOnURLFetchComplete(net::TestURLFetcher* fetcher,
44 const std::string& response_body) {
45 fetcher->set_url(GURL());
46 fetcher->set_status(net::URLRequestStatus());
47 fetcher->set_response_code(response_code);
48 fetcher->SetResponseString(response_body);
50 fetcher->delegate()->OnURLFetchComplete(fetcher);
55 // This tests AutofillDownloadManager. AutofillDownloadTest implements
56 // AutofillDownloadManager::Observer and creates an instance of
57 // AutofillDownloadManager. Then it records responses to different initiated
58 // requests, which are verified later. To mock network requests
59 // TestURLFetcherFactory is used, which creates URLFetchers that do not
60 // go over the wire, but allow calling back HTTP responses directly.
61 // The responses in test are out of order and verify: successful query request,
62 // successful upload request, failed upload request.
63 class AutofillDownloadTest : public AutofillDownloadManager::Observer,
64 public testing::Test {
66 AutofillDownloadTest()
67 : download_manager_(&profile_, this) {
70 void LimitCache(size_t cache_size) {
71 download_manager_.set_max_form_cache_size(cache_size);
74 // AutofillDownloadManager::Observer implementation.
75 virtual void OnLoadedServerPredictions(
76 const std::string& response_xml) OVERRIDE {
77 ResponseData response;
78 response.response = response_xml;
79 response.type_of_response = QUERY_SUCCESSFULL;
80 responses_.push_back(response);
83 virtual void OnUploadedPossibleFieldTypes() OVERRIDE {
84 ResponseData response;
85 response.type_of_response = UPLOAD_SUCCESSFULL;
86 responses_.push_back(response);
89 virtual void OnServerRequestError(
90 const std::string& form_signature,
91 AutofillDownloadManager::AutofillRequestType request_type,
92 int http_error) OVERRIDE {
93 ResponseData response;
94 response.signature = form_signature;
95 response.error = http_error;
96 response.type_of_response =
97 request_type == AutofillDownloadManager::REQUEST_QUERY ?
98 REQUEST_QUERY_FAILED : REQUEST_UPLOAD_FAILED;
99 responses_.push_back(response);
105 REQUEST_QUERY_FAILED,
106 REQUEST_UPLOAD_FAILED,
109 struct ResponseData {
110 ResponseType type_of_response;
112 std::string signature;
113 std::string response;
115 ResponseData() : type_of_response(REQUEST_QUERY_FAILED), error(0) {}
117 std::list<ResponseData> responses_;
119 content::TestBrowserThreadBundle thread_bundle_;
120 TestingProfile profile_;
121 AutofillDownloadManager download_manager_;
124 TEST_F(AutofillDownloadTest, QueryAndUploadTest) {
125 // Create and register factory.
126 net::TestURLFetcherFactory factory;
129 form.method = ASCIIToUTF16("post");
132 field.label = ASCIIToUTF16("username");
133 field.name = ASCIIToUTF16("username");
134 field.form_control_type = "text";
135 form.fields.push_back(field);
137 field.label = ASCIIToUTF16("First Name");
138 field.name = ASCIIToUTF16("firstname");
139 field.form_control_type = "text";
140 form.fields.push_back(field);
142 field.label = ASCIIToUTF16("Last Name");
143 field.name = ASCIIToUTF16("lastname");
144 field.form_control_type = "text";
145 form.fields.push_back(field);
147 field.label = ASCIIToUTF16("email");
148 field.name = ASCIIToUTF16("email");
149 field.form_control_type = "text";
150 form.fields.push_back(field);
152 field.label = ASCIIToUTF16("email2");
153 field.name = ASCIIToUTF16("email2");
154 field.form_control_type = "text";
155 form.fields.push_back(field);
157 field.label = ASCIIToUTF16("password");
158 field.name = ASCIIToUTF16("password");
159 field.form_control_type = "password";
160 form.fields.push_back(field);
162 field.label = base::string16();
163 field.name = ASCIIToUTF16("Submit");
164 field.form_control_type = "submit";
165 form.fields.push_back(field);
167 FormStructure *form_structure = new FormStructure(form);
168 ScopedVector<FormStructure> form_structures;
169 form_structures.push_back(form_structure);
173 field.label = ASCIIToUTF16("address");
174 field.name = ASCIIToUTF16("address");
175 field.form_control_type = "text";
176 form.fields.push_back(field);
178 field.label = ASCIIToUTF16("address2");
179 field.name = ASCIIToUTF16("address2");
180 field.form_control_type = "text";
181 form.fields.push_back(field);
183 field.label = ASCIIToUTF16("city");
184 field.name = ASCIIToUTF16("city");
185 field.form_control_type = "text";
186 form.fields.push_back(field);
188 field.label = base::string16();
189 field.name = ASCIIToUTF16("Submit");
190 field.form_control_type = "submit";
191 form.fields.push_back(field);
193 form_structure = new FormStructure(form);
194 form_structures.push_back(form_structure);
196 // Request with id 0.
197 MockAutofillMetrics mock_metric_logger;
198 EXPECT_CALL(mock_metric_logger,
199 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
200 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get(),
201 mock_metric_logger));
202 // Set upload to 100% so requests happen.
203 download_manager_.SetPositiveUploadRate(1.0);
204 download_manager_.SetNegativeUploadRate(1.0);
205 // Request with id 1.
206 EXPECT_TRUE(download_manager_.StartUploadRequest(
207 *(form_structures[0]), true, ServerFieldTypeSet()));
208 // Request with id 2.
209 EXPECT_TRUE(download_manager_.StartUploadRequest(
210 *(form_structures[1]), false, ServerFieldTypeSet()));
212 const char *responses[] = {
213 "<autofillqueryresponse>"
214 "<field autofilltype=\"0\" />"
215 "<field autofilltype=\"3\" />"
216 "<field autofilltype=\"5\" />"
217 "<field autofilltype=\"9\" />"
218 "<field autofilltype=\"0\" />"
219 "<field autofilltype=\"30\" />"
220 "<field autofilltype=\"31\" />"
221 "<field autofilltype=\"33\" />"
222 "</autofillqueryresponse>",
223 "<autofilluploadresponse positiveuploadrate=\"0.5\" "
224 "negativeuploadrate=\"0.3\"/>",
228 // Return them out of sequence.
229 net::TestURLFetcher* fetcher = factory.GetFetcherByID(1);
230 ASSERT_TRUE(fetcher);
231 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1]));
233 // After that upload rates would be adjusted to 0.5/0.3
234 EXPECT_DOUBLE_EQ(0.5, download_manager_.GetPositiveUploadRate());
235 EXPECT_DOUBLE_EQ(0.3, download_manager_.GetNegativeUploadRate());
237 fetcher = factory.GetFetcherByID(2);
238 ASSERT_TRUE(fetcher);
239 FakeOnURLFetchComplete(fetcher, 404, std::string(responses[2]));
241 fetcher = factory.GetFetcherByID(0);
242 ASSERT_TRUE(fetcher);
243 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
244 EXPECT_EQ(static_cast<size_t>(3), responses_.size());
246 EXPECT_EQ(AutofillDownloadTest::UPLOAD_SUCCESSFULL,
247 responses_.front().type_of_response);
248 EXPECT_EQ(0, responses_.front().error);
249 EXPECT_EQ(std::string(), responses_.front().signature);
250 // Expected response on non-query request is an empty string.
251 EXPECT_EQ(std::string(), responses_.front().response);
252 responses_.pop_front();
254 EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED,
255 responses_.front().type_of_response);
256 EXPECT_EQ(404, responses_.front().error);
257 EXPECT_EQ(form_structures[1]->FormSignature(),
258 responses_.front().signature);
259 // Expected response on non-query request is an empty string.
260 EXPECT_EQ(std::string(), responses_.front().response);
261 responses_.pop_front();
263 EXPECT_EQ(responses_.front().type_of_response,
264 AutofillDownloadTest::QUERY_SUCCESSFULL);
265 EXPECT_EQ(0, responses_.front().error);
266 EXPECT_EQ(std::string(), responses_.front().signature);
267 EXPECT_EQ(responses[0], responses_.front().response);
268 responses_.pop_front();
270 // Set upload to 0% so no new requests happen.
271 download_manager_.SetPositiveUploadRate(0.0);
272 download_manager_.SetNegativeUploadRate(0.0);
273 // No actual requests for the next two calls, as we set upload rate to 0%.
274 EXPECT_FALSE(download_manager_.StartUploadRequest(
275 *(form_structures[0]), true, ServerFieldTypeSet()));
276 EXPECT_FALSE(download_manager_.StartUploadRequest(
277 *(form_structures[1]), false, ServerFieldTypeSet()));
278 fetcher = factory.GetFetcherByID(3);
279 EXPECT_EQ(NULL, fetcher);
281 // Modify form structures to miss the cache.
282 field.label = ASCIIToUTF16("Address line 2");
283 field.name = ASCIIToUTF16("address2");
284 field.form_control_type = "text";
285 form.fields.push_back(field);
286 form_structure = new FormStructure(form);
287 form_structures.push_back(form_structure);
289 // Request with id 3.
290 EXPECT_CALL(mock_metric_logger,
291 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
292 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get(),
293 mock_metric_logger));
294 fetcher = factory.GetFetcherByID(3);
295 ASSERT_TRUE(fetcher);
296 fetcher->set_backoff_delay(TestTimeouts::action_max_timeout());
297 FakeOnURLFetchComplete(fetcher, 500, std::string(responses[0]));
299 EXPECT_EQ(AutofillDownloadTest::REQUEST_QUERY_FAILED,
300 responses_.front().type_of_response);
301 EXPECT_EQ(500, responses_.front().error);
302 // Expected response on non-query request is an empty string.
303 EXPECT_EQ(std::string(), responses_.front().response);
304 responses_.pop_front();
306 // Query requests should be ignored for the next 10 seconds.
307 EXPECT_CALL(mock_metric_logger,
308 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(0);
309 EXPECT_FALSE(download_manager_.StartQueryRequest(form_structures.get(),
310 mock_metric_logger));
311 fetcher = factory.GetFetcherByID(4);
312 EXPECT_EQ(NULL, fetcher);
314 // Set upload required to true so requests happen.
315 form_structures[0]->upload_required_ = UPLOAD_REQUIRED;
316 // Request with id 4.
317 EXPECT_TRUE(download_manager_.StartUploadRequest(
318 *(form_structures[0]), true, ServerFieldTypeSet()));
319 fetcher = factory.GetFetcherByID(4);
320 ASSERT_TRUE(fetcher);
321 fetcher->set_backoff_delay(TestTimeouts::action_max_timeout());
322 FakeOnURLFetchComplete(fetcher, 503, std::string(responses[2]));
323 EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED,
324 responses_.front().type_of_response);
325 EXPECT_EQ(503, responses_.front().error);
326 responses_.pop_front();
328 // Upload requests should be ignored for the next 10 seconds.
329 EXPECT_FALSE(download_manager_.StartUploadRequest(
330 *(form_structures[0]), true, ServerFieldTypeSet()));
331 fetcher = factory.GetFetcherByID(5);
332 EXPECT_EQ(NULL, fetcher);
335 TEST_F(AutofillDownloadTest, CacheQueryTest) {
336 // Create and register factory.
337 net::TestURLFetcherFactory factory;
340 form.method = ASCIIToUTF16("post");
343 field.form_control_type = "text";
345 field.label = ASCIIToUTF16("username");
346 field.name = ASCIIToUTF16("username");
347 form.fields.push_back(field);
349 field.label = ASCIIToUTF16("First Name");
350 field.name = ASCIIToUTF16("firstname");
351 form.fields.push_back(field);
353 field.label = ASCIIToUTF16("Last Name");
354 field.name = ASCIIToUTF16("lastname");
355 form.fields.push_back(field);
357 FormStructure *form_structure = new FormStructure(form);
358 ScopedVector<FormStructure> form_structures0;
359 form_structures0.push_back(form_structure);
361 // Add a slightly different form, which should result in a different request.
362 field.label = ASCIIToUTF16("email");
363 field.name = ASCIIToUTF16("email");
364 form.fields.push_back(field);
365 form_structure = new FormStructure(form);
366 ScopedVector<FormStructure> form_structures1;
367 form_structures1.push_back(form_structure);
369 // Add another slightly different form, which should also result in a
370 // different request.
371 field.label = ASCIIToUTF16("email2");
372 field.name = ASCIIToUTF16("email2");
373 form.fields.push_back(field);
374 form_structure = new FormStructure(form);
375 ScopedVector<FormStructure> form_structures2;
376 form_structures2.push_back(form_structure);
378 // Limit cache to two forms.
381 const char *responses[] = {
382 "<autofillqueryresponse>"
383 "<field autofilltype=\"0\" />"
384 "<field autofilltype=\"3\" />"
385 "<field autofilltype=\"5\" />"
386 "</autofillqueryresponse>",
387 "<autofillqueryresponse>"
388 "<field autofilltype=\"0\" />"
389 "<field autofilltype=\"3\" />"
390 "<field autofilltype=\"5\" />"
391 "<field autofilltype=\"9\" />"
392 "</autofillqueryresponse>",
393 "<autofillqueryresponse>"
394 "<field autofilltype=\"0\" />"
395 "<field autofilltype=\"3\" />"
396 "<field autofilltype=\"5\" />"
397 "<field autofilltype=\"9\" />"
398 "<field autofilltype=\"0\" />"
399 "</autofillqueryresponse>",
402 // Request with id 0.
403 MockAutofillMetrics mock_metric_logger;
404 EXPECT_CALL(mock_metric_logger,
405 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
406 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
407 mock_metric_logger));
409 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
411 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
412 ASSERT_TRUE(fetcher);
413 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
414 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
415 EXPECT_EQ(responses[0], responses_.front().response);
419 // No actual request - should be a cache hit.
420 EXPECT_CALL(mock_metric_logger,
421 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
422 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
423 mock_metric_logger));
424 // Data is available immediately from cache - no over-the-wire trip.
425 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
426 EXPECT_EQ(responses[0], responses_.front().response);
429 // Request with id 1.
430 EXPECT_CALL(mock_metric_logger,
431 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
432 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(),
433 mock_metric_logger));
435 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
437 fetcher = factory.GetFetcherByID(1);
438 ASSERT_TRUE(fetcher);
439 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1]));
440 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
441 EXPECT_EQ(responses[1], responses_.front().response);
445 // Request with id 2.
446 EXPECT_CALL(mock_metric_logger,
447 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
448 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(),
449 mock_metric_logger));
451 fetcher = factory.GetFetcherByID(2);
452 ASSERT_TRUE(fetcher);
453 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[2]));
454 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
455 EXPECT_EQ(responses[2], responses_.front().response);
459 // No actual requests - should be a cache hit.
460 EXPECT_CALL(mock_metric_logger,
461 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
462 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures1.get(),
463 mock_metric_logger));
465 EXPECT_CALL(mock_metric_logger,
466 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
467 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures2.get(),
468 mock_metric_logger));
470 ASSERT_EQ(static_cast<size_t>(2), responses_.size());
471 EXPECT_EQ(responses[1], responses_.front().response);
472 EXPECT_EQ(responses[2], responses_.back().response);
475 // The first structure should've expired.
476 // Request with id 3.
477 EXPECT_CALL(mock_metric_logger,
478 LogServerQueryMetric(AutofillMetrics::QUERY_SENT)).Times(1);
479 EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures0.get(),
480 mock_metric_logger));
482 EXPECT_EQ(static_cast<size_t>(0), responses_.size());
484 fetcher = factory.GetFetcherByID(3);
485 ASSERT_TRUE(fetcher);
486 FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
487 ASSERT_EQ(static_cast<size_t>(1), responses_.size());
488 EXPECT_EQ(responses[0], responses_.front().response);
491 } // namespace autofill