• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/string_util.h"
8 #include "base/test/test_timeouts.h"
9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/autofill/autofill_download.h"
11 #include "chrome/browser/autofill/autofill_field.h"
12 #include "chrome/browser/autofill/autofill_metrics.h"
13 #include "chrome/browser/autofill/form_structure.h"
14 #include "chrome/common/net/test_url_fetcher_factory.h"
15 #include "chrome/test/test_url_request_context_getter.h"
16 #include "chrome/test/testing_browser_process.h"
17 #include "chrome/test/testing_browser_process_test.h"
18 #include "chrome/test/testing_profile.h"
19 #include "net/url_request/url_request_status.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
23 #include "webkit/glue/form_data.h"
24 
25 using webkit_glue::FormData;
26 using WebKit::WebInputElement;
27 
28 namespace {
29 
30 class MockAutofillMetrics : public AutofillMetrics {
31  public:
MockAutofillMetrics()32   MockAutofillMetrics() {}
33   MOCK_CONST_METHOD1(Log, void(ServerQueryMetric metric));
34 
35  private:
36   DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
37 };
38 
39 }  // namespace
40 
41 // This tests AutofillDownloadManager. AutofillDownloadTestHelper implements
42 // AutofillDownloadManager::Observer and creates an instance of
43 // AutofillDownloadManager. Then it records responses to different initiated
44 // requests, which are verified later. To mock network requests
45 // TestURLFetcherFactory is used, which creates URLFetchers that do not
46 // go over the wire, but allow calling back HTTP responses directly.
47 // The responses in test are out of order and verify: successful query request,
48 // successful upload request, failed upload request.
49 class AutofillDownloadTestHelper : public AutofillDownloadManager::Observer {
50  public:
AutofillDownloadTestHelper()51   AutofillDownloadTestHelper()
52       : download_manager(&profile),
53         request_context_getter(new TestURLRequestContextGetter()) {
54     download_manager.SetObserver(this);
55   }
~AutofillDownloadTestHelper()56   ~AutofillDownloadTestHelper() {
57     Profile::set_default_request_context(NULL);
58     download_manager.SetObserver(NULL);
59   }
60 
InitContextGetter()61   void InitContextGetter() {
62     Profile::set_default_request_context(request_context_getter.get());
63   }
64 
LimitCache(size_t cache_size)65   void LimitCache(size_t cache_size) {
66     download_manager.set_max_form_cache_size(cache_size);
67   }
68 
69   // AutofillDownloadManager::Observer overridables:
OnLoadedAutofillHeuristics(const std::string & heuristic_xml)70   virtual void OnLoadedAutofillHeuristics(
71       const std::string& heuristic_xml) {
72     ResponseData response;
73     response.response = heuristic_xml;
74     response.type_of_response = QUERY_SUCCESSFULL;
75     responses_.push_back(response);
76   };
OnUploadedAutofillHeuristics(const std::string & form_signature)77   virtual void OnUploadedAutofillHeuristics(const std::string& form_signature) {
78     ResponseData response;
79     response.type_of_response = UPLOAD_SUCCESSFULL;
80     responses_.push_back(response);
81   }
OnHeuristicsRequestError(const std::string & form_signature,AutofillDownloadManager::AutofillRequestType request_type,int http_error)82   virtual void OnHeuristicsRequestError(
83       const std::string& form_signature,
84       AutofillDownloadManager::AutofillRequestType request_type,
85       int http_error) {
86     ResponseData response;
87     response.signature = form_signature;
88     response.error = http_error;
89     response.type_of_response =
90         request_type == AutofillDownloadManager::REQUEST_QUERY ?
91             REQUEST_QUERY_FAILED : REQUEST_UPLOAD_FAILED;
92     responses_.push_back(response);
93   }
94 
95   enum TYPE_OF_RESPONSE {
96     QUERY_SUCCESSFULL,
97     UPLOAD_SUCCESSFULL,
98     REQUEST_QUERY_FAILED,
99     REQUEST_UPLOAD_FAILED,
100   };
101 
102   struct ResponseData {
103     TYPE_OF_RESPONSE type_of_response;
104     int error;
105     std::string signature;
106     std::string response;
ResponseDataAutofillDownloadTestHelper::ResponseData107     ResponseData() : type_of_response(REQUEST_QUERY_FAILED), error(0) {
108     }
109   };
110   std::list<AutofillDownloadTestHelper::ResponseData> responses_;
111 
112   TestingProfile profile;
113   AutofillDownloadManager download_manager;
114   scoped_refptr<net::URLRequestContextGetter> request_context_getter;
115 };
116 
117 typedef TestingBrowserProcessTest AutofillDownloadTest;
118 
TEST_F(AutofillDownloadTest,QueryAndUploadTest)119 TEST_F(AutofillDownloadTest, QueryAndUploadTest) {
120   MessageLoopForUI message_loop;
121   // Create and register factory.
122   AutofillDownloadTestHelper helper;
123   TestURLFetcherFactory factory;
124   URLFetcher::set_factory(&factory);
125 
126   FormData form;
127   form.method = ASCIIToUTF16("post");
128   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("username"),
129                                                ASCIIToUTF16("username"),
130                                                string16(),
131                                                ASCIIToUTF16("text"),
132                                                0,
133                                                false));
134   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"),
135                                                ASCIIToUTF16("firstname"),
136                                                string16(),
137                                                ASCIIToUTF16("text"),
138                                                0,
139                                                false));
140   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"),
141                                                ASCIIToUTF16("lastname"),
142                                                string16(),
143                                                ASCIIToUTF16("text"),
144                                                0,
145                                                false));
146   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email"),
147                                                ASCIIToUTF16("email"),
148                                                string16(),
149                                                ASCIIToUTF16("text"),
150                                                0,
151                                                false));
152   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email2"),
153                                                ASCIIToUTF16("email2"),
154                                                string16(),
155                                                ASCIIToUTF16("text"),
156                                                0,
157                                                false));
158   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("password"),
159                                                ASCIIToUTF16("password"),
160                                                string16(),
161                                                ASCIIToUTF16("password"),
162                                                0,
163                                                false));
164   form.fields.push_back(webkit_glue::FormField(string16(),
165                                                ASCIIToUTF16("Submit"),
166                                                string16(),
167                                                ASCIIToUTF16("submit"),
168                                                0,
169                                                false));
170 
171   FormStructure *form_structure = new FormStructure(form);
172   ScopedVector<FormStructure> form_structures;
173   form_structures.push_back(form_structure);
174 
175   form.fields.clear();
176   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("address"),
177                                                ASCIIToUTF16("address"),
178                                                string16(),
179                                                ASCIIToUTF16("text"),
180                                                0,
181                                                false));
182   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("address2"),
183                                                ASCIIToUTF16("address2"),
184                                                string16(),
185                                                ASCIIToUTF16("text"),
186                                                0,
187                                                false));
188   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("city"),
189                                                ASCIIToUTF16("city"),
190                                                string16(),
191                                                ASCIIToUTF16("text"),
192                                                0,
193                                                false));
194   form.fields.push_back(webkit_glue::FormField(string16(),
195                                                ASCIIToUTF16("Submit"),
196                                                string16(),
197                                                ASCIIToUTF16("submit"),
198                                                0,
199                                                false));
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, Log(AutofillMetrics::QUERY_SENT)).Times(2);
206   // First one will fail because context is not set up.
207   EXPECT_FALSE(helper.download_manager.StartQueryRequest(form_structures,
208                                                          mock_metric_logger));
209   helper.InitContextGetter();
210   EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures,
211                                                         mock_metric_logger));
212   // Set upload to 100% so requests happen.
213   helper.download_manager.SetPositiveUploadRate(1.0);
214   helper.download_manager.SetNegativeUploadRate(1.0);
215   // Request with id 1.
216   EXPECT_TRUE(helper.download_manager.StartUploadRequest(*(form_structures[0]),
217                                                          true));
218   // Request with id 2.
219   EXPECT_TRUE(helper.download_manager.StartUploadRequest(*(form_structures[1]),
220                                                          false));
221 
222   const char *responses[] = {
223     "<autofillqueryresponse>"
224       "<field autofilltype=\"0\" />"
225       "<field autofilltype=\"3\" />"
226       "<field autofilltype=\"5\" />"
227       "<field autofilltype=\"9\" />"
228       "<field autofilltype=\"0\" />"
229       "<field autofilltype=\"30\" />"
230       "<field autofilltype=\"31\" />"
231       "<field autofilltype=\"33\" />"
232     "</autofillqueryresponse>",
233     "<autofilluploadresponse positiveuploadrate=\"0.5\" "
234     "negativeuploadrate=\"0.3\"/>",
235     "<html></html>",
236   };
237 
238   // Return them out of sequence.
239   TestURLFetcher* fetcher = factory.GetFetcherByID(1);
240   ASSERT_TRUE(fetcher);
241   fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
242                                           net::URLRequestStatus(),
243                                           200, ResponseCookies(),
244                                           std::string(responses[1]));
245   // After that upload rates would be adjusted to 0.5/0.3
246   EXPECT_DOUBLE_EQ(0.5, helper.download_manager.GetPositiveUploadRate());
247   EXPECT_DOUBLE_EQ(0.3, helper.download_manager.GetNegativeUploadRate());
248 
249   fetcher = factory.GetFetcherByID(2);
250   ASSERT_TRUE(fetcher);
251   fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
252                                           net::URLRequestStatus(),
253                                           404, ResponseCookies(),
254                                           std::string(responses[2]));
255   fetcher = factory.GetFetcherByID(0);
256   ASSERT_TRUE(fetcher);
257   fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
258                                           net::URLRequestStatus(),
259                                           200, ResponseCookies(),
260                                           std::string(responses[0]));
261   EXPECT_EQ(static_cast<size_t>(3), helper.responses_.size());
262 
263   EXPECT_EQ(AutofillDownloadTestHelper::UPLOAD_SUCCESSFULL,
264             helper.responses_.front().type_of_response);
265   EXPECT_EQ(0, helper.responses_.front().error);
266   EXPECT_EQ(std::string(), helper.responses_.front().signature);
267   // Expected response on non-query request is an empty string.
268   EXPECT_EQ(std::string(), helper.responses_.front().response);
269   helper.responses_.pop_front();
270 
271   EXPECT_EQ(AutofillDownloadTestHelper::REQUEST_UPLOAD_FAILED,
272             helper.responses_.front().type_of_response);
273   EXPECT_EQ(404, helper.responses_.front().error);
274   EXPECT_EQ(form_structures[1]->FormSignature(),
275             helper.responses_.front().signature);
276   // Expected response on non-query request is an empty string.
277   EXPECT_EQ(std::string(), helper.responses_.front().response);
278   helper.responses_.pop_front();
279 
280   EXPECT_EQ(helper.responses_.front().type_of_response,
281             AutofillDownloadTestHelper::QUERY_SUCCESSFULL);
282   EXPECT_EQ(0, helper.responses_.front().error);
283   EXPECT_EQ(std::string(), helper.responses_.front().signature);
284   EXPECT_EQ(responses[0], helper.responses_.front().response);
285   helper.responses_.pop_front();
286 
287   // Set upload to 0% so no new requests happen.
288   helper.download_manager.SetPositiveUploadRate(0.0);
289   helper.download_manager.SetNegativeUploadRate(0.0);
290   // No actual requests for the next two calls, as we set upload rate to 0%.
291   EXPECT_FALSE(helper.download_manager.StartUploadRequest(*(form_structures[0]),
292                                                          true));
293   EXPECT_FALSE(helper.download_manager.StartUploadRequest(*(form_structures[1]),
294                                                          false));
295   fetcher = factory.GetFetcherByID(3);
296   EXPECT_EQ(NULL, fetcher);
297 
298   // Modify form structures to miss the cache.
299   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address line 2"),
300                                                ASCIIToUTF16("address2"),
301                                                string16(),
302                                                ASCIIToUTF16("text"),
303                                                0,
304                                                false));
305   form_structure = new FormStructure(form);
306   form_structures.push_back(form_structure);
307 
308   // Request with id 3.
309   EXPECT_CALL(mock_metric_logger, Log(AutofillMetrics::QUERY_SENT)).Times(1);
310   EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures,
311                                                         mock_metric_logger));
312   fetcher = factory.GetFetcherByID(3);
313   ASSERT_TRUE(fetcher);
314   fetcher->set_backoff_delay(
315       base::TimeDelta::FromMilliseconds(TestTimeouts::action_max_timeout_ms()));
316   fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
317                                           net::URLRequestStatus(),
318                                           500, ResponseCookies(),
319                                           std::string(responses[0]));
320   EXPECT_EQ(AutofillDownloadTestHelper::REQUEST_QUERY_FAILED,
321             helper.responses_.front().type_of_response);
322   EXPECT_EQ(500, helper.responses_.front().error);
323   // Expected response on non-query request is an empty string.
324   EXPECT_EQ(std::string(), helper.responses_.front().response);
325   helper.responses_.pop_front();
326 
327   // Query requests should be ignored for the next 10 seconds.
328   EXPECT_CALL(mock_metric_logger, Log(AutofillMetrics::QUERY_SENT)).Times(0);
329   EXPECT_FALSE(helper.download_manager.StartQueryRequest(form_structures,
330                                                          mock_metric_logger));
331   fetcher = factory.GetFetcherByID(4);
332   EXPECT_EQ(NULL, fetcher);
333 
334   // Set upload to 100% so requests happen.
335   helper.download_manager.SetPositiveUploadRate(1.0);
336   // Request with id 4.
337   EXPECT_TRUE(helper.download_manager.StartUploadRequest(*(form_structures[0]),
338               true));
339   fetcher = factory.GetFetcherByID(4);
340   ASSERT_TRUE(fetcher);
341   fetcher->set_backoff_delay(
342       base::TimeDelta::FromMilliseconds(TestTimeouts::action_max_timeout_ms()));
343   fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
344                                           net::URLRequestStatus(),
345                                           503, ResponseCookies(),
346                                           std::string(responses[2]));
347   EXPECT_EQ(AutofillDownloadTestHelper::REQUEST_UPLOAD_FAILED,
348             helper.responses_.front().type_of_response);
349   EXPECT_EQ(503, helper.responses_.front().error);
350   helper.responses_.pop_front();
351 
352   // Upload requests should be ignored for the next 10 seconds.
353   EXPECT_FALSE(helper.download_manager.StartUploadRequest(*(form_structures[0]),
354               true));
355   fetcher = factory.GetFetcherByID(5);
356   EXPECT_EQ(NULL, fetcher);
357 
358   // Make sure consumer of URLFetcher does the right thing.
359   URLFetcher::set_factory(NULL);
360 }
361 
TEST_F(AutofillDownloadTest,CacheQueryTest)362 TEST_F(AutofillDownloadTest, CacheQueryTest) {
363   MessageLoopForUI message_loop;
364   AutofillDownloadTestHelper helper;
365   // Create and register factory.
366   TestURLFetcherFactory factory;
367   URLFetcher::set_factory(&factory);
368   helper.InitContextGetter();
369 
370   FormData form;
371   form.method = ASCIIToUTF16("post");
372   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("username"),
373                                                ASCIIToUTF16("username"),
374                                                string16(),
375                                                ASCIIToUTF16("text"),
376                                                0,
377                                                false));
378   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"),
379                                                ASCIIToUTF16("firstname"),
380                                                string16(),
381                                                ASCIIToUTF16("text"),
382                                                0,
383                                                false));
384   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"),
385                                                ASCIIToUTF16("lastname"),
386                                                string16(),
387                                                ASCIIToUTF16("text"),
388                                                0,
389                                                false));
390   FormStructure *form_structure = new FormStructure(form);
391   ScopedVector<FormStructure> form_structures0;
392   form_structures0.push_back(form_structure);
393 
394   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email"),
395                                                ASCIIToUTF16("email"),
396                                                string16(),
397                                                ASCIIToUTF16("text"),
398                                                0,
399                                                false));
400   // Slightly different form - so different request.
401   form_structure = new FormStructure(form);
402   ScopedVector<FormStructure> form_structures1;
403   form_structures1.push_back(form_structure);
404 
405   form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("email2"),
406                                                ASCIIToUTF16("email2"),
407                                                string16(),
408                                                ASCIIToUTF16("text"),
409                                                0,
410                                                false));
411   // Slightly different form - so different request.
412   form_structure = new FormStructure(form);
413   ScopedVector<FormStructure> form_structures2;
414   form_structures2.push_back(form_structure);
415 
416   // Limit cache to two forms.
417   helper.LimitCache(2);
418 
419   const char *responses[] = {
420     "<autofillqueryresponse>"
421       "<field autofilltype=\"0\" />"
422       "<field autofilltype=\"3\" />"
423       "<field autofilltype=\"5\" />"
424     "</autofillqueryresponse>",
425     "<autofillqueryresponse>"
426       "<field autofilltype=\"0\" />"
427       "<field autofilltype=\"3\" />"
428       "<field autofilltype=\"5\" />"
429       "<field autofilltype=\"9\" />"
430     "</autofillqueryresponse>",
431     "<autofillqueryresponse>"
432       "<field autofilltype=\"0\" />"
433       "<field autofilltype=\"3\" />"
434       "<field autofilltype=\"5\" />"
435       "<field autofilltype=\"9\" />"
436       "<field autofilltype=\"0\" />"
437     "</autofillqueryresponse>",
438   };
439 
440   // Request with id 0.
441   MockAutofillMetrics mock_metric_logger;
442   EXPECT_CALL(mock_metric_logger, Log(AutofillMetrics::QUERY_SENT)).Times(1);
443   EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures0,
444                                                         mock_metric_logger));
445   // No responses yet
446   EXPECT_EQ(static_cast<size_t>(0), helper.responses_.size());
447 
448   TestURLFetcher* fetcher = factory.GetFetcherByID(0);
449   ASSERT_TRUE(fetcher);
450   fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
451                                           net::URLRequestStatus(),
452                                           200, ResponseCookies(),
453                                           std::string(responses[0]));
454   ASSERT_EQ(static_cast<size_t>(1), helper.responses_.size());
455   EXPECT_EQ(responses[0], helper.responses_.front().response);
456 
457   helper.responses_.clear();
458 
459   // No actual request - should be a cache hit.
460   EXPECT_CALL(mock_metric_logger, Log(AutofillMetrics::QUERY_SENT)).Times(1);
461   EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures0,
462                                                         mock_metric_logger));
463   // Data is available immediately from cache - no over-the-wire trip.
464   ASSERT_EQ(static_cast<size_t>(1), helper.responses_.size());
465   EXPECT_EQ(responses[0], helper.responses_.front().response);
466   helper.responses_.clear();
467 
468   // Request with id 1.
469   EXPECT_CALL(mock_metric_logger, Log(AutofillMetrics::QUERY_SENT)).Times(1);
470   EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures1,
471                                                         mock_metric_logger));
472   // No responses yet
473   EXPECT_EQ(static_cast<size_t>(0), helper.responses_.size());
474 
475   fetcher = factory.GetFetcherByID(1);
476   ASSERT_TRUE(fetcher);
477   fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
478                                           net::URLRequestStatus(),
479                                           200, ResponseCookies(),
480                                           std::string(responses[1]));
481   ASSERT_EQ(static_cast<size_t>(1), helper.responses_.size());
482   EXPECT_EQ(responses[1], helper.responses_.front().response);
483 
484   helper.responses_.clear();
485 
486   // Request with id 2.
487   EXPECT_CALL(mock_metric_logger, Log(AutofillMetrics::QUERY_SENT)).Times(1);
488   EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures2,
489                                                         mock_metric_logger));
490 
491   fetcher = factory.GetFetcherByID(2);
492   ASSERT_TRUE(fetcher);
493   fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
494                                           net::URLRequestStatus(),
495                                           200, ResponseCookies(),
496                                           std::string(responses[2]));
497   ASSERT_EQ(static_cast<size_t>(1), helper.responses_.size());
498   EXPECT_EQ(responses[2], helper.responses_.front().response);
499 
500   helper.responses_.clear();
501 
502   // No actual requests - should be a cache hit.
503   EXPECT_CALL(mock_metric_logger, Log(AutofillMetrics::QUERY_SENT)).Times(1);
504   EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures1,
505                                                         mock_metric_logger));
506 
507   EXPECT_CALL(mock_metric_logger, Log(AutofillMetrics::QUERY_SENT)).Times(1);
508   EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures2,
509                                                         mock_metric_logger));
510 
511   ASSERT_EQ(static_cast<size_t>(2), helper.responses_.size());
512   EXPECT_EQ(responses[1], helper.responses_.front().response);
513   EXPECT_EQ(responses[2], helper.responses_.back().response);
514   helper.responses_.clear();
515 
516   // The first structure should've expired.
517   // Request with id 3.
518   EXPECT_CALL(mock_metric_logger, Log(AutofillMetrics::QUERY_SENT)).Times(1);
519   EXPECT_TRUE(helper.download_manager.StartQueryRequest(form_structures0,
520                                                         mock_metric_logger));
521   // No responses yet
522   EXPECT_EQ(static_cast<size_t>(0), helper.responses_.size());
523 
524   fetcher = factory.GetFetcherByID(3);
525   ASSERT_TRUE(fetcher);
526   fetcher->delegate()->OnURLFetchComplete(fetcher, GURL(),
527                                           net::URLRequestStatus(),
528                                           200, ResponseCookies(),
529                                           std::string(responses[0]));
530   ASSERT_EQ(static_cast<size_t>(1), helper.responses_.size());
531   EXPECT_EQ(responses[0], helper.responses_.front().response);
532 
533   // Make sure consumer of URLFetcher does the right thing.
534   URLFetcher::set_factory(NULL);
535 }
536 
537