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"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "components/autofill/core/browser/autofill_client.h"
13 #include "components/autofill/core/browser/autofill_driver.h"
14 #include "components/autofill/core/browser/autofill_external_delegate.h"
15 #include "components/autofill/core/browser/validation.h"
16 #include "components/autofill/core/common/autofill_pref_names.h"
17 #include "components/autofill/core/common/form_data.h"
22 // Limit on the number of suggestions to appear in the pop-up menu under an
23 // text input element in a form.
24 const int kMaxAutocompleteMenuItems
= 6;
26 bool IsTextField(const FormFieldData
& field
) {
28 field
.form_control_type
== "text" ||
29 field
.form_control_type
== "search" ||
30 field
.form_control_type
== "tel" ||
31 field
.form_control_type
== "url" ||
32 field
.form_control_type
== "email";
37 AutocompleteHistoryManager::AutocompleteHistoryManager(
38 AutofillDriver
* driver
,
39 AutofillClient
* autofill_client
)
41 database_(autofill_client
->GetDatabase()),
42 pending_query_handle_(0),
44 external_delegate_(NULL
),
45 autofill_client_(autofill_client
) {
46 DCHECK(autofill_client_
);
49 AutocompleteHistoryManager::~AutocompleteHistoryManager() {
53 void AutocompleteHistoryManager::OnWebDataServiceRequestDone(
54 WebDataServiceBase::Handle h
,
55 const WDTypedResult
* result
) {
56 DCHECK(pending_query_handle_
);
57 pending_query_handle_
= 0;
59 if (!autofill_client_
->IsAutocompleteEnabled()) {
60 SendSuggestions(NULL
);
65 // Returning early here if |result| is NULL. We've seen this happen on
66 // Linux due to NFS dismounting and causing sql failures.
67 // See http://crbug.com/68783.
69 SendSuggestions(NULL
);
73 DCHECK_EQ(AUTOFILL_VALUE_RESULT
, result
->GetType());
74 const WDResult
<std::vector
<base::string16
> >* autofill_result
=
75 static_cast<const WDResult
<std::vector
<base::string16
> >*>(result
);
76 std::vector
<base::string16
> suggestions
= autofill_result
->GetValue();
77 SendSuggestions(&suggestions
);
80 void AutocompleteHistoryManager::OnGetAutocompleteSuggestions(
82 const base::string16
& name
,
83 const base::string16
& prefix
,
84 const std::string
& form_control_type
,
85 const std::vector
<Suggestion
>& suggestions
) {
89 autofill_suggestions_
= suggestions
;
90 if (!autofill_client_
->IsAutocompleteEnabled() ||
91 form_control_type
== "textarea") {
92 SendSuggestions(NULL
);
96 if (database_
.get()) {
97 pending_query_handle_
= database_
->GetFormValuesForElementName(
98 name
, prefix
, kMaxAutocompleteMenuItems
, this);
102 void AutocompleteHistoryManager::OnFormSubmitted(const FormData
& form
) {
103 if (!autofill_client_
->IsAutocompleteEnabled())
106 if (driver_
->IsOffTheRecord())
109 // Don't save data that was submitted through JavaScript.
110 if (!form
.user_submitted
)
113 // We put the following restriction on stored FormFields:
117 // - autocomplete is not disabled
118 // - value is not a credit card number
119 // - value is not a SSN
120 std::vector
<FormFieldData
> values
;
121 for (std::vector
<FormFieldData
>::const_iterator iter
=
123 iter
!= form
.fields
.end(); ++iter
) {
124 if (!iter
->value
.empty() &&
125 !iter
->name
.empty() &&
126 IsTextField(*iter
) &&
127 iter
->should_autocomplete
&&
128 !autofill::IsValidCreditCardNumber(iter
->value
) &&
129 !autofill::IsSSN(iter
->value
)) {
130 values
.push_back(*iter
);
134 if (!values
.empty() && database_
.get())
135 database_
->AddFormFields(values
);
138 void AutocompleteHistoryManager::OnRemoveAutocompleteEntry(
139 const base::string16
& name
, const base::string16
& value
) {
141 database_
->RemoveFormValueForElementName(name
, value
);
144 void AutocompleteHistoryManager::SetExternalDelegate(
145 AutofillExternalDelegate
* delegate
) {
146 external_delegate_
= delegate
;
149 void AutocompleteHistoryManager::CancelPendingQuery() {
150 if (pending_query_handle_
) {
152 database_
->CancelRequest(pending_query_handle_
);
153 pending_query_handle_
= 0;
157 void AutocompleteHistoryManager::SendSuggestions(
158 const std::vector
<base::string16
>* autocomplete_results
) {
159 if (autocomplete_results
) {
160 // Combine Autofill and Autocomplete values into values and labels.
161 for (const auto& new_result
: *autocomplete_results
) {
163 for (const auto& autofill_suggestion
: autofill_suggestions_
) {
164 // Don't add duplicate values.
165 if (new_result
== autofill_suggestion
.value
) {
172 autofill_suggestions_
.push_back(Suggestion(new_result
));
176 external_delegate_
->OnSuggestionsReturned(query_id_
, autofill_suggestions_
);
179 autofill_suggestions_
.clear();
182 } // namespace autofill