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