Home | History | Annotate | Download | only in browser
      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 
     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 
     33 AutofillExternalDelegate::~AutofillExternalDelegate() {}
     34 
     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 
     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 
    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 
    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 
    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 
    159 void AutofillExternalDelegate::OnPopupHidden() {
    160 }
    161 
    162 bool AutofillExternalDelegate::ShouldRepostEvent(const ui::MouseEvent& event) {
    163   NOTREACHED();
    164   return true;
    165 }
    166 
    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 
    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 
    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 
    209 void AutofillExternalDelegate::DidEndTextFieldEditing() {
    210   autofill_manager_->delegate()->HideAutofillPopup();
    211 
    212   has_shown_autofill_popup_for_current_edit_ = false;
    213 }
    214 
    215 void AutofillExternalDelegate::ClearPreviewedForm() {
    216   autofill_driver_->RendererShouldClearPreviewedForm();
    217 }
    218 
    219 void AutofillExternalDelegate::Reset() {
    220   autofill_manager_->delegate()->HideAutofillPopup();
    221 
    222   password_autofill_manager_.Reset();
    223 }
    224 
    225 void AutofillExternalDelegate::AddPasswordFormMapping(
    226       const FormFieldData& form,
    227       const PasswordFormFillData& fill_data) {
    228   password_autofill_manager_.AddPasswordFormMapping(form, fill_data);
    229 }
    230 
    231 base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() {
    232   return weak_ptr_factory_.GetWeakPtr();
    233 }
    234 
    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 
    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 
    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 
    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