Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / components / autofill / core / browser / autocomplete_history_manager.cc
blobacfb47df60fbf963abdbc98e9dfc45dc3b891fc1
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(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
58 // fixed.
59 tracked_objects::ScopedTracker tracking_profile(
60 FROM_HERE_WITH_EXPLICIT_FUNCTION(
61 "422460 AutocompleteHistoryManager::OnWebDataServiceRequestDone"));
63 DCHECK(pending_query_handle_);
64 pending_query_handle_ = 0;
66 if (!autofill_client_->IsAutocompleteEnabled()) {
67 SendSuggestions(NULL);
68 return;
71 DCHECK(result);
72 // Returning early here if |result| is NULL. We've seen this happen on
73 // Linux due to NFS dismounting and causing sql failures.
74 // See http://crbug.com/68783.
75 if (!result) {
76 SendSuggestions(NULL);
77 return;
80 DCHECK_EQ(AUTOFILL_VALUE_RESULT, result->GetType());
81 const WDResult<std::vector<base::string16> >* autofill_result =
82 static_cast<const WDResult<std::vector<base::string16> >*>(result);
83 std::vector<base::string16> suggestions = autofill_result->GetValue();
84 SendSuggestions(&suggestions);
87 void AutocompleteHistoryManager::OnGetAutocompleteSuggestions(
88 int query_id,
89 const base::string16& name,
90 const base::string16& prefix,
91 const std::string& form_control_type,
92 const std::vector<Suggestion>& suggestions) {
93 CancelPendingQuery();
95 query_id_ = query_id;
96 autofill_suggestions_ = suggestions;
97 if (!autofill_client_->IsAutocompleteEnabled() ||
98 form_control_type == "textarea") {
99 SendSuggestions(NULL);
100 return;
103 if (database_.get()) {
104 pending_query_handle_ = database_->GetFormValuesForElementName(
105 name, prefix, kMaxAutocompleteMenuItems, this);
109 void AutocompleteHistoryManager::OnFormSubmitted(const FormData& form) {
110 if (!autofill_client_->IsAutocompleteEnabled())
111 return;
113 if (driver_->IsOffTheRecord())
114 return;
116 // Don't save data that was submitted through JavaScript.
117 if (!form.user_submitted)
118 return;
120 // We put the following restriction on stored FormFields:
121 // - non-empty name
122 // - non-empty value
123 // - text field
124 // - autocomplete is not disabled
125 // - value is not a credit card number
126 // - value is not a SSN
127 // - field was not identified as a CVC field (this is handled in
128 // AutofillManager)
129 std::vector<FormFieldData> values;
130 for (const FormFieldData& field : form.fields) {
131 if (!field.value.empty() && !field.name.empty() && IsTextField(field) &&
132 field.should_autocomplete &&
133 !autofill::IsValidCreditCardNumber(field.value) &&
134 !autofill::IsSSN(field.value)) {
135 values.push_back(field);
139 if (!values.empty() && database_.get())
140 database_->AddFormFields(values);
143 void AutocompleteHistoryManager::OnRemoveAutocompleteEntry(
144 const base::string16& name, const base::string16& value) {
145 if (database_.get())
146 database_->RemoveFormValueForElementName(name, value);
149 void AutocompleteHistoryManager::SetExternalDelegate(
150 AutofillExternalDelegate* delegate) {
151 external_delegate_ = delegate;
154 void AutocompleteHistoryManager::CancelPendingQuery() {
155 if (pending_query_handle_) {
156 if (database_.get())
157 database_->CancelRequest(pending_query_handle_);
158 pending_query_handle_ = 0;
162 void AutocompleteHistoryManager::SendSuggestions(
163 const std::vector<base::string16>* autocomplete_results) {
164 if (autocomplete_results) {
165 // Combine Autofill and Autocomplete values into values and labels.
166 for (const auto& new_result : *autocomplete_results) {
167 bool unique = true;
168 for (const auto& autofill_suggestion : autofill_suggestions_) {
169 // Don't add duplicate values.
170 if (new_result == autofill_suggestion.value) {
171 unique = false;
172 break;
176 if (unique)
177 autofill_suggestions_.push_back(Suggestion(new_result));
181 external_delegate_->OnSuggestionsReturned(query_id_, autofill_suggestions_);
183 query_id_ = 0;
184 autofill_suggestions_.clear();
187 } // namespace autofill