15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/autofill/core/browser/autofill_download_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/autofill/core/browser/autofill_driver.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/autofill_metrics.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/autofill_xml_parser.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/form_structure.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "components/autofill/core/common/autofill_pref_names.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/webrtc/libjingle/xmllite/xmlparser.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace autofill {
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kAutofillQueryServerNameStartInHeader[] = "GFE/";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxFormCacheSize = 16;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(GOOGLE_CHROME_BUILD)
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kClientName[] = "Google Chrome";
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#else
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kClientName[] = "Chromium";
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  // defined(GOOGLE_CHROME_BUILD)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string RequestTypeToString(AutofillDownloadManager::RequestType type) {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case AutofillDownloadManager::REQUEST_QUERY:
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "query";
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case AutofillDownloadManager::REQUEST_UPLOAD:
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "upload";
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NOTREACHED();
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return std::string();
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)GURL GetRequestUrl(AutofillDownloadManager::RequestType request_type) {
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GURL("https://clients1.google.com/tbproxy/af/" +
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              RequestTypeToString(request_type) + "?client=" + kClientName);
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct AutofillDownloadManager::FormRequestData {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> form_signatures;
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  RequestType request_type;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)AutofillDownloadManager::AutofillDownloadManager(AutofillDriver* driver,
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 PrefService* pref_service,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 Observer* observer)
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : driver_(driver),
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pref_service_(pref_service),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_(observer),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_form_cache_size_(kMaxFormCacheSize),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_query_request_(base::Time::Now()),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_upload_request_(base::Time::Now()),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      positive_upload_rate_(0),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      negative_upload_rate_(0),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fetcher_id_for_unittest_(0) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(observer_);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  positive_upload_rate_ =
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pref_service_->GetDouble(prefs::kAutofillPositiveUploadRate);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_upload_rate_ =
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pref_service_->GetDouble(prefs::kAutofillNegativeUploadRate);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutofillDownloadManager::~AutofillDownloadManager() {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPairFirstPointers(url_fetchers_.begin(),
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      url_fetchers_.end());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutofillDownloadManager::StartQueryRequest(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<FormStructure*>& forms,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AutofillMetrics& metric_logger) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_query_request_ > base::Time::Now()) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are in back-off mode: do not do the request.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string form_xml;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FormRequestData request_data;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         &form_xml)) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_data.request_type = AutofillDownloadManager::REQUEST_QUERY;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_SENT);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string query_data;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CheckCacheForQueryRequest(request_data.form_signatures, &query_data)) {
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DVLOG(1) << "AutofillDownloadManager: query request has been retrieved "
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             << "from the cache, form signatures: "
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             << GetCombinedSignature(request_data.form_signatures);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnLoadedServerPredictions(query_data);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StartRequest(form_xml, request_data);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutofillDownloadManager::StartUploadRequest(
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FormStructure& form,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool form_was_autofilled,
1153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ServerFieldTypeSet& available_field_types) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string form_xml;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!form.EncodeUploadRequest(available_field_types, form_was_autofilled,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                &form_xml))
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_upload_request_ > base::Time::Now()) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are in back-off mode: do not do the request.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "AutofillDownloadManager: Upload request is throttled.";
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flip a coin to see if we should upload this form.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double upload_rate = form_was_autofilled ? GetPositiveUploadRate() :
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             GetNegativeUploadRate();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (form.upload_required() == UPLOAD_NOT_REQUIRED ||
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (form.upload_required() == USE_UPLOAD_RATES &&
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       base::RandDouble() > upload_rate)) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "AutofillDownloadManager: Upload request is ignored.";
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we ever need notification that upload was skipped, add it here.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FormRequestData request_data;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_data.form_signatures.push_back(form.FormSignature());
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_data.request_type = AutofillDownloadManager::REQUEST_UPLOAD;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StartRequest(form_xml, request_data);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double AutofillDownloadManager::GetPositiveUploadRate() const {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return positive_upload_rate_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double AutofillDownloadManager::GetNegativeUploadRate() const {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return negative_upload_rate_;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillDownloadManager::SetPositiveUploadRate(double rate) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rate == positive_upload_rate_)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  positive_upload_rate_ = rate;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(rate, 0.0);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(rate, 1.0);
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pref_service_->SetDouble(prefs::kAutofillPositiveUploadRate, rate);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillDownloadManager::SetNegativeUploadRate(double rate) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rate == negative_upload_rate_)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_upload_rate_ = rate;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(rate, 0.0);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(rate, 1.0);
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pref_service_->SetDouble(prefs::kAutofillNegativeUploadRate, rate);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutofillDownloadManager::StartRequest(
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& form_xml,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FormRequestData& request_data) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequestContextGetter* request_context =
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      driver_->GetURLRequestContext();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_context);
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL request_url = GetRequestUrl(request_data.request_type);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Id is ignored for regular chrome, in unit test id's for fake fetcher
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // factory will be 0, 1, 2, ...
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLFetcher* fetcher = net::URLFetcher::Create(
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fetcher_id_for_unittest_++, request_url, net::URLFetcher::POST,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_fetchers_[fetcher] = request_data;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetAutomaticallyRetryOn5xx(false);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetRequestContext(request_context);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetUploadData("text/plain", form_xml);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        net::LOAD_DO_NOT_SEND_COOKIES);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->Start();
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Sending AutofillDownloadManager "
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << RequestTypeToString(request_data.request_type)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " request: " << form_xml;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillDownloadManager::CacheQueryRequest(
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& forms_in_query,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& query_data) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string signature = GetCombinedSignature(forms_in_query);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (QueryRequestCache::iterator it = cached_forms_.begin();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != cached_forms_.end(); ++it) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->first == signature) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We hit the cache, move to the first position and return.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::pair<std::string, std::string> data = *it;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cached_forms_.erase(it);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cached_forms_.push_front(data);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::pair<std::string, std::string> data;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.first = signature;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.second = query_data;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cached_forms_.push_front(data);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (cached_forms_.size() > max_form_cache_size_)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cached_forms_.pop_back();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutofillDownloadManager::CheckCacheForQueryRequest(
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& forms_in_query,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* query_data) const {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string signature = GetCombinedSignature(forms_in_query);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (QueryRequestCache::const_iterator it = cached_forms_.begin();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != cached_forms_.end(); ++it) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->first == signature) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We hit the cache, fill the data and return.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *query_data = it->second;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string AutofillDownloadManager::GetCombinedSignature(
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& forms_in_query) const {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t total_size = forms_in_query.size();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < forms_in_query.size(); ++i)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_size += forms_in_query[i].length();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string signature;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signature.reserve(total_size);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < forms_in_query.size(); ++i) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      signature.append(",");
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    signature.append(forms_in_query[i]);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return signature;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillDownloadManager::OnURLFetchComplete(
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<net::URLFetcher *, FormRequestData>::iterator it =
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_fetchers_.find(const_cast<net::URLFetcher*>(source));
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == url_fetchers_.end()) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Looks like crash on Mac is possibly caused with callback entering here
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // with unknown fetcher when network is refreshed.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string request_type(RequestTypeToString(it->second.request_type));
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kHttpResponseOk = 200;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kHttpInternalServerError = 500;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kHttpBadGateway = 502;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kHttpServiceUnavailable = 503;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(it->second.form_signatures.size());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source->GetResponseCode() != kHttpResponseOk) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool back_off = false;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string server_header;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (source->GetResponseCode()) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kHttpBadGateway:
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!source->GetResponseHeaders()->EnumerateHeader(NULL, "server",
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           &server_header) ||
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            StartsWithASCII(server_header.c_str(),
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            kAutofillQueryServerNameStartInHeader,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            false) != 0)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Bad gateway was received from Autofill servers. Fall through to back
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // off.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kHttpInternalServerError:
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kHttpServiceUnavailable:
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        back_off = true;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (back_off) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time back_off_time(base::Time::Now() + source->GetBackoffDelay());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (it->second.request_type == AutofillDownloadManager::REQUEST_QUERY) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_query_request_ = back_off_time;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_upload_request_ = back_off_time;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << "AutofillDownloadManager: " << request_type
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " request has failed with response "
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << source->GetResponseCode();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnServerRequestError(it->second.form_signatures[0],
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    it->second.request_type,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    source->GetResponseCode());
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response_body;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source->GetResponseAsString(&response_body);
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << "AutofillDownloadManager: " << request_type
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             << " request has succeeded with response body: " << response_body;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->second.request_type == AutofillDownloadManager::REQUEST_QUERY) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CacheQueryRequest(it->second.form_signatures, response_body);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_->OnLoadedServerPredictions(response_body);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double new_positive_upload_rate = 0;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double new_negative_upload_rate = 0;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AutofillUploadXmlParser parse_handler(&new_positive_upload_rate,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            &new_negative_upload_rate);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buzz::XmlParser parser(&parse_handler);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parser.Parse(response_body.data(), response_body.length(), true);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (parse_handler.succeeded()) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetPositiveUploadRate(new_positive_upload_rate);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetNegativeUploadRate(new_negative_upload_rate);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_->OnUploadedPossibleFieldTypes();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete it->first;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_fetchers_.erase(it);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace autofill
331