[Autofill] Don't save autocomplete text entered into fields with autocomplete="off"
[chromium-blink-merge.git] / components / autofill / core / browser / autocomplete_history_manager.cc
blob1c970fc3b038918aecc5a005928b49b4ce1688aa
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/autofill/core/browser/autocomplete_history_manager.h"
7 #include <vector>
9 #include "base/prefs/pref_service.h"
10 #include "base/profiler/scoped_tracker.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "components/autofill/core/browser/autofill_client.h"
14 #include "components/autofill/core/browser/autofill_driver.h"
15 #include "components/autofill/core/browser/autofill_external_delegate.h"
16 #include "components/autofill/core/browser/validation.h"
17 #include "components/autofill/core/common/autofill_pref_names.h"
18 #include "components/autofill/core/common/form_data.h"
20 namespace autofill {
21 namespace {
23 // Limit on the number of suggestions to appear in the pop-up menu under an
24 // text input element in a form.
25 const int kMaxAutocompleteMenuItems = 6;
27 bool IsTextField(const FormFieldData& field) {
28 return
29 field.form_control_type == "text" ||
30 field.form_control_type == "search" ||
31 field.form_control_type == "tel" ||
32 field.form_control_type == "url" ||
33 field.form_control_type == "email";
36 } // namespace
38 AutocompleteHistoryManager::AutocompleteHistoryManager(
39 AutofillDriver* driver,
40 AutofillClient* autofill_client)
41 : driver_(driver),
42 database_(autofill_client->GetDatabase()),
43 pending_query_handle_(0),
44 query_id_(0),
45 external_delegate_(NULL),
46 autofill_client_(autofill_client) {
47 DCHECK(autofill_client_);
50 AutocompleteHistoryManager::~AutocompleteHistoryManager() {
51 CancelPendingQuery();
54 void AutocompleteHistoryManager::OnWebDataServiceRequestDone(
55 WebDataServiceBase::Handle h,
56 const WDTypedResult* result) {
57 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422460 is fixed.
58 tracked_objects::ScopedTracker tracking_profile(
59 FROM_HERE_WITH_EXPLICIT_FUNCTION(
60 "422460 AutocompleteHistoryManager::OnWebDataServiceRequestDone"));
62 DCHECK(pending_query_handle_);
63 pending_query_handle_ = 0;
65 if (!autofill_client_->IsAutocompleteEnabled()) {
66 SendSuggestions(NULL);
67 return;
70 DCHECK(result);
71 // Returning early here if |result| is NULL. We've seen this happen on
72 // Linux due to NFS dismounting and causing sql failures.
73 // See http://crbug.com/68783.
74 if (!result) {
75 SendSuggestions(NULL);
76 return;
79 DCHECK_EQ(AUTOFILL_VALUE_RESULT, result->GetType());
80 const WDResult<std::vector<base::string16> >* autofill_result =
81 static_cast<const WDResult<std::vector<base::string16> >*>(result);
82 std::vector<base::string16> suggestions = autofill_result->GetValue();
83 SendSuggestions(&suggestions);
86 void AutocompleteHistoryManager::OnGetAutocompleteSuggestions(
87 int query_id,
88 const base::string16& name,
89 const base::string16& prefix,
90 const std::string& form_control_type,
91 const std::vector<base::string16>& autofill_values,
92 const std::vector<base::string16>& autofill_labels,
93 const std::vector<base::string16>& autofill_icons,
94 const std::vector<int>& autofill_unique_ids) {
95 CancelPendingQuery();
97 query_id_ = query_id;
98 autofill_values_ = autofill_values;
99 autofill_labels_ = autofill_labels;
100 autofill_icons_ = autofill_icons;
101 autofill_unique_ids_ = autofill_unique_ids;
102 if (!autofill_client_->IsAutocompleteEnabled() ||
103 form_control_type == "textarea") {
104 SendSuggestions(NULL);
105 return;
108 if (database_.get()) {
109 pending_query_handle_ = database_->GetFormValuesForElementName(
110 name, prefix, kMaxAutocompleteMenuItems, this);
114 void AutocompleteHistoryManager::OnFormSubmitted(const FormData& form) {
115 if (!autofill_client_->IsAutocompleteEnabled())
116 return;
118 if (driver_->IsOffTheRecord())
119 return;
121 // Don't save data that was submitted through JavaScript.
122 if (!form.user_submitted)
123 return;
125 // We put the following restriction on stored FormFields:
126 // - non-empty name
127 // - non-empty value
128 // - text field
129 // - autocomplete is not disabled
130 // - value is not a credit card number
131 // - value is not a SSN
132 std::vector<FormFieldData> values;
133 for (std::vector<FormFieldData>::const_iterator iter =
134 form.fields.begin();
135 iter != form.fields.end(); ++iter) {
136 if (!iter->value.empty() &&
137 !iter->name.empty() &&
138 IsTextField(*iter) &&
139 iter->should_autocomplete &&
140 !autofill::IsValidCreditCardNumber(iter->value) &&
141 !autofill::IsSSN(iter->value)) {
142 values.push_back(*iter);
146 if (!values.empty() && database_.get())
147 database_->AddFormFields(values);
150 void AutocompleteHistoryManager::OnRemoveAutocompleteEntry(
151 const base::string16& name, const base::string16& value) {
152 if (database_.get())
153 database_->RemoveFormValueForElementName(name, value);
156 void AutocompleteHistoryManager::SetExternalDelegate(
157 AutofillExternalDelegate* delegate) {
158 external_delegate_ = delegate;
161 void AutocompleteHistoryManager::CancelPendingQuery() {
162 if (pending_query_handle_) {
163 if (database_.get())
164 database_->CancelRequest(pending_query_handle_);
165 pending_query_handle_ = 0;
169 void AutocompleteHistoryManager::SendSuggestions(
170 const std::vector<base::string16>* suggestions) {
171 if (suggestions) {
172 // Combine Autofill and Autocomplete values into values and labels.
173 for (size_t i = 0; i < suggestions->size(); ++i) {
174 bool unique = true;
175 for (size_t j = 0; j < autofill_values_.size(); ++j) {
176 // Don't add duplicate values.
177 if (autofill_values_[j] == (*suggestions)[i]) {
178 unique = false;
179 break;
183 if (unique) {
184 autofill_values_.push_back((*suggestions)[i]);
185 autofill_labels_.push_back(base::string16());
186 autofill_icons_.push_back(base::string16());
187 autofill_unique_ids_.push_back(0); // 0 means no profile.
192 external_delegate_->OnSuggestionsReturned(query_id_,
193 autofill_values_,
194 autofill_labels_,
195 autofill_icons_,
196 autofill_unique_ids_);
198 query_id_ = 0;
199 autofill_values_.clear();
200 autofill_labels_.clear();
201 autofill_icons_.clear();
202 autofill_unique_ids_.clear();
205 } // namespace autofill