Update To 11.40.268.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/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"
19
20 namespace autofill {
21 namespace {
22
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;
26
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";
34 }
35
36 }  // namespace
37
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_);
48 }
49
50 AutocompleteHistoryManager::~AutocompleteHistoryManager() {
51   CancelPendingQuery();
52 }
53
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"));
61
62   DCHECK(pending_query_handle_);
63   pending_query_handle_ = 0;
64
65   if (!autofill_client_->IsAutocompleteEnabled()) {
66     SendSuggestions(NULL);
67     return;
68   }
69
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;
77   }
78
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);
84 }
85
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();
96
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;
106   }
107
108   if (database_.get()) {
109     pending_query_handle_ = database_->GetFormValuesForElementName(
110         name, prefix, kMaxAutocompleteMenuItems, this);
111   }
112 }
113
114 void AutocompleteHistoryManager::OnFormSubmitted(const FormData& form) {
115   if (!autofill_client_->IsAutocompleteEnabled())
116     return;
117
118   if (driver_->IsOffTheRecord())
119     return;
120
121   // Don't save data that was submitted through JavaScript.
122   if (!form.user_submitted)
123     return;
124
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);
143     }
144   }
145
146   if (!values.empty() && database_.get())
147     database_->AddFormFields(values);
148 }
149
150 void AutocompleteHistoryManager::OnRemoveAutocompleteEntry(
151     const base::string16& name, const base::string16& value) {
152   if (database_.get())
153     database_->RemoveFormValueForElementName(name, value);
154 }
155
156 void AutocompleteHistoryManager::SetExternalDelegate(
157     AutofillExternalDelegate* delegate) {
158   external_delegate_ = delegate;
159 }
160
161 void AutocompleteHistoryManager::CancelPendingQuery() {
162   if (pending_query_handle_) {
163     if (database_.get())
164       database_->CancelRequest(pending_query_handle_);
165     pending_query_handle_ = 0;
166   }
167 }
168
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;
180         }
181       }
182
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.
188       }
189     }
190   }
191
192   external_delegate_->OnSuggestionsReturned(query_id_,
193                                             autofill_values_,
194                                             autofill_labels_,
195                                             autofill_icons_,
196                                             autofill_unique_ids_);
197
198   query_id_ = 0;
199   autofill_values_.clear();
200   autofill_labels_.clear();
201   autofill_icons_.clear();
202   autofill_unique_ids_.clear();
203 }
204
205 }  // namespace autofill