• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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