Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / components / autofill / core / browser / autocomplete_history_manager.cc
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.
4
5 #include "components/autofill/core/browser/autocomplete_history_manager.h"
6
7 #include <vector>
8
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"
18
19 namespace autofill {
20 namespace {
21
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;
25
26 bool IsTextField(const FormFieldData& field) {
27   return
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";
33 }
34
35 }  // namespace
36
37 AutocompleteHistoryManager::AutocompleteHistoryManager(
38     AutofillDriver* driver,
39     AutofillClient* autofill_client)
40     : driver_(driver),
41       database_(autofill_client->GetDatabase()),
42       pending_query_handle_(0),
43       query_id_(0),
44       external_delegate_(NULL),
45       autofill_client_(autofill_client) {
46   DCHECK(autofill_client_);
47 }
48
49 AutocompleteHistoryManager::~AutocompleteHistoryManager() {
50   CancelPendingQuery();
51 }
52
53 void AutocompleteHistoryManager::OnWebDataServiceRequestDone(
54     WebDataServiceBase::Handle h,
55     const WDTypedResult* result) {
56   DCHECK(pending_query_handle_);
57   pending_query_handle_ = 0;
58
59   if (!autofill_client_->IsAutocompleteEnabled()) {
60     SendSuggestions(NULL);
61     return;
62   }
63
64   DCHECK(result);
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.
68   if (!result) {
69     SendSuggestions(NULL);
70     return;
71   }
72
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);
78 }
79
80 void AutocompleteHistoryManager::OnGetAutocompleteSuggestions(
81     int query_id,
82     const base::string16& name,
83     const base::string16& prefix,
84     const std::string form_control_type,
85     const std::vector<base::string16>& autofill_values,
86     const std::vector<base::string16>& autofill_labels,
87     const std::vector<base::string16>& autofill_icons,
88     const std::vector<int>& autofill_unique_ids) {
89   CancelPendingQuery();
90
91   query_id_ = query_id;
92   autofill_values_ = autofill_values;
93   autofill_labels_ = autofill_labels;
94   autofill_icons_ = autofill_icons;
95   autofill_unique_ids_ = autofill_unique_ids;
96   if (!autofill_client_->IsAutocompleteEnabled() ||
97       form_control_type == "textarea") {
98     SendSuggestions(NULL);
99     return;
100   }
101
102   if (database_.get()) {
103     pending_query_handle_ = database_->GetFormValuesForElementName(
104         name, prefix, kMaxAutocompleteMenuItems, this);
105   }
106 }
107
108 void AutocompleteHistoryManager::OnFormSubmitted(const FormData& form) {
109   if (!autofill_client_->IsAutocompleteEnabled())
110     return;
111
112   if (driver_->IsOffTheRecord())
113     return;
114
115   // Don't save data that was submitted through JavaScript.
116   if (!form.user_submitted)
117     return;
118
119   // We put the following restriction on stored FormFields:
120   //  - non-empty name
121   //  - non-empty value
122   //  - text field
123   //  - value is not a credit card number
124   //  - value is not a SSN
125   std::vector<FormFieldData> values;
126   for (std::vector<FormFieldData>::const_iterator iter =
127            form.fields.begin();
128        iter != form.fields.end(); ++iter) {
129     if (!iter->value.empty() &&
130         !iter->name.empty() &&
131         IsTextField(*iter) &&
132         !autofill::IsValidCreditCardNumber(iter->value) &&
133         !autofill::IsSSN(iter->value)) {
134       values.push_back(*iter);
135     }
136   }
137
138   if (!values.empty() && database_.get())
139     database_->AddFormFields(values);
140 }
141
142 void AutocompleteHistoryManager::OnRemoveAutocompleteEntry(
143     const base::string16& name, const base::string16& value) {
144   if (database_.get())
145     database_->RemoveFormValueForElementName(name, value);
146 }
147
148 void AutocompleteHistoryManager::SetExternalDelegate(
149     AutofillExternalDelegate* delegate) {
150   external_delegate_ = delegate;
151 }
152
153 void AutocompleteHistoryManager::CancelPendingQuery() {
154   if (pending_query_handle_) {
155     if (database_.get())
156       database_->CancelRequest(pending_query_handle_);
157     pending_query_handle_ = 0;
158   }
159 }
160
161 void AutocompleteHistoryManager::SendSuggestions(
162     const std::vector<base::string16>* suggestions) {
163   if (suggestions) {
164     // Combine Autofill and Autocomplete values into values and labels.
165     for (size_t i = 0; i < suggestions->size(); ++i) {
166       bool unique = true;
167       for (size_t j = 0; j < autofill_values_.size(); ++j) {
168         // Don't add duplicate values.
169         if (autofill_values_[j] == (*suggestions)[i]) {
170           unique = false;
171           break;
172         }
173       }
174
175       if (unique) {
176         autofill_values_.push_back((*suggestions)[i]);
177         autofill_labels_.push_back(base::string16());
178         autofill_icons_.push_back(base::string16());
179         autofill_unique_ids_.push_back(0);  // 0 means no profile.
180       }
181     }
182   }
183
184   external_delegate_->OnSuggestionsReturned(query_id_,
185                                             autofill_values_,
186                                             autofill_labels_,
187                                             autofill_icons_,
188                                             autofill_unique_ids_);
189
190   query_id_ = 0;
191   autofill_values_.clear();
192   autofill_labels_.clear();
193   autofill_icons_.clear();
194   autofill_unique_ids_.clear();
195 }
196
197 }  // namespace autofill