OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/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/browser/autofill_driver.h" | |
13 #include "components/autofill/browser/autofill_external_delegate.h" | |
14 #include "components/autofill/browser/validation.h" | |
15 #include "components/autofill/core/common/autofill_messages.h" | |
16 #include "components/autofill/core/common/autofill_pref_names.h" | |
17 #include "components/autofill/core/common/form_data.h" | |
18 #include "components/user_prefs/user_prefs.h" | |
19 #include "content/public/browser/browser_context.h" | |
20 #include "content/public/browser/render_view_host.h" | |
21 #include "content/public/browser/web_contents.h" | |
22 #include "ipc/ipc_message_macros.h" | |
23 | |
24 using content::BrowserContext; | |
25 using content::WebContents; | |
26 | |
27 namespace autofill { | |
28 namespace { | |
29 | |
30 // Limit on the number of suggestions to appear in the pop-up menu under an | |
31 // text input element in a form. | |
32 const int kMaxAutocompleteMenuItems = 6; | |
33 | |
34 bool IsTextField(const FormFieldData& field) { | |
35 return | |
36 field.form_control_type == "text" || | |
37 field.form_control_type == "search" || | |
38 field.form_control_type == "tel" || | |
39 field.form_control_type == "url" || | |
40 field.form_control_type == "email" || | |
41 field.form_control_type == "text"; | |
42 } | |
43 | |
44 } // namespace | |
45 | |
46 AutocompleteHistoryManager::AutocompleteHistoryManager(AutofillDriver* driver) | |
47 : browser_context_(driver->GetWebContents()->GetBrowserContext()), | |
48 driver_(driver), | |
49 autofill_data_( | |
50 AutofillWebDataService::FromBrowserContext(browser_context_)), | |
51 pending_query_handle_(0), | |
52 query_id_(0), | |
53 external_delegate_(NULL), | |
54 send_ipc_(true) { | |
55 autofill_enabled_.Init( | |
56 prefs::kAutofillEnabled, | |
57 user_prefs::UserPrefs::Get(browser_context_)); | |
58 } | |
59 | |
60 AutocompleteHistoryManager::~AutocompleteHistoryManager() { | |
61 CancelPendingQuery(); | |
62 } | |
63 | |
64 void AutocompleteHistoryManager::OnWebDataServiceRequestDone( | |
65 WebDataServiceBase::Handle h, | |
66 const WDTypedResult* result) { | |
67 DCHECK(pending_query_handle_); | |
68 pending_query_handle_ = 0; | |
69 | |
70 if (!*autofill_enabled_) { | |
71 SendSuggestions(NULL); | |
72 return; | |
73 } | |
74 | |
75 DCHECK(result); | |
76 // Returning early here if |result| is NULL. We've seen this happen on | |
77 // Linux due to NFS dismounting and causing sql failures. | |
78 // See http://crbug.com/68783. | |
79 if (!result) { | |
80 SendSuggestions(NULL); | |
81 return; | |
82 } | |
83 | |
84 DCHECK_EQ(AUTOFILL_VALUE_RESULT, result->GetType()); | |
85 const WDResult<std::vector<base::string16> >* autofill_result = | |
86 static_cast<const WDResult<std::vector<base::string16> >*>(result); | |
87 std::vector<base::string16> suggestions = autofill_result->GetValue(); | |
88 SendSuggestions(&suggestions); | |
89 } | |
90 | |
91 void AutocompleteHistoryManager::OnGetAutocompleteSuggestions( | |
92 int query_id, | |
93 const base::string16& name, | |
94 const base::string16& prefix, | |
95 const std::vector<base::string16>& autofill_values, | |
96 const std::vector<base::string16>& autofill_labels, | |
97 const std::vector<string16>& autofill_icons, | |
98 const std::vector<int>& autofill_unique_ids) { | |
99 CancelPendingQuery(); | |
100 | |
101 query_id_ = query_id; | |
102 autofill_values_ = autofill_values; | |
103 autofill_labels_ = autofill_labels; | |
104 autofill_icons_ = autofill_icons; | |
105 autofill_unique_ids_ = autofill_unique_ids; | |
106 if (!*autofill_enabled_) { | |
107 SendSuggestions(NULL); | |
108 return; | |
109 } | |
110 | |
111 if (autofill_data_.get()) { | |
112 pending_query_handle_ = autofill_data_->GetFormValuesForElementName( | |
113 name, prefix, kMaxAutocompleteMenuItems, this); | |
114 } | |
115 } | |
116 | |
117 void AutocompleteHistoryManager::OnFormSubmitted(const FormData& form) { | |
118 if (!*autofill_enabled_) | |
119 return; | |
120 | |
121 if (browser_context_->IsOffTheRecord()) | |
122 return; | |
123 | |
124 // Don't save data that was submitted through JavaScript. | |
125 if (!form.user_submitted) | |
126 return; | |
127 | |
128 // We put the following restriction on stored FormFields: | |
129 // - non-empty name | |
130 // - non-empty value | |
131 // - text field | |
132 // - value is not a credit card number | |
133 // - value is not a SSN | |
134 std::vector<FormFieldData> values; | |
135 for (std::vector<FormFieldData>::const_iterator iter = | |
136 form.fields.begin(); | |
137 iter != form.fields.end(); ++iter) { | |
138 if (!iter->value.empty() && | |
139 !iter->name.empty() && | |
140 IsTextField(*iter) && | |
141 !autofill::IsValidCreditCardNumber(iter->value) && | |
142 !autofill::IsSSN(iter->value)) { | |
143 values.push_back(*iter); | |
144 } | |
145 } | |
146 | |
147 if (!values.empty() && autofill_data_.get()) | |
148 autofill_data_->AddFormFields(values); | |
149 } | |
150 | |
151 void AutocompleteHistoryManager::OnRemoveAutocompleteEntry( | |
152 const base::string16& name, const base::string16& value) { | |
153 if (autofill_data_.get()) | |
154 autofill_data_->RemoveFormValueForElementName(name, value); | |
155 } | |
156 | |
157 void AutocompleteHistoryManager::SetExternalDelegate( | |
158 AutofillExternalDelegate* delegate) { | |
159 external_delegate_ = delegate; | |
160 } | |
161 | |
162 void AutocompleteHistoryManager::CancelPendingQuery() { | |
163 if (pending_query_handle_) { | |
164 if (autofill_data_.get()) | |
165 autofill_data_->CancelRequest(pending_query_handle_); | |
166 pending_query_handle_ = 0; | |
167 } | |
168 } | |
169 | |
170 void AutocompleteHistoryManager::SendSuggestions( | |
171 const std::vector<base::string16>* suggestions) { | |
172 if (suggestions) { | |
173 // Combine Autofill and Autocomplete values into values and labels. | |
174 for (size_t i = 0; i < suggestions->size(); ++i) { | |
175 bool unique = true; | |
176 for (size_t j = 0; j < autofill_values_.size(); ++j) { | |
177 // Don't add duplicate values. | |
178 if (autofill_values_[j] == (*suggestions)[i]) { | |
179 unique = false; | |
180 break; | |
181 } | |
182 } | |
183 | |
184 if (unique) { | |
185 autofill_values_.push_back((*suggestions)[i]); | |
186 autofill_labels_.push_back(base::string16()); | |
187 autofill_icons_.push_back(base::string16()); | |
188 autofill_unique_ids_.push_back(0); // 0 means no profile. | |
189 } | |
190 } | |
191 } | |
192 | |
193 if (external_delegate_) { | |
194 external_delegate_->OnSuggestionsReturned( | |
195 query_id_, | |
196 autofill_values_, | |
197 autofill_labels_, | |
198 autofill_icons_, | |
199 autofill_unique_ids_); | |
200 } else { | |
201 WebContents* web_contents = driver_->GetWebContents(); | |
202 if (web_contents && send_ipc_) { | |
203 web_contents->Send( | |
204 new AutofillMsg_SuggestionsReturned(web_contents->GetRoutingID(), | |
205 query_id_, | |
206 autofill_values_, | |
207 autofill_labels_, | |
208 autofill_icons_, | |
209 autofill_unique_ids_)); | |
210 } | |
211 } | |
212 | |
213 query_id_ = 0; | |
214 autofill_values_.clear(); | |
215 autofill_labels_.clear(); | |
216 autofill_icons_.clear(); | |
217 autofill_unique_ids_.clear(); | |
218 } | |
219 | |
220 } // namespace autofill | |
OLD | NEW |