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/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"
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
) {
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";
38 AutocompleteHistoryManager::AutocompleteHistoryManager(
39 AutofillDriver
* driver
,
40 AutofillClient
* autofill_client
)
42 database_(autofill_client
->GetDatabase()),
43 pending_query_handle_(0),
45 external_delegate_(NULL
),
46 autofill_client_(autofill_client
) {
47 DCHECK(autofill_client_
);
50 AutocompleteHistoryManager::~AutocompleteHistoryManager() {
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
);
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.
75 SendSuggestions(NULL
);
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(
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
) {
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
);
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())
118 if (driver_
->IsOffTheRecord())
121 // Don't save data that was submitted through JavaScript.
122 if (!form
.user_submitted
)
125 // We put the following restriction on stored FormFields:
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
=
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
) {
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_
) {
164 database_
->CancelRequest(pending_query_handle_
);
165 pending_query_handle_
= 0;
169 void AutocompleteHistoryManager::SendSuggestions(
170 const std::vector
<base::string16
>* suggestions
) {
172 // Combine Autofill and Autocomplete values into values and labels.
173 for (size_t i
= 0; i
< suggestions
->size(); ++i
) {
175 for (size_t j
= 0; j
< autofill_values_
.size(); ++j
) {
176 // Don't add duplicate values.
177 if (autofill_values_
[j
] == (*suggestions
)[i
]) {
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_
,
196 autofill_unique_ids_
);
199 autofill_values_
.clear();
200 autofill_labels_
.clear();
201 autofill_icons_
.clear();
202 autofill_unique_ids_
.clear();
205 } // namespace autofill