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
11bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch#ifdef ANDROID
12bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch#include "android/jni/autofill_request_url.h"
13bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch#endif
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/rand_util.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/stl_util-inl.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_util.h"
18201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/autofill/autofill_metrics.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autofill/autofill_xml_parser.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/autofill/form_structure.h"
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "googleurl/src/gurl.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_response_headers.h"
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "third_party/libjingle/source/talk/xmllite/xmlparser.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#define AUTO_FILL_QUERY_SERVER_REQUEST_URL \
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    "http://toolbarqueries.clients.google.com:80/tbproxy/af/query"
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#define AUTO_FILL_UPLOAD_SERVER_REQUEST_URL \
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    "http://toolbarqueries.clients.google.com:80/tbproxy/af/upload"
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#define AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER "GFE/"
334f3a742b60841cf402cd4192bd864afb7306356bBen Murdoch#ifdef ANDROID
344f3a742b60841cf402cd4192bd864afb7306356bBen Murdoch#define ANDROID_AUTOFILL_CLIENT_PARAM "?client=AndroidBrowser"
354f3a742b60841cf402cd4192bd864afb7306356bBen Murdoch#endif
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace {
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst size_t kMaxFormCacheSize = 16;
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct AutofillDownloadManager::FormRequestData {
42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::vector<std::string> form_signatures;
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  AutofillRequestType request_type;
44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick};
45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
46c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen#ifdef ANDROID
47c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen// Taken from autofill_manager.cc
48c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsenconst double kAutoFillPositiveUploadRateDefaultValue = 0.01;
49c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsenconst double kAutoFillNegativeUploadRateDefaultValue = 0.01;
50c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen#endif
51c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen
52dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenAutofillDownloadManager::AutofillDownloadManager(Profile* profile)
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : profile_(profile),
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      observer_(NULL),
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      max_form_cache_size_(kMaxFormCacheSize),
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next_query_request_(base::Time::Now()),
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next_upload_request_(base::Time::Now()),
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      positive_upload_rate_(0),
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      negative_upload_rate_(0),
6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      fetcher_id_for_unittest_(0) {
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |profile_| could be NULL in some unit-tests.
62c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen#ifdef ANDROID
63c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen  positive_upload_rate_ = kAutoFillPositiveUploadRateDefaultValue;
64c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen  negative_upload_rate_ = kAutoFillNegativeUploadRateDefaultValue;
65c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen#else
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (profile_) {
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PrefService* preferences = profile_->GetPrefs();
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    positive_upload_rate_ =
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        preferences->GetDouble(prefs::kAutofillPositiveUploadRate);
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    negative_upload_rate_ =
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        preferences->GetDouble(prefs::kAutofillNegativeUploadRate);
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
73c4becdd46e31d261b930e4b5a539cbc1d45c23a6Kristian Monsen#endif
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenAutofillDownloadManager::~AutofillDownloadManager() {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  STLDeleteContainerPairFirstPointers(url_fetchers_.begin(),
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      url_fetchers_.end());
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutofillDownloadManager::SetObserver(
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    AutofillDownloadManager::Observer *observer) {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (observer) {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(!observer_);
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    observer_ = observer;
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    observer_ = NULL;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool AutofillDownloadManager::StartQueryRequest(
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const ScopedVector<FormStructure>& forms,
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const AutofillMetrics& metric_logger) {
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (next_query_request_ > base::Time::Now()) {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We are in back-off mode: do not do the request.
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string form_xml;
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FormRequestData request_data;
100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures,
10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                         &form_xml)) {
102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return false;
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  request_data.request_type = AutofillDownloadManager::REQUEST_QUERY;
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  metric_logger.Log(AutofillMetrics::QUERY_SENT);
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string query_data;
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (CheckCacheForQueryRequest(request_data.form_signatures, &query_data)) {
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << "AutofillDownloadManager: query request has been retrieved from"
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            << "the cache";
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (observer_)
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      observer_->OnLoadedAutofillHeuristics(query_data);
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return true;
11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return StartRequest(form_xml, request_data);
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool AutofillDownloadManager::StartUploadRequest(
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FormStructure& form, bool form_was_matched) {
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (next_upload_request_ > base::Time::Now()) {
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We are in back-off mode: do not do the request.
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check if we need to upload form.
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  double upload_rate = form_was_matched ? GetPositiveUploadRate() :
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          GetNegativeUploadRate();
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (base::RandDouble() > upload_rate) {
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << "AutofillDownloadManager: Upload request is ignored";
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If we ever need notification that upload was skipped, add it here.
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string form_xml;
136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!form.EncodeUploadRequest(form_was_matched, &form_xml))
137513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return false;
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FormRequestData request_data;
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_data.form_signatures.push_back(form.FormSignature());
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  request_data.request_type = AutofillDownloadManager::REQUEST_UPLOAD;
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return StartRequest(form_xml, request_data);
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool AutofillDownloadManager::CancelRequest(
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& form_signature,
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    AutofillDownloadManager::AutofillRequestType request_type) {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::map<URLFetcher *, FormRequestData>::iterator it =
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       url_fetchers_.begin();
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       it != url_fetchers_.end();
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       ++it) {
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (std::find(it->second.form_signatures.begin(),
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        it->second.form_signatures.end(), form_signature) !=
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        it->second.form_signatures.end() &&
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        it->second.request_type == request_type) {
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete it->first;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url_fetchers_.erase(it);
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsendouble AutofillDownloadManager::GetPositiveUploadRate() const {
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return positive_upload_rate_;
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsendouble AutofillDownloadManager::GetNegativeUploadRate() const {
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return negative_upload_rate_;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutofillDownloadManager::SetPositiveUploadRate(double rate) {
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rate == positive_upload_rate_)
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  positive_upload_rate_ = rate;
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(rate, 0.0);
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_LE(rate, 1.0);
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(profile_);
1806e1a1d3242a4de2a633c62ba45948dd2d0620990Kristian Monsen#ifndef ANDROID
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrefService* preferences = profile_->GetPrefs();
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  preferences->SetDouble(prefs::kAutofillPositiveUploadRate, rate);
183cfb4826edae011aed657a813297687800ed85e17Kristian Monsen#endif
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutofillDownloadManager::SetNegativeUploadRate(double rate) {
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rate == negative_upload_rate_)
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  negative_upload_rate_ = rate;
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(rate, 0.0);
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_LE(rate, 1.0);
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(profile_);
1936e1a1d3242a4de2a633c62ba45948dd2d0620990Kristian Monsen#ifndef ANDROID
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrefService* preferences = profile_->GetPrefs();
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  preferences->SetDouble(prefs::kAutofillNegativeUploadRate, rate);
196cfb4826edae011aed657a813297687800ed85e17Kristian Monsen#endif
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool AutofillDownloadManager::StartRequest(
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& form_xml,
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FormRequestData& request_data) {
202cfb4826edae011aed657a813297687800ed85e17Kristian Monsen  net::URLRequestContextGetter* request_context =
20372348d7342b67133b80566824ec56ee7afff127fKristian Monsen#ifdef ANDROID
20472348d7342b67133b80566824ec56ee7afff127fKristian Monsen      // On Android, use the webview request context getter which was passed
20572348d7342b67133b80566824ec56ee7afff127fKristian Monsen      // through in the WebAutoFill::init() method in WebKit.
20672348d7342b67133b80566824ec56ee7afff127fKristian Monsen      profile_->GetRequestContext();
20772348d7342b67133b80566824ec56ee7afff127fKristian Monsen#else
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      Profile::GetDefaultRequestContext();
20972348d7342b67133b80566824ec56ee7afff127fKristian Monsen#endif
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Check if default request context is NULL: this very rarely happens,
211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // I think, this could happen only if user opens chrome with some pages
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // loading the forms immediately; I cannot reproduce this even in that
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // scenario, but bug 74492 shows it happened at least once. In that case bail
214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // out and fall back on our own heuristics.
215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!request_context)
216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string request_url;
218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (request_data.request_type == AutofillDownloadManager::REQUEST_QUERY)
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request_url = AUTO_FILL_QUERY_SERVER_REQUEST_URL;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request_url = AUTO_FILL_UPLOAD_SERVER_REQUEST_URL;
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
223bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch#ifdef ANDROID
224bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch  if (request_data.request_type == AutofillDownloadManager::REQUEST_QUERY) {
225bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch    // Ask the platform what URL to use for Autofill. If the
226bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch    // platform doesn't know, bail and rely on the heuristics
227bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch    // we've gathered.
228bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch    request_url = android::AutofillRequestUrl::GetQueryUrl();
229bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch    if (request_url.empty())
230bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch      return false;
2314f3a742b60841cf402cd4192bd864afb7306356bBen Murdoch    request_url += ANDROID_AUTOFILL_CLIENT_PARAM;
2324f3a742b60841cf402cd4192bd864afb7306356bBen Murdoch
233bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch  }
234bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch#endif
235bb958596648e7394f6cd9dcbd264ef9931655764Ben Murdoch
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Id is ignored for regular chrome, in unit test id's for fake fetcher
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // factory will be 0, 1, 2, ...
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  URLFetcher *fetcher = URLFetcher::Create(fetcher_id_for_unittest_++,
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           GURL(request_url),
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           URLFetcher::POST,
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           this);
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url_fetchers_[fetcher] = request_data;
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  fetcher->set_automatically_retry_on_5xx(false);
244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  fetcher->set_request_context(request_context);
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  fetcher->set_upload_data("text/plain", form_xml);
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  fetcher->Start();
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutofillDownloadManager::CacheQueryRequest(
25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::vector<std::string>& forms_in_query,
25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::string& query_data) {
25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string signature = GetCombinedSignature(forms_in_query);
25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (QueryRequestCache::iterator it = cached_forms_.begin();
25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen       it != cached_forms_.end(); ++it) {
25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (it->first == signature) {
25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // We hit the cache, move to the first position and return.
25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      std::pair<std::string, std::string> data = *it;
25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cached_forms_.erase(it);
26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cached_forms_.push_front(data);
26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return;
26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::pair<std::string, std::string> data;
26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  data.first = signature;
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  data.second = query_data;
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  cached_forms_.push_front(data);
26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  while (cached_forms_.size() > max_form_cache_size_)
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    cached_forms_.pop_back();
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool AutofillDownloadManager::CheckCacheForQueryRequest(
27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::vector<std::string>& forms_in_query,
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string* query_data) const {
27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string signature = GetCombinedSignature(forms_in_query);
27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (QueryRequestCache::const_iterator it = cached_forms_.begin();
27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen       it != cached_forms_.end(); ++it) {
27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (it->first == signature) {
27972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // We hit the cache, fill the data and return.
28072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      *query_data = it->second;
28172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return true;
28272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
28372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
28472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return false;
28572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
28672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::string AutofillDownloadManager::GetCombinedSignature(
28872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::vector<std::string>& forms_in_query) const {
28972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  size_t total_size = forms_in_query.size();
29072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (size_t i = 0; i < forms_in_query.size(); ++i)
29172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    total_size += forms_in_query[i].length();
29272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string signature;
29372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
29472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  signature.reserve(total_size);
29572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
29672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (size_t i = 0; i < forms_in_query.size(); ++i) {
29772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (i)
29872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      signature.append(",");
29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    signature.append(forms_in_query[i]);
30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return signature;
30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AutofillDownloadManager::OnURLFetchComplete(
3053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const URLFetcher* source,
3063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const GURL& url,
3073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const net::URLRequestStatus& status,
3083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    int response_code,
3093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const ResponseCookies& cookies,
3103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const std::string& data) {
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::map<URLFetcher *, FormRequestData>::iterator it =
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url_fetchers_.find(const_cast<URLFetcher*>(source));
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it == url_fetchers_.end()) {
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Looks like crash on Mac is possibly caused with callback entering here
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // with unknown fetcher when network is refreshed.
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string type_of_request(
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      it->second.request_type == AutofillDownloadManager::REQUEST_QUERY ?
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "query" : "upload");
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kHttpResponseOk = 200;
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kHttpInternalServerError = 500;
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kHttpBadGateway = 502;
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kHttpServiceUnavailable = 503;
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(it->second.form_signatures.size());
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (response_code != kHttpResponseOk) {
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool back_off = false;
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string server_header;
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (response_code) {
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case kHttpBadGateway:
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (!source->response_headers()->EnumerateHeader(NULL, "server",
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                         &server_header) ||
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            StartsWithASCII(server_header.c_str(),
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER,
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            false) != 0)
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // Bad gateway was received from Autofill servers. Fall through to back
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // off.
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case kHttpInternalServerError:
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case kHttpServiceUnavailable:
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        back_off = true;
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (back_off) {
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      base::Time back_off_time(base::Time::Now() + source->backoff_delay());
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (it->second.request_type == AutofillDownloadManager::REQUEST_QUERY) {
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        next_query_request_ = back_off_time;
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        next_upload_request_ = back_off_time;
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
355dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(WARNING) << "AutofillDownloadManager: " << type_of_request
3564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                 << " request has failed with response " << response_code;
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (observer_) {
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      observer_->OnHeuristicsRequestError(it->second.form_signatures[0],
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          it->second.request_type,
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          response_code);
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << "AutofillDownloadManager: " << type_of_request
364731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            << " request has succeeded";
365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (it->second.request_type == AutofillDownloadManager::REQUEST_QUERY) {
36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      CacheQueryRequest(it->second.form_signatures, data);
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (observer_)
368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        observer_->OnLoadedAutofillHeuristics(data);
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      double new_positive_upload_rate = 0;
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      double new_negative_upload_rate = 0;
372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      AutofillUploadXmlParser parse_handler(&new_positive_upload_rate,
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            &new_negative_upload_rate);
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      buzz::XmlParser parser(&parse_handler);
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      parser.Parse(data.data(), data.length(), true);
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (parse_handler.succeeded()) {
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        SetPositiveUploadRate(new_positive_upload_rate);
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        SetNegativeUploadRate(new_negative_upload_rate);
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (observer_)
382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        observer_->OnUploadedAutofillHeuristics(it->second.form_signatures[0]);
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete it->first;
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url_fetchers_.erase(it);
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
388