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/autofill_external_delegate.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "components/autofill/core/browser/autocomplete_history_manager.h"
9 #include "components/autofill/core/browser/autofill_driver.h"
10 #include "components/autofill/core/browser/autofill_manager.h"
11 #include "grit/component_strings.h"
12 #include "third_party/WebKit/public/web/WebAutofillClient.h"
13 #include "ui/base/l10n/l10n_util.h"
14
15 using blink::WebAutofillClient;
16
17 namespace autofill {
18
AutofillExternalDelegate(AutofillManager * autofill_manager,AutofillDriver * autofill_driver)19 AutofillExternalDelegate::AutofillExternalDelegate(
20 AutofillManager* autofill_manager,
21 AutofillDriver* autofill_driver)
22 : autofill_manager_(autofill_manager),
23 autofill_driver_(autofill_driver),
24 password_autofill_manager_(autofill_driver),
25 autofill_query_id_(0),
26 display_warning_if_disabled_(false),
27 has_autofill_suggestion_(false),
28 has_shown_autofill_popup_for_current_edit_(false),
29 weak_ptr_factory_(this) {
30 DCHECK(autofill_manager);
31 }
32
~AutofillExternalDelegate()33 AutofillExternalDelegate::~AutofillExternalDelegate() {}
34
OnQuery(int query_id,const FormData & form,const FormFieldData & field,const gfx::RectF & element_bounds,bool display_warning_if_disabled)35 void AutofillExternalDelegate::OnQuery(int query_id,
36 const FormData& form,
37 const FormFieldData& field,
38 const gfx::RectF& element_bounds,
39 bool display_warning_if_disabled) {
40 autofill_query_form_ = form;
41 autofill_query_field_ = field;
42 display_warning_if_disabled_ = display_warning_if_disabled;
43 autofill_query_id_ = query_id;
44 element_bounds_ = element_bounds;
45 }
46
OnSuggestionsReturned(int query_id,const std::vector<base::string16> & autofill_values,const std::vector<base::string16> & autofill_labels,const std::vector<base::string16> & autofill_icons,const std::vector<int> & autofill_unique_ids)47 void AutofillExternalDelegate::OnSuggestionsReturned(
48 int query_id,
49 const std::vector<base::string16>& autofill_values,
50 const std::vector<base::string16>& autofill_labels,
51 const std::vector<base::string16>& autofill_icons,
52 const std::vector<int>& autofill_unique_ids) {
53 if (query_id != autofill_query_id_)
54 return;
55
56 std::vector<base::string16> values(autofill_values);
57 std::vector<base::string16> labels(autofill_labels);
58 std::vector<base::string16> icons(autofill_icons);
59 std::vector<int> ids(autofill_unique_ids);
60
61 // Add or hide warnings as appropriate.
62 ApplyAutofillWarnings(&values, &labels, &icons, &ids);
63
64 // Add a separator to go between the values and menu items.
65 values.push_back(base::string16());
66 labels.push_back(base::string16());
67 icons.push_back(base::string16());
68 ids.push_back(WebAutofillClient::MenuItemIDSeparator);
69
70 // Only include "Autofill Options" special menu item if we have Autofill
71 // suggestions.
72 has_autofill_suggestion_ = false;
73 for (size_t i = 0; i < ids.size(); ++i) {
74 if (ids[i] > 0) {
75 has_autofill_suggestion_ = true;
76 break;
77 }
78 }
79
80 if (has_autofill_suggestion_)
81 ApplyAutofillOptions(&values, &labels, &icons, &ids);
82
83 // Remove the separator if it is the last element.
84 DCHECK_GT(ids.size(), 0U);
85 if (ids.back() == WebAutofillClient::MenuItemIDSeparator) {
86 values.pop_back();
87 labels.pop_back();
88 icons.pop_back();
89 ids.pop_back();
90 }
91
92 // If anything else is added to modify the values after inserting the data
93 // list, AutofillPopupControllerImpl::UpdateDataListValues will need to be
94 // updated to match.
95 InsertDataListValues(&values, &labels, &icons, &ids);
96
97 if (values.empty()) {
98 // No suggestions, any popup currently showing is obsolete.
99 autofill_manager_->delegate()->HideAutofillPopup();
100 return;
101 }
102
103 // Send to display.
104 if (autofill_query_field_.is_focusable) {
105 autofill_manager_->delegate()->ShowAutofillPopup(
106 element_bounds_,
107 autofill_query_field_.text_direction,
108 values,
109 labels,
110 icons,
111 ids,
112 GetWeakPtr());
113 }
114 }
115
OnShowPasswordSuggestions(const std::vector<base::string16> & suggestions,const std::vector<base::string16> & realms,const FormFieldData & field,const gfx::RectF & element_bounds)116 void AutofillExternalDelegate::OnShowPasswordSuggestions(
117 const std::vector<base::string16>& suggestions,
118 const std::vector<base::string16>& realms,
119 const FormFieldData& field,
120 const gfx::RectF& element_bounds) {
121 autofill_query_field_ = field;
122 element_bounds_ = element_bounds;
123
124 if (suggestions.empty()) {
125 autofill_manager_->delegate()->HideAutofillPopup();
126 return;
127 }
128
129 std::vector<base::string16> empty(suggestions.size());
130 std::vector<int> password_ids(suggestions.size(),
131 WebAutofillClient::MenuItemIDPasswordEntry);
132 autofill_manager_->delegate()->ShowAutofillPopup(
133 element_bounds_,
134 autofill_query_field_.text_direction,
135 suggestions,
136 realms,
137 empty,
138 password_ids,
139 GetWeakPtr());
140 }
141
SetCurrentDataListValues(const std::vector<base::string16> & data_list_values,const std::vector<base::string16> & data_list_labels)142 void AutofillExternalDelegate::SetCurrentDataListValues(
143 const std::vector<base::string16>& data_list_values,
144 const std::vector<base::string16>& data_list_labels) {
145 data_list_values_ = data_list_values;
146 data_list_labels_ = data_list_labels;
147
148 autofill_manager_->delegate()->UpdateAutofillPopupDataListValues(
149 data_list_values,
150 data_list_labels);
151 }
152
OnPopupShown()153 void AutofillExternalDelegate::OnPopupShown() {
154 autofill_manager_->OnDidShowAutofillSuggestions(
155 has_autofill_suggestion_ && !has_shown_autofill_popup_for_current_edit_);
156 has_shown_autofill_popup_for_current_edit_ |= has_autofill_suggestion_;
157 }
158
OnPopupHidden()159 void AutofillExternalDelegate::OnPopupHidden() {
160 }
161
ShouldRepostEvent(const ui::MouseEvent & event)162 bool AutofillExternalDelegate::ShouldRepostEvent(const ui::MouseEvent& event) {
163 NOTREACHED();
164 return true;
165 }
166
DidSelectSuggestion(int identifier)167 void AutofillExternalDelegate::DidSelectSuggestion(int identifier) {
168 ClearPreviewedForm();
169
170 // Only preview the data if it is a profile.
171 if (identifier > 0)
172 FillAutofillFormData(identifier, true);
173 }
174
DidAcceptSuggestion(const base::string16 & value,int identifier)175 void AutofillExternalDelegate::DidAcceptSuggestion(const base::string16& value,
176 int identifier) {
177 if (identifier == WebAutofillClient::MenuItemIDAutofillOptions) {
178 // User selected 'Autofill Options'.
179 autofill_manager_->OnShowAutofillDialog();
180 } else if (identifier == WebAutofillClient::MenuItemIDClearForm) {
181 // User selected 'Clear form'.
182 autofill_driver_->RendererShouldClearFilledForm();
183 } else if (identifier == WebAutofillClient::MenuItemIDPasswordEntry) {
184 bool success = password_autofill_manager_.DidAcceptAutofillSuggestion(
185 autofill_query_field_, value);
186 DCHECK(success);
187 } else if (identifier == WebAutofillClient::MenuItemIDDataListEntry) {
188 autofill_driver_->RendererShouldAcceptDataListSuggestion(value);
189 } else if (identifier == WebAutofillClient::MenuItemIDAutocompleteEntry) {
190 // User selected an Autocomplete, so we fill directly.
191 autofill_driver_->RendererShouldSetNodeText(value);
192 } else {
193 FillAutofillFormData(identifier, false);
194 }
195
196 autofill_manager_->delegate()->HideAutofillPopup();
197 }
198
RemoveSuggestion(const base::string16 & value,int identifier)199 void AutofillExternalDelegate::RemoveSuggestion(const base::string16& value,
200 int identifier) {
201 if (identifier > 0) {
202 autofill_manager_->RemoveAutofillProfileOrCreditCard(identifier);
203 } else {
204 autofill_manager_->RemoveAutocompleteEntry(autofill_query_field_.name,
205 value);
206 }
207 }
208
DidEndTextFieldEditing()209 void AutofillExternalDelegate::DidEndTextFieldEditing() {
210 autofill_manager_->delegate()->HideAutofillPopup();
211
212 has_shown_autofill_popup_for_current_edit_ = false;
213 }
214
ClearPreviewedForm()215 void AutofillExternalDelegate::ClearPreviewedForm() {
216 autofill_driver_->RendererShouldClearPreviewedForm();
217 }
218
Reset()219 void AutofillExternalDelegate::Reset() {
220 autofill_manager_->delegate()->HideAutofillPopup();
221
222 password_autofill_manager_.Reset();
223 }
224
AddPasswordFormMapping(const FormFieldData & form,const PasswordFormFillData & fill_data)225 void AutofillExternalDelegate::AddPasswordFormMapping(
226 const FormFieldData& form,
227 const PasswordFormFillData& fill_data) {
228 password_autofill_manager_.AddPasswordFormMapping(form, fill_data);
229 }
230
GetWeakPtr()231 base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() {
232 return weak_ptr_factory_.GetWeakPtr();
233 }
234
FillAutofillFormData(int unique_id,bool is_preview)235 void AutofillExternalDelegate::FillAutofillFormData(int unique_id,
236 bool is_preview) {
237 // If the selected element is a warning we don't want to do anything.
238 if (unique_id == WebAutofillClient::MenuItemIDWarningMessage)
239 return;
240
241 AutofillDriver::RendererFormDataAction renderer_action = is_preview ?
242 AutofillDriver::FORM_DATA_ACTION_PREVIEW :
243 AutofillDriver::FORM_DATA_ACTION_FILL;
244
245 DCHECK(autofill_driver_->RendererIsAvailable());
246 autofill_driver_->SetRendererActionOnFormDataReception(renderer_action);
247 // Fill the values for the whole form.
248 autofill_manager_->OnFillAutofillFormData(autofill_query_id_,
249 autofill_query_form_,
250 autofill_query_field_,
251 unique_id);
252 }
253
ApplyAutofillWarnings(std::vector<base::string16> * autofill_values,std::vector<base::string16> * autofill_labels,std::vector<base::string16> * autofill_icons,std::vector<int> * autofill_unique_ids)254 void AutofillExternalDelegate::ApplyAutofillWarnings(
255 std::vector<base::string16>* autofill_values,
256 std::vector<base::string16>* autofill_labels,
257 std::vector<base::string16>* autofill_icons,
258 std::vector<int>* autofill_unique_ids) {
259 if (!autofill_query_field_.should_autocomplete) {
260 // Autofill is disabled. If there were some profile or credit card
261 // suggestions to show, show a warning instead. Otherwise, clear out the
262 // list of suggestions.
263 if (!autofill_unique_ids->empty() && (*autofill_unique_ids)[0] > 0) {
264 // If autofill is disabled and we had suggestions, show a warning instead.
265 autofill_values->assign(
266 1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED));
267 autofill_labels->assign(1, base::string16());
268 autofill_icons->assign(1, base::string16());
269 autofill_unique_ids->assign(1,
270 WebAutofillClient::MenuItemIDWarningMessage);
271 } else {
272 autofill_values->clear();
273 autofill_labels->clear();
274 autofill_icons->clear();
275 autofill_unique_ids->clear();
276 }
277 } else if (autofill_unique_ids->size() > 1 &&
278 (*autofill_unique_ids)[0] ==
279 WebAutofillClient::MenuItemIDWarningMessage) {
280 // If we received a warning instead of suggestions from autofill but regular
281 // suggestions from autocomplete, don't show the autofill warning.
282 autofill_values->erase(autofill_values->begin());
283 autofill_labels->erase(autofill_labels->begin());
284 autofill_icons->erase(autofill_icons->begin());
285 autofill_unique_ids->erase(autofill_unique_ids->begin());
286 }
287
288 // If we were about to show a warning and we shouldn't, don't.
289 if (!autofill_unique_ids->empty() &&
290 (*autofill_unique_ids)[0] ==
291 WebAutofillClient::MenuItemIDWarningMessage &&
292 !display_warning_if_disabled_) {
293 autofill_values->clear();
294 autofill_labels->clear();
295 autofill_icons->clear();
296 autofill_unique_ids->clear();
297 }
298 }
299
ApplyAutofillOptions(std::vector<base::string16> * autofill_values,std::vector<base::string16> * autofill_labels,std::vector<base::string16> * autofill_icons,std::vector<int> * autofill_unique_ids)300 void AutofillExternalDelegate::ApplyAutofillOptions(
301 std::vector<base::string16>* autofill_values,
302 std::vector<base::string16>* autofill_labels,
303 std::vector<base::string16>* autofill_icons,
304 std::vector<int>* autofill_unique_ids) {
305 // The form has been auto-filled, so give the user the chance to clear the
306 // form. Append the 'Clear form' menu item.
307 if (autofill_query_field_.is_autofilled) {
308 autofill_values->push_back(
309 l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM));
310 autofill_labels->push_back(base::string16());
311 autofill_icons->push_back(base::string16());
312 autofill_unique_ids->push_back(WebAutofillClient::MenuItemIDClearForm);
313 }
314
315 // Append the 'Chrome Autofill options' menu item;
316 autofill_values->push_back(
317 l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_POPUP));
318 autofill_labels->push_back(base::string16());
319 autofill_icons->push_back(base::string16());
320 autofill_unique_ids->push_back(WebAutofillClient::MenuItemIDAutofillOptions);
321 }
322
InsertDataListValues(std::vector<base::string16> * autofill_values,std::vector<base::string16> * autofill_labels,std::vector<base::string16> * autofill_icons,std::vector<int> * autofill_unique_ids)323 void AutofillExternalDelegate::InsertDataListValues(
324 std::vector<base::string16>* autofill_values,
325 std::vector<base::string16>* autofill_labels,
326 std::vector<base::string16>* autofill_icons,
327 std::vector<int>* autofill_unique_ids) {
328 if (data_list_values_.empty())
329 return;
330
331 // Insert the separator between the datalist and Autofill values (if there
332 // are any).
333 if (!autofill_values->empty()) {
334 autofill_values->insert(autofill_values->begin(), base::string16());
335 autofill_labels->insert(autofill_labels->begin(), base::string16());
336 autofill_icons->insert(autofill_icons->begin(), base::string16());
337 autofill_unique_ids->insert(autofill_unique_ids->begin(),
338 WebAutofillClient::MenuItemIDSeparator);
339 }
340
341 // Insert the datalist elements.
342 autofill_values->insert(autofill_values->begin(),
343 data_list_values_.begin(),
344 data_list_values_.end());
345 autofill_labels->insert(autofill_labels->begin(),
346 data_list_labels_.begin(),
347 data_list_labels_.end());
348
349 // Set the values that all datalist elements share.
350 autofill_icons->insert(autofill_icons->begin(),
351 data_list_values_.size(),
352 base::string16());
353 autofill_unique_ids->insert(autofill_unique_ids->begin(),
354 data_list_values_.size(),
355 WebAutofillClient::MenuItemIDDataListEntry);
356 }
357
358 } // namespace autofill
359