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