1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 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)
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/autofill_download.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ostream>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/autofill_download_url.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/autofill_metrics.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/autofill_xml_parser.h"
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/form_structure.h"
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "components/autofill/core/common/autofill_pref_names.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/user_prefs.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_context.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/libjingle/source/talk/xmllite/xmlparser.h"
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserContext;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace autofill {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAutofillQueryServerNameStartInHeader[] = "GFE/";
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxFormCacheSize = 16;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Generate field assignments xml that can be manually changed and then fed back
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// into the Autofill server as experiment data.
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void LogFieldAssignments(
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const FormStructure& form,
423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ServerFieldTypeSet& available_field_types) {
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string form_xml;
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!form.EncodeFieldAssignments(available_field_types, &form_xml))
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << "AutofillDownloadManager FieldAssignments for "
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << form.source_url()
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << " :\n"
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << form_xml;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string AutofillDownloadManager::AutofillRequestTypeToString(
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AutofillRequestType type) {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case AutofillDownloadManager::REQUEST_QUERY:
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "query";
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case AutofillDownloadManager::REQUEST_UPLOAD:
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "upload";
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return std::string();
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct AutofillDownloadManager::FormRequestData {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> form_signatures;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutofillRequestType request_type;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutofillDownloadManager::AutofillDownloadManager(BrowserContext* context,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 Observer* observer)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : browser_context_(context),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_(observer),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_form_cache_size_(kMaxFormCacheSize),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_query_request_(base::Time::Now()),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_upload_request_(base::Time::Now()),
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      positive_upload_rate_(0),
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      negative_upload_rate_(0),
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fetcher_id_for_unittest_(0) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(observer_);
835e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  PrefService* preferences = user_prefs::UserPrefs::Get(browser_context_);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  positive_upload_rate_ =
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      preferences->GetDouble(prefs::kAutofillPositiveUploadRate);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_upload_rate_ =
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      preferences->GetDouble(prefs::kAutofillNegativeUploadRate);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutofillDownloadManager::~AutofillDownloadManager() {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPairFirstPointers(url_fetchers_.begin(),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      url_fetchers_.end());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutofillDownloadManager::StartQueryRequest(
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<FormStructure*>& forms,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AutofillMetrics& metric_logger) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_query_request_ > base::Time::Now()) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are in back-off mode: do not do the request.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string form_xml;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FormRequestData request_data;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         &form_xml)) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_data.request_type = AutofillDownloadManager::REQUEST_QUERY;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_SENT);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string query_data;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CheckCacheForQueryRequest(request_data.form_signatures, &query_data)) {
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DVLOG(1) << "AutofillDownloadManager: query request has been retrieved "
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             << "from the cache, form signatures: "
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             << GetCombinedSignature(request_data.form_signatures);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnLoadedServerPredictions(query_data);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StartRequest(form_xml, request_data);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutofillDownloadManager::StartUploadRequest(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FormStructure& form,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool form_was_autofilled,
1273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ServerFieldTypeSet& available_field_types) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string form_xml;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!form.EncodeUploadRequest(available_field_types, form_was_autofilled,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                &form_xml))
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LogFieldAssignments(form, available_field_types);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_upload_request_ > base::Time::Now()) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are in back-off mode: do not do the request.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "AutofillDownloadManager: Upload request is throttled.";
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flip a coin to see if we should upload this form.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double upload_rate = form_was_autofilled ? GetPositiveUploadRate() :
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             GetNegativeUploadRate();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (form.upload_required() == UPLOAD_NOT_REQUIRED ||
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (form.upload_required() == USE_UPLOAD_RATES &&
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       base::RandDouble() > upload_rate)) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "AutofillDownloadManager: Upload request is ignored.";
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we ever need notification that upload was skipped, add it here.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FormRequestData request_data;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_data.form_signatures.push_back(form.FormSignature());
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_data.request_type = AutofillDownloadManager::REQUEST_UPLOAD;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StartRequest(form_xml, request_data);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double AutofillDownloadManager::GetPositiveUploadRate() const {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return positive_upload_rate_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double AutofillDownloadManager::GetNegativeUploadRate() const {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return negative_upload_rate_;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillDownloadManager::SetPositiveUploadRate(double rate) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rate == positive_upload_rate_)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  positive_upload_rate_ = rate;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(rate, 0.0);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(rate, 1.0);
1735e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  PrefService* preferences = user_prefs::UserPrefs::Get(browser_context_);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  preferences->SetDouble(prefs::kAutofillPositiveUploadRate, rate);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillDownloadManager::SetNegativeUploadRate(double rate) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rate == negative_upload_rate_)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_upload_rate_ = rate;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(rate, 0.0);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(rate, 1.0);
1835e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  PrefService* preferences = user_prefs::UserPrefs::Get(browser_context_);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  preferences->SetDouble(prefs::kAutofillNegativeUploadRate, rate);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutofillDownloadManager::StartRequest(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& form_xml,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FormRequestData& request_data) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequestContextGetter* request_context =
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_context_->GetRequestContext();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_context);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL request_url;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_data.request_type == AutofillDownloadManager::REQUEST_QUERY)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_url = autofill::GetAutofillQueryUrl();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_url = autofill::GetAutofillUploadUrl();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Id is ignored for regular chrome, in unit test id's for fake fetcher
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // factory will be 0, 1, 2, ...
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLFetcher* fetcher = net::URLFetcher::Create(
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fetcher_id_for_unittest_++, request_url, net::URLFetcher::POST,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_fetchers_[fetcher] = request_data;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetAutomaticallyRetryOn5xx(false);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetRequestContext(request_context);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetUploadData("text/plain", form_xml);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        net::LOAD_DO_NOT_SEND_COOKIES);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->Start();
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Sending AutofillDownloadManager "
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << AutofillRequestTypeToString(request_data.request_type)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << " request: " << form_xml;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillDownloadManager::CacheQueryRequest(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& forms_in_query,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& query_data) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string signature = GetCombinedSignature(forms_in_query);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (QueryRequestCache::iterator it = cached_forms_.begin();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != cached_forms_.end(); ++it) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->first == signature) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We hit the cache, move to the first position and return.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::pair<std::string, std::string> data = *it;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cached_forms_.erase(it);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cached_forms_.push_front(data);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::pair<std::string, std::string> data;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.first = signature;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.second = query_data;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cached_forms_.push_front(data);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (cached_forms_.size() > max_form_cache_size_)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cached_forms_.pop_back();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutofillDownloadManager::CheckCacheForQueryRequest(
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& forms_in_query,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* query_data) const {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string signature = GetCombinedSignature(forms_in_query);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (QueryRequestCache::const_iterator it = cached_forms_.begin();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != cached_forms_.end(); ++it) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->first == signature) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We hit the cache, fill the data and return.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *query_data = it->second;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string AutofillDownloadManager::GetCombinedSignature(
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& forms_in_query) const {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t total_size = forms_in_query.size();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < forms_in_query.size(); ++i)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_size += forms_in_query[i].length();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string signature;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signature.reserve(total_size);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < forms_in_query.size(); ++i) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      signature.append(",");
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    signature.append(forms_in_query[i]);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return signature;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillDownloadManager::OnURLFetchComplete(
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<net::URLFetcher *, FormRequestData>::iterator it =
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_fetchers_.find(const_cast<net::URLFetcher*>(source));
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == url_fetchers_.end()) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Looks like crash on Mac is possibly caused with callback entering here
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // with unknown fetcher when network is refreshed.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string type_of_request(
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AutofillRequestTypeToString(it->second.request_type));
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kHttpResponseOk = 200;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kHttpInternalServerError = 500;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kHttpBadGateway = 502;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kHttpServiceUnavailable = 503;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(it->second.form_signatures.size());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source->GetResponseCode() != kHttpResponseOk) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool back_off = false;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string server_header;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (source->GetResponseCode()) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kHttpBadGateway:
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!source->GetResponseHeaders()->EnumerateHeader(NULL, "server",
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           &server_header) ||
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            StartsWithASCII(server_header.c_str(),
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            kAutofillQueryServerNameStartInHeader,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            false) != 0)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Bad gateway was received from Autofill servers. Fall through to back
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // off.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kHttpInternalServerError:
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kHttpServiceUnavailable:
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        back_off = true;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (back_off) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time back_off_time(base::Time::Now() + source->GetBackoffDelay());
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (it->second.request_type == AutofillDownloadManager::REQUEST_QUERY) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_query_request_ = back_off_time;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_upload_request_ = back_off_time;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "AutofillDownloadManager: " << type_of_request
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " request has failed with response "
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << source->GetResponseCode();
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->OnServerRequestError(it->second.form_signatures[0],
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    it->second.request_type,
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    source->GetResponseCode());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response_body;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source->GetResponseAsString(&response_body);
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "AutofillDownloadManager: " << type_of_request
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << " request has succeeded with response body: "
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << response_body;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->second.request_type == AutofillDownloadManager::REQUEST_QUERY) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CacheQueryRequest(it->second.form_signatures, response_body);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_->OnLoadedServerPredictions(response_body);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double new_positive_upload_rate = 0;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double new_negative_upload_rate = 0;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AutofillUploadXmlParser parse_handler(&new_positive_upload_rate,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            &new_negative_upload_rate);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buzz::XmlParser parser(&parse_handler);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parser.Parse(response_body.data(), response_body.length(), true);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (parse_handler.succeeded()) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetPositiveUploadRate(new_positive_upload_rate);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetNegativeUploadRate(new_negative_upload_rate);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_->OnUploadedPossibleFieldTypes();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete it->first;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_fetchers_.erase(it);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace autofill
353