autofill_external_delegate.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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/common/autofill_messages.h" 12#include "content/public/browser/render_view_host.h" 13#include "content/public/browser/web_contents.h" 14#include "grit/component_strings.h" 15#include "third_party/WebKit/public/web/WebAutofillClient.h" 16#include "ui/base/l10n/l10n_util.h" 17 18#if defined(OS_ANDROID) 19#include "content/public/browser/android/content_view_core.h" 20#endif 21 22using content::RenderViewHost; 23using WebKit::WebAutofillClient; 24 25namespace autofill { 26 27AutofillExternalDelegate::AutofillExternalDelegate( 28 content::WebContents* web_contents, 29 AutofillManager* autofill_manager, 30 AutofillDriver* autofill_driver) 31 : web_contents_(web_contents), 32 autofill_manager_(autofill_manager), 33 autofill_driver_(autofill_driver), 34 password_autofill_manager_(web_contents), 35 autofill_query_id_(0), 36 display_warning_if_disabled_(false), 37 has_autofill_suggestion_(false), 38 has_shown_autofill_popup_for_current_edit_(false), 39 registered_keyboard_listener_with_(NULL), 40 weak_ptr_factory_(this) { 41 DCHECK(autofill_manager); 42} 43 44AutofillExternalDelegate::~AutofillExternalDelegate() {} 45 46void AutofillExternalDelegate::OnQuery(int query_id, 47 const FormData& form, 48 const FormFieldData& field, 49 const gfx::RectF& element_bounds, 50 bool display_warning_if_disabled) { 51 autofill_query_form_ = form; 52 autofill_query_field_ = field; 53 display_warning_if_disabled_ = display_warning_if_disabled; 54 autofill_query_id_ = query_id; 55 element_bounds_ = element_bounds; 56} 57 58void AutofillExternalDelegate::OnSuggestionsReturned( 59 int query_id, 60 const std::vector<base::string16>& autofill_values, 61 const std::vector<base::string16>& autofill_labels, 62 const std::vector<base::string16>& autofill_icons, 63 const std::vector<int>& autofill_unique_ids) { 64 if (query_id != autofill_query_id_) 65 return; 66 67 std::vector<base::string16> values(autofill_values); 68 std::vector<base::string16> labels(autofill_labels); 69 std::vector<base::string16> icons(autofill_icons); 70 std::vector<int> ids(autofill_unique_ids); 71 72 // Add or hide warnings as appropriate. 73 ApplyAutofillWarnings(&values, &labels, &icons, &ids); 74 75 // Add a separator to go between the values and menu items. 76 values.push_back(base::string16()); 77 labels.push_back(base::string16()); 78 icons.push_back(base::string16()); 79 ids.push_back(WebAutofillClient::MenuItemIDSeparator); 80 81 // Only include "Autofill Options" special menu item if we have Autofill 82 // suggestions. 83 has_autofill_suggestion_ = false; 84 for (size_t i = 0; i < ids.size(); ++i) { 85 if (ids[i] > 0) { 86 has_autofill_suggestion_ = true; 87 break; 88 } 89 } 90 91 if (has_autofill_suggestion_) 92 ApplyAutofillOptions(&values, &labels, &icons, &ids); 93 94 // Remove the separator if it is the last element. 95 DCHECK_GT(ids.size(), 0U); 96 if (ids.back() == WebAutofillClient::MenuItemIDSeparator) { 97 values.pop_back(); 98 labels.pop_back(); 99 icons.pop_back(); 100 ids.pop_back(); 101 } 102 103 InsertDataListValues(&values, &labels, &icons, &ids); 104 105 if (values.empty()) { 106 // No suggestions, any popup currently showing is obsolete. 107 autofill_manager_->delegate()->HideAutofillPopup(); 108 return; 109 } 110 111 // Send to display. 112 if (autofill_query_field_.is_focusable) { 113 autofill_manager_->delegate()->ShowAutofillPopup( 114 element_bounds_, 115 autofill_query_field_.text_direction, 116 values, 117 labels, 118 icons, 119 ids, 120 GetWeakPtr()); 121 } 122} 123 124void AutofillExternalDelegate::OnShowPasswordSuggestions( 125 const std::vector<base::string16>& suggestions, 126 const std::vector<base::string16>& realms, 127 const FormFieldData& field, 128 const gfx::RectF& element_bounds) { 129 autofill_query_field_ = field; 130 element_bounds_ = element_bounds; 131 132 if (suggestions.empty()) { 133 autofill_manager_->delegate()->HideAutofillPopup(); 134 return; 135 } 136 137 std::vector<base::string16> empty(suggestions.size()); 138 std::vector<int> password_ids(suggestions.size(), 139 WebAutofillClient::MenuItemIDPasswordEntry); 140 autofill_manager_->delegate()->ShowAutofillPopup( 141 element_bounds_, 142 autofill_query_field_.text_direction, 143 suggestions, 144 realms, 145 empty, 146 password_ids, 147 GetWeakPtr()); 148} 149 150void AutofillExternalDelegate::SetCurrentDataListValues( 151 const std::vector<base::string16>& data_list_values, 152 const std::vector<base::string16>& data_list_labels, 153 const std::vector<base::string16>& data_list_icons, 154 const std::vector<int>& data_list_unique_ids) { 155 data_list_values_ = data_list_values; 156 data_list_labels_ = data_list_labels; 157 data_list_icons_ = data_list_icons; 158 data_list_unique_ids_ = data_list_unique_ids; 159} 160 161void AutofillExternalDelegate::OnPopupShown( 162 content::KeyboardListener* listener) { 163 if (!registered_keyboard_listener_with_) { 164 registered_keyboard_listener_with_ = web_contents_->GetRenderViewHost(); 165 registered_keyboard_listener_with_->AddKeyboardListener(listener); 166 } 167 168 autofill_manager_->OnDidShowAutofillSuggestions( 169 has_autofill_suggestion_ && !has_shown_autofill_popup_for_current_edit_); 170 has_shown_autofill_popup_for_current_edit_ |= has_autofill_suggestion_; 171} 172 173void AutofillExternalDelegate::OnPopupHidden( 174 content::KeyboardListener* listener) { 175 if ((!web_contents_->IsBeingDestroyed()) && 176 (registered_keyboard_listener_with_ == 177 web_contents_->GetRenderViewHost())) { 178 web_contents_->GetRenderViewHost()->RemoveKeyboardListener(listener); 179 } 180 181 registered_keyboard_listener_with_ = NULL; 182} 183 184void AutofillExternalDelegate::DidSelectSuggestion(int identifier) { 185 ClearPreviewedForm(); 186 187 // Only preview the data if it is a profile. 188 if (identifier > 0) 189 FillAutofillFormData(identifier, true); 190} 191 192void AutofillExternalDelegate::DidAcceptSuggestion(const base::string16& value, 193 int identifier) { 194 RenderViewHost* host = web_contents_->GetRenderViewHost(); 195 196 if (identifier == WebAutofillClient::MenuItemIDAutofillOptions) { 197 // User selected 'Autofill Options'. 198 autofill_manager_->OnShowAutofillDialog(); 199 } else if (identifier == WebAutofillClient::MenuItemIDClearForm) { 200 // User selected 'Clear form'. 201 autofill_driver_->RendererShouldClearFilledForm(); 202 } else if (identifier == WebAutofillClient::MenuItemIDPasswordEntry) { 203 bool success = password_autofill_manager_.DidAcceptAutofillSuggestion( 204 autofill_query_field_, value); 205 DCHECK(success); 206 } else if (identifier == WebAutofillClient::MenuItemIDDataListEntry) { 207 host->Send(new AutofillMsg_AcceptDataListSuggestion(host->GetRoutingID(), 208 value)); 209 } else if (identifier == WebAutofillClient::MenuItemIDAutocompleteEntry) { 210 // User selected an Autocomplete, so we fill directly. 211 host->Send(new AutofillMsg_SetNodeText(host->GetRoutingID(), value)); 212 } else { 213 FillAutofillFormData(identifier, false); 214 } 215 216 autofill_manager_->delegate()->HideAutofillPopup(); 217} 218 219void AutofillExternalDelegate::RemoveSuggestion(const base::string16& value, 220 int identifier) { 221 if (identifier > 0) { 222 autofill_manager_->RemoveAutofillProfileOrCreditCard(identifier); 223 } else { 224 autofill_manager_->RemoveAutocompleteEntry(autofill_query_field_.name, 225 value); 226 } 227} 228 229void AutofillExternalDelegate::DidEndTextFieldEditing() { 230 autofill_manager_->delegate()->HideAutofillPopup(); 231 232 has_shown_autofill_popup_for_current_edit_ = false; 233} 234 235void AutofillExternalDelegate::ClearPreviewedForm() { 236 autofill_driver_->RendererShouldClearPreviewedForm(); 237} 238 239void AutofillExternalDelegate::Reset() { 240 autofill_manager_->delegate()->HideAutofillPopup(); 241 242 password_autofill_manager_.Reset(); 243} 244 245void AutofillExternalDelegate::AddPasswordFormMapping( 246 const FormFieldData& form, 247 const PasswordFormFillData& fill_data) { 248 password_autofill_manager_.AddPasswordFormMapping(form, fill_data); 249} 250 251base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() { 252 return weak_ptr_factory_.GetWeakPtr(); 253} 254 255void AutofillExternalDelegate::FillAutofillFormData(int unique_id, 256 bool is_preview) { 257 // If the selected element is a warning we don't want to do anything. 258 if (unique_id == WebAutofillClient::MenuItemIDWarningMessage) 259 return; 260 261 AutofillDriver::RendererFormDataAction renderer_action = is_preview ? 262 AutofillDriver::FORM_DATA_ACTION_PREVIEW : 263 AutofillDriver::FORM_DATA_ACTION_FILL; 264 265 DCHECK(autofill_driver_->RendererIsAvailable()); 266 autofill_driver_->SetRendererActionOnFormDataReception(renderer_action); 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