autofill_download.cc revision cfb4826edae011aed657a813297687800ed85e17
1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autofill/autofill_download.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm>
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <ostream>
94a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <vector>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/rand_util.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/stl_util-inl.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_util.h"
15201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/autofill/autofill_metrics.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autofill/autofill_xml_parser.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/autofill/form_structure.h"
183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "googleurl/src/gurl.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_response_headers.h"
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "third_party/libjingle/source/talk/xmllite/xmlparser.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#define AUTO_FILL_QUERY_SERVER_REQUEST_URL \
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    "http://toolbarqueries.clients.google.com:80/tbproxy/af/query"
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#define AUTO_FILL_UPLOAD_SERVER_REQUEST_URL \
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    "http://toolbarqueries.clients.google.com:80/tbproxy/af/upload"
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#define AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER "GFE/"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace {
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst size_t kMaxFormCacheSize = 16;
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct AutofillDownloadManager::FormRequestData {
36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::vector<std::string> form_signatures;
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  AutofillRequestType request_type;
38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick};
39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
40c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen#ifdef ANDROID
41c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen// Taken from autofill_manager.cc
42c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsenconst double kAutoFillPositiveUploadRateDefaultValue = 0.01;
43c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsenconst double kAutoFillNegativeUploadRateDefaultValue = 0.01;
44c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen#endif
45c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen
46dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenAutofillDownloadManager::AutofillDownloadManager(Profile* profile)
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : profile_(profile),
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      observer_(NULL),
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      max_form_cache_size_(kMaxFormCacheSize),
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next_query_request_(base::Time::Now()),
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next_upload_request_(base::Time::Now()),
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      positive_upload_rate_(0),
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      negative_upload_rate_(0),
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      fetcher_id_for_unittest_(0) {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |profile_| could be NULL in some unit-tests.
56c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen#ifdef ANDROID
57c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen  positive_upload_rate_ = kAutoFillPositiveUploadRateDefaultValue;
58c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen  negative_upload_rate_ = kAutoFillNegativeUploadRateDefaultValue;
59c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen#else
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (profile_) {
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PrefService* preferences = profile_->GetPrefs();
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    positive_upload_rate_ =
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        preferences->GetDouble(prefs::kAutofillPositiveUploadRate);
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    negative_upload_rate_ =
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        preferences->GetDouble(prefs::kAutofillNegativeUploadRate);
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
67c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen#endif
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
70dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenAutofillDownloadManager::~AutofillDownloadManager() {
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  STLDeleteContainerPairFirstPointers(url_fetchers_.begin(),
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      url_fetchers_.end());
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutofillDownloadManager::SetObserver(
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    AutofillDownloadManager::Observer *observer) {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (observer) {
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(!observer_);
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    observer_ = observer;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    observer_ = NULL;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool AutofillDownloadManager::StartQueryRequest(
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const ScopedVector<FormStructure>& forms,
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const AutofillMetrics& metric_logger) {
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (next_query_request_ > base::Time::Now()) {
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We are in back-off mode: do not do the request.
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string form_xml;
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FormRequestData request_data;
94513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures,
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                         &form_xml)) {
96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return false;
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  request_data.request_type = AutofillDownloadManager::REQUEST_QUERY;
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  metric_logger.Log(AutofillMetrics::QUERY_SENT);
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string query_data;
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (CheckCacheForQueryRequest(request_data.form_signatures, &query_data)) {
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << "AutofillDownloadManager: query request has been retrieved from"
10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            << "the cache";
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (observer_)
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      observer_->OnLoadedAutofillHeuristics(query_data);
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return true;
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return StartRequest(form_xml, request_data);
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool AutofillDownloadManager::StartUploadRequest(
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FormStructure& form, bool form_was_matched) {
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (next_upload_request_ > base::Time::Now()) {
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We are in back-off mode: do not do the request.
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check if we need to upload form.
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  double upload_rate = form_was_matched ? GetPositiveUploadRate() :
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          GetNegativeUploadRate();
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (base::RandDouble() > upload_rate) {
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << "AutofillDownloadManager: Upload request is ignored";
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If we ever need notification that upload was skipped, add it here.
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string form_xml;
130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!form.EncodeUploadRequest(form_was_matched, &form_xml))
131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return false;
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FormRequestData request_data;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_data.form_signatures.push_back(form.FormSignature());
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  request_data.request_type = AutofillDownloadManager::REQUEST_UPLOAD;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return StartRequest(form_xml, request_data);
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool AutofillDownloadManager::CancelRequest(
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& form_signature,
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    AutofillDownloadManager::AutofillRequestType request_type) {
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::map<URLFetcher *, FormRequestData>::iterator it =
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       url_fetchers_.begin();
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       it != url_fetchers_.end();
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       ++it) {
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (std::find(it->second.form_signatures.begin(),
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        it->second.form_signatures.end(), form_signature) !=
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        it->second.form_signatures.end() &&
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        it->second.request_type == request_type) {
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete it->first;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url_fetchers_.erase(it);
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsendouble AutofillDownloadManager::GetPositiveUploadRate() const {
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return positive_upload_rate_;
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsendouble AutofillDownloadManager::GetNegativeUploadRate() const {
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return negative_upload_rate_;
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutofillDownloadManager::SetPositiveUploadRate(double rate) {
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rate == positive_upload_rate_)
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  positive_upload_rate_ = rate;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(rate, 0.0);
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_LE(rate, 1.0);
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(profile_);
1746e1a1d3242a4de2a633c62ba45948dd2d0620990Kristian Monsen#ifndef ANDROID
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrefService* preferences = profile_->GetPrefs();
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  preferences->SetDouble(prefs::kAutofillPositiveUploadRate, rate);
177cfb4826edae011aed657a813297687800ed85e17Kristian Monsen#endif
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutofillDownloadManager::SetNegativeUploadRate(double rate) {
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rate == negative_upload_rate_)
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  negative_upload_rate_ = rate;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(rate, 0.0);
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_LE(rate, 1.0);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(profile_);
1876e1a1d3242a4de2a633c62ba45948dd2d0620990Kristian Monsen#ifndef ANDROID
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrefService* preferences = profile_->GetPrefs();
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  preferences->SetDouble(prefs::kAutofillNegativeUploadRate, rate);
190cfb4826edae011aed657a813297687800ed85e17Kristian Monsen#endif
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool AutofillDownloadManager::StartRequest(
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& form_xml,
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FormRequestData& request_data) {
196cfb4826edae011aed657a813297687800ed85e17Kristian Monsen  net::URLRequestContextGetter* request_context =
19772348d7342b67133b80566824ec56ee7afff127fKristian Monsen#ifdef ANDROID
19872348d7342b67133b80566824ec56ee7afff127fKristian Monsen      // On Android, use the webview request context getter which was passed
19972348d7342b67133b80566824ec56ee7afff127fKristian Monsen      // through in the WebAutoFill::init() method in WebKit.
20072348d7342b67133b80566824ec56ee7afff127fKristian Monsen      profile_->GetRequestContext();
20172348d7342b67133b80566824ec56ee7afff127fKristian Monsen#else
202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      Profile::GetDefaultRequestContext();
20372348d7342b67133b80566824ec56ee7afff127fKristian Monsen#endif
204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Check if default request context is NULL: this very rarely happens,
205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // I think, this could happen only if user opens chrome with some pages
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // loading the forms immediately; I cannot reproduce this even in that
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // scenario, but bug 74492 shows it happened at least once. In that case bail
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // out and fall back on our own heuristics.
209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!request_context)
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string request_url;
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (request_data.request_type == AutofillDownloadManager::REQUEST_QUERY)
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request_url = AUTO_FILL_QUERY_SERVER_REQUEST_URL;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request_url = AUTO_FILL_UPLOAD_SERVER_REQUEST_URL;
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Id is ignored for regular chrome, in unit test id's for fake fetcher
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // factory will be 0, 1, 2, ...
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  URLFetcher *fetcher = URLFetcher::Create(fetcher_id_for_unittest_++,
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           GURL(request_url),
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           URLFetcher::POST,
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           this);
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url_fetchers_[fetcher] = request_data;
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fetcher->set_automatically_retry_on_5xx(false);
225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  fetcher->set_request_context(request_context);
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  fetcher->set_upload_data("text/plain", form_xml);
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  fetcher->Start();
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutofillDownloadManager::CacheQueryRequest(
23272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::vector<std::string>& forms_in_query,
23372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::string& query_data) {
23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string signature = GetCombinedSignature(forms_in_query);
23572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (QueryRequestCache::iterator it = cached_forms_.begin();
23672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen       it != cached_forms_.end(); ++it) {
23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (it->first == signature) {
23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // We hit the cache, move to the first position and return.
23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      std::pair<std::string, std::string> data = *it;
24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cached_forms_.erase(it);
24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cached_forms_.push_front(data);
24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return;
24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::pair<std::string, std::string> data;
24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  data.first = signature;
24772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  data.second = query_data;
24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  cached_forms_.push_front(data);
24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  while (cached_forms_.size() > max_form_cache_size_)
25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    cached_forms_.pop_back();
25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool AutofillDownloadManager::CheckCacheForQueryRequest(
25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::vector<std::string>& forms_in_query,
25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string* query_data) const {
25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string signature = GetCombinedSignature(forms_in_query);
25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (QueryRequestCache::const_iterator it = cached_forms_.begin();
25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen       it != cached_forms_.end(); ++it) {
25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (it->first == signature) {
26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // We hit the cache, fill the data and return.
26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      *query_data = it->second;
26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return true;
26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return false;
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::string AutofillDownloadManager::GetCombinedSignature(
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::vector<std::string>& forms_in_query) const {
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  size_t total_size = forms_in_query.size();
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (size_t i = 0; i < forms_in_query.size(); ++i)
27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    total_size += forms_in_query[i].length();
27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string signature;
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  signature.reserve(total_size);
27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (size_t i = 0; i < forms_in_query.size(); ++i) {
27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (i)
27972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      signature.append(",");
28072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    signature.append(forms_in_query[i]);
28172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
28272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return signature;
28372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
28472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutofillDownloadManager::OnURLFetchComplete(
2863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const URLFetcher* source,
2873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const GURL& url,
2883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const net::URLRequestStatus& status,
2893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    int response_code,
2903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const ResponseCookies& cookies,
2913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const std::string& data) {
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::map<URLFetcher *, FormRequestData>::iterator it =
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url_fetchers_.find(const_cast<URLFetcher*>(source));
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it == url_fetchers_.end()) {
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Looks like crash on Mac is possibly caused with callback entering here
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // with unknown fetcher when network is refreshed.
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string type_of_request(
300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      it->second.request_type == AutofillDownloadManager::REQUEST_QUERY ?
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "query" : "upload");
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kHttpResponseOk = 200;
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kHttpInternalServerError = 500;
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kHttpBadGateway = 502;
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kHttpServiceUnavailable = 503;
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(it->second.form_signatures.size());
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (response_code != kHttpResponseOk) {
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool back_off = false;
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string server_header;
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (response_code) {
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case kHttpBadGateway:
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (!source->response_headers()->EnumerateHeader(NULL, "server",
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                         &server_header) ||
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            StartsWithASCII(server_header.c_str(),
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER,
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            false) != 0)
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // Bad gateway was received from Autofill servers. Fall through to back
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // off.
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case kHttpInternalServerError:
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case kHttpServiceUnavailable:
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        back_off = true;
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (back_off) {
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      base::Time back_off_time(base::Time::Now() + source->backoff_delay());
329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (it->second.request_type == AutofillDownloadManager::REQUEST_QUERY) {
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        next_query_request_ = back_off_time;
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        next_upload_request_ = back_off_time;
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(WARNING) << "AutofillDownloadManager: " << type_of_request
3374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                 << " request has failed with response " << response_code;
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (observer_) {
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      observer_->OnHeuristicsRequestError(it->second.form_signatures[0],
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          it->second.request_type,
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          response_code);
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << "AutofillDownloadManager: " << type_of_request
345731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            << " request has succeeded";
346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (it->second.request_type == AutofillDownloadManager::REQUEST_QUERY) {
34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      CacheQueryRequest(it->second.form_signatures, data);
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (observer_)
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        observer_->OnLoadedAutofillHeuristics(data);
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      double new_positive_upload_rate = 0;
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      double new_negative_upload_rate = 0;
353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      AutofillUploadXmlParser parse_handler(&new_positive_upload_rate,
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            &new_negative_upload_rate);
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      buzz::XmlParser parser(&parse_handler);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      parser.Parse(data.data(), data.length(), true);
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (parse_handler.succeeded()) {
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        SetPositiveUploadRate(new_positive_upload_rate);
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        SetNegativeUploadRate(new_negative_upload_rate);
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (observer_)
363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        observer_->OnUploadedAutofillHeuristics(it->second.form_signatures[0]);
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete it->first;
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url_fetchers_.erase(it);
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
369