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