OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autofill/autofill_download.h" | 5 #include "chrome/browser/autofill/autofill_download.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/rand_util.h" | 11 #include "base/rand_util.h" |
12 #include "base/stl_util-inl.h" | 12 #include "base/stl_util-inl.h" |
13 #include "chrome/browser/autofill/autofill_metrics.h" | 13 #include "chrome/browser/autofill/autofill_metrics.h" |
14 #include "chrome/browser/autofill/autofill_xml_parser.h" | 14 #include "chrome/browser/autofill/autofill_xml_parser.h" |
15 #include "chrome/browser/prefs/pref_service.h" | 15 #include "chrome/browser/prefs/pref_service.h" |
16 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/common/pref_names.h" | 17 #include "chrome/common/pref_names.h" |
18 #include "net/http/http_response_headers.h" | 18 #include "net/http/http_response_headers.h" |
19 | 19 |
20 #define DISABLED_REQUEST_URL "http://disabled" | 20 #define DISABLED_REQUEST_URL "http://disabled" |
21 | 21 |
22 #if defined(GOOGLE_CHROME_BUILD) | 22 #if defined(GOOGLE_CHROME_BUILD) |
23 #include "chrome/browser/autofill/internal/autofill_download_internal.h" | 23 #include "chrome/browser/autofill/internal/autofill_download_internal.h" |
24 #else | 24 #else |
25 #define AUTO_FILL_QUERY_SERVER_REQUEST_URL DISABLED_REQUEST_URL | 25 #define AUTO_FILL_QUERY_SERVER_REQUEST_URL DISABLED_REQUEST_URL |
26 #define AUTO_FILL_UPLOAD_SERVER_REQUEST_URL DISABLED_REQUEST_URL | 26 #define AUTO_FILL_UPLOAD_SERVER_REQUEST_URL DISABLED_REQUEST_URL |
27 #define AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER "SOMESERVER/" | 27 #define AUTO_FILL_QUERY_SERVER_NAME_START_IN_HEADER "SOMESERVER/" |
28 #endif | 28 #endif |
29 | 29 |
| 30 namespace { |
| 31 const size_t kMaxFormCacheSize = 16; |
| 32 }; |
| 33 |
30 struct AutoFillDownloadManager::FormRequestData { | 34 struct AutoFillDownloadManager::FormRequestData { |
31 std::vector<std::string> form_signatures; | 35 std::vector<std::string> form_signatures; |
32 AutoFillRequestType request_type; | 36 AutoFillRequestType request_type; |
33 }; | 37 }; |
34 | 38 |
35 AutoFillDownloadManager::AutoFillDownloadManager(Profile* profile) | 39 AutoFillDownloadManager::AutoFillDownloadManager(Profile* profile) |
36 : profile_(profile), | 40 : profile_(profile), |
37 observer_(NULL), | 41 observer_(NULL), |
| 42 max_form_cache_size_(kMaxFormCacheSize), |
38 next_query_request_(base::Time::Now()), | 43 next_query_request_(base::Time::Now()), |
39 next_upload_request_(base::Time::Now()), | 44 next_upload_request_(base::Time::Now()), |
40 positive_upload_rate_(0), | 45 positive_upload_rate_(0), |
41 negative_upload_rate_(0), | 46 negative_upload_rate_(0), |
42 fetcher_id_for_unittest_(0), | 47 fetcher_id_for_unittest_(0), |
43 is_testing_(false) { | 48 is_testing_(false) { |
44 // |profile_| could be NULL in some unit-tests. | 49 // |profile_| could be NULL in some unit-tests. |
45 if (profile_) { | 50 if (profile_) { |
46 PrefService* preferences = profile_->GetPrefs(); | 51 PrefService* preferences = profile_->GetPrefs(); |
47 positive_upload_rate_ = | 52 positive_upload_rate_ = |
(...skipping 21 matching lines...) Expand all Loading... |
69 bool AutoFillDownloadManager::StartQueryRequest( | 74 bool AutoFillDownloadManager::StartQueryRequest( |
70 const ScopedVector<FormStructure>& forms, | 75 const ScopedVector<FormStructure>& forms, |
71 const AutoFillMetrics& metric_logger) { | 76 const AutoFillMetrics& metric_logger) { |
72 if (next_query_request_ > base::Time::Now()) { | 77 if (next_query_request_ > base::Time::Now()) { |
73 // We are in back-off mode: do not do the request. | 78 // We are in back-off mode: do not do the request. |
74 return false; | 79 return false; |
75 } | 80 } |
76 std::string form_xml; | 81 std::string form_xml; |
77 FormRequestData request_data; | 82 FormRequestData request_data; |
78 if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures, | 83 if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures, |
79 &form_xml)) | 84 &form_xml)) { |
80 return false; | 85 return false; |
| 86 } |
81 | 87 |
82 request_data.request_type = AutoFillDownloadManager::REQUEST_QUERY; | 88 request_data.request_type = AutoFillDownloadManager::REQUEST_QUERY; |
83 metric_logger.Log(AutoFillMetrics::QUERY_SENT); | 89 metric_logger.Log(AutoFillMetrics::QUERY_SENT); |
84 | 90 |
| 91 std::string query_data; |
| 92 if (CheckCacheForQueryRequest(request_data.form_signatures, &query_data)) { |
| 93 VLOG(1) << "AutoFillDownloadManager: query request has been retrieved from" |
| 94 << "the cache"; |
| 95 if (observer_) |
| 96 observer_->OnLoadedAutoFillHeuristics(query_data); |
| 97 return true; |
| 98 } |
| 99 |
85 return StartRequest(form_xml, request_data); | 100 return StartRequest(form_xml, request_data); |
86 } | 101 } |
87 | 102 |
88 bool AutoFillDownloadManager::StartUploadRequest( | 103 bool AutoFillDownloadManager::StartUploadRequest( |
89 const FormStructure& form, bool form_was_matched) { | 104 const FormStructure& form, bool form_was_matched) { |
90 if (next_upload_request_ > base::Time::Now()) { | 105 if (next_upload_request_ > base::Time::Now()) { |
91 // We are in back-off mode: do not do the request. | 106 // We are in back-off mode: do not do the request. |
92 return false; | 107 return false; |
93 } | 108 } |
94 | 109 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 URLFetcher::POST, | 196 URLFetcher::POST, |
182 this); | 197 this); |
183 url_fetchers_[fetcher] = request_data; | 198 url_fetchers_[fetcher] = request_data; |
184 fetcher->set_automatically_retry_on_5xx(false); | 199 fetcher->set_automatically_retry_on_5xx(false); |
185 fetcher->set_request_context(Profile::GetDefaultRequestContext()); | 200 fetcher->set_request_context(Profile::GetDefaultRequestContext()); |
186 fetcher->set_upload_data("text/plain", form_xml); | 201 fetcher->set_upload_data("text/plain", form_xml); |
187 fetcher->Start(); | 202 fetcher->Start(); |
188 return true; | 203 return true; |
189 } | 204 } |
190 | 205 |
| 206 void AutoFillDownloadManager::CacheQueryRequest( |
| 207 const std::vector<std::string>& forms_in_query, |
| 208 const std::string& query_data) { |
| 209 std::string signature = GetCombinedSignature(forms_in_query); |
| 210 for (QueryRequestCache::iterator it = cached_forms_.begin(); |
| 211 it != cached_forms_.end(); ++it) { |
| 212 if (it->first == signature) { |
| 213 // We hit the cache, move to the first position and return. |
| 214 std::pair<std::string, std::string> data = *it; |
| 215 cached_forms_.erase(it); |
| 216 cached_forms_.push_front(data); |
| 217 return; |
| 218 } |
| 219 } |
| 220 std::pair<std::string, std::string> data; |
| 221 data.first = signature; |
| 222 data.second = query_data; |
| 223 cached_forms_.push_front(data); |
| 224 while (cached_forms_.size() > max_form_cache_size_) |
| 225 cached_forms_.pop_back(); |
| 226 } |
| 227 |
| 228 bool AutoFillDownloadManager::CheckCacheForQueryRequest( |
| 229 const std::vector<std::string>& forms_in_query, |
| 230 std::string* query_data) const { |
| 231 std::string signature = GetCombinedSignature(forms_in_query); |
| 232 for (QueryRequestCache::const_iterator it = cached_forms_.begin(); |
| 233 it != cached_forms_.end(); ++it) { |
| 234 if (it->first == signature) { |
| 235 // We hit the cache, fill the data and return. |
| 236 *query_data = it->second; |
| 237 return true; |
| 238 } |
| 239 } |
| 240 return false; |
| 241 } |
| 242 |
| 243 std::string AutoFillDownloadManager::GetCombinedSignature( |
| 244 const std::vector<std::string>& forms_in_query) const { |
| 245 size_t total_size = forms_in_query.size(); |
| 246 for (size_t i = 0; i < forms_in_query.size(); ++i) |
| 247 total_size += forms_in_query[i].length(); |
| 248 std::string signature; |
| 249 |
| 250 signature.reserve(total_size); |
| 251 |
| 252 for (size_t i = 0; i < forms_in_query.size(); ++i) { |
| 253 if (i) |
| 254 signature.append(","); |
| 255 signature.append(forms_in_query[i]); |
| 256 } |
| 257 return signature; |
| 258 } |
| 259 |
191 void AutoFillDownloadManager::OnURLFetchComplete( | 260 void AutoFillDownloadManager::OnURLFetchComplete( |
192 const URLFetcher* source, | 261 const URLFetcher* source, |
193 const GURL& url, | 262 const GURL& url, |
194 const net::URLRequestStatus& status, | 263 const net::URLRequestStatus& status, |
195 int response_code, | 264 int response_code, |
196 const ResponseCookies& cookies, | 265 const ResponseCookies& cookies, |
197 const std::string& data) { | 266 const std::string& data) { |
198 std::map<URLFetcher *, FormRequestData>::iterator it = | 267 std::map<URLFetcher *, FormRequestData>::iterator it = |
199 url_fetchers_.find(const_cast<URLFetcher*>(source)); | 268 url_fetchers_.find(const_cast<URLFetcher*>(source)); |
200 if (it == url_fetchers_.end()) { | 269 if (it == url_fetchers_.end()) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 << " request has failed with response " << response_code; | 312 << " request has failed with response " << response_code; |
244 if (observer_) { | 313 if (observer_) { |
245 observer_->OnHeuristicsRequestError(it->second.form_signatures[0], | 314 observer_->OnHeuristicsRequestError(it->second.form_signatures[0], |
246 it->second.request_type, | 315 it->second.request_type, |
247 response_code); | 316 response_code); |
248 } | 317 } |
249 } else { | 318 } else { |
250 VLOG(1) << "AutoFillDownloadManager: " << type_of_request | 319 VLOG(1) << "AutoFillDownloadManager: " << type_of_request |
251 << " request has succeeded"; | 320 << " request has succeeded"; |
252 if (it->second.request_type == AutoFillDownloadManager::REQUEST_QUERY) { | 321 if (it->second.request_type == AutoFillDownloadManager::REQUEST_QUERY) { |
| 322 CacheQueryRequest(it->second.form_signatures, data); |
253 if (observer_) | 323 if (observer_) |
254 observer_->OnLoadedAutoFillHeuristics(data); | 324 observer_->OnLoadedAutoFillHeuristics(data); |
255 } else { | 325 } else { |
256 double new_positive_upload_rate = 0; | 326 double new_positive_upload_rate = 0; |
257 double new_negative_upload_rate = 0; | 327 double new_negative_upload_rate = 0; |
258 AutoFillUploadXmlParser parse_handler(&new_positive_upload_rate, | 328 AutoFillUploadXmlParser parse_handler(&new_positive_upload_rate, |
259 &new_negative_upload_rate); | 329 &new_negative_upload_rate); |
260 buzz::XmlParser parser(&parse_handler); | 330 buzz::XmlParser parser(&parse_handler); |
261 parser.Parse(data.data(), data.length(), true); | 331 parser.Parse(data.data(), data.length(), true); |
262 if (parse_handler.succeeded()) { | 332 if (parse_handler.succeeded()) { |
263 SetPositiveUploadRate(new_positive_upload_rate); | 333 SetPositiveUploadRate(new_positive_upload_rate); |
264 SetNegativeUploadRate(new_negative_upload_rate); | 334 SetNegativeUploadRate(new_negative_upload_rate); |
265 } | 335 } |
266 | 336 |
267 if (observer_) | 337 if (observer_) |
268 observer_->OnUploadedAutoFillHeuristics(it->second.form_signatures[0]); | 338 observer_->OnUploadedAutoFillHeuristics(it->second.form_signatures[0]); |
269 } | 339 } |
270 } | 340 } |
271 delete it->first; | 341 delete it->first; |
272 url_fetchers_.erase(it); | 342 url_fetchers_.erase(it); |
273 } | 343 } |
OLD | NEW |