| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/autofill/core/browser/autofill_external_delegate.h" | 5 #include "components/autofill/core/browser/autofill_external_delegate.h" |
| 6 | 6 |
| 7 #include "base/message_loop/message_loop.h" |
| 8 #include "base/metrics/histogram.h" |
| 7 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 8 #include "components/autofill/core/browser/autocomplete_history_manager.h" | 10 #include "components/autofill/core/browser/autocomplete_history_manager.h" |
| 9 #include "components/autofill/core/browser/autofill_driver.h" | 11 #include "components/autofill/core/browser/autofill_driver.h" |
| 10 #include "components/autofill/core/browser/autofill_manager.h" | 12 #include "components/autofill/core/browser/autofill_manager.h" |
| 11 #include "components/autofill/core/browser/popup_item_ids.h" | 13 #include "components/autofill/core/browser/popup_item_ids.h" |
| 12 #include "grit/components_strings.h" | 14 #include "grit/components_strings.h" |
| 13 #include "ui/base/l10n/l10n_util.h" | 15 #include "ui/base/l10n/l10n_util.h" |
| 14 | 16 |
| 17 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 18 namespace { |
| 19 |
| 20 enum AccessAddressBookEventType { |
| 21 // An Autofill entry was shown that prompts the user to give Chrome access to |
| 22 // the user's Address Book. |
| 23 SHOWED_ACCESS_ADDRESS_BOOK_ENTRY = 0, |
| 24 |
| 25 // The user selected the Autofill entry which prompts Chrome to access the |
| 26 // user's Address Book. |
| 27 SELECTED_ACCESS_ADDRESS_BOOK_ENTRY = 1, |
| 28 |
| 29 // Always keep this at the end. |
| 30 ACCESS_ADDRESS_BOOK_ENTRY_MAX, |
| 31 }; |
| 32 |
| 33 // Emits an entry for the histogram. |
| 34 void EmitHistogram(AccessAddressBookEventType type) { |
| 35 UMA_HISTOGRAM_ENUMERATION( |
| 36 "Autofill.MacAddressBook", type, ACCESS_ADDRESS_BOOK_ENTRY_MAX); |
| 37 } |
| 38 |
| 39 } // namespace |
| 40 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 41 |
| 15 namespace autofill { | 42 namespace autofill { |
| 16 | 43 |
| 17 AutofillExternalDelegate::AutofillExternalDelegate( | 44 AutofillExternalDelegate::AutofillExternalDelegate(AutofillManager* manager, |
| 18 AutofillManager* manager, | 45 AutofillDriver* driver) |
| 19 AutofillDriver* driver) | |
| 20 : manager_(manager), | 46 : manager_(manager), |
| 21 driver_(driver), | 47 driver_(driver), |
| 22 query_id_(0), | 48 query_id_(0), |
| 23 display_warning_if_disabled_(false), | 49 display_warning_if_disabled_(false), |
| 24 has_suggestion_(false), | 50 has_suggestion_(false), |
| 25 has_shown_popup_for_current_edit_(false), | 51 has_shown_popup_for_current_edit_(false), |
| 26 weak_ptr_factory_(this) { | 52 weak_ptr_factory_(this) { |
| 27 DCHECK(manager); | 53 DCHECK(manager); |
| 28 } | 54 } |
| 29 | 55 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 labels.pop_back(); | 110 labels.pop_back(); |
| 85 icons.pop_back(); | 111 icons.pop_back(); |
| 86 ids.pop_back(); | 112 ids.pop_back(); |
| 87 } | 113 } |
| 88 | 114 |
| 89 // If anything else is added to modify the values after inserting the data | 115 // If anything else is added to modify the values after inserting the data |
| 90 // list, AutofillPopupControllerImpl::UpdateDataListValues will need to be | 116 // list, AutofillPopupControllerImpl::UpdateDataListValues will need to be |
| 91 // updated to match. | 117 // updated to match. |
| 92 InsertDataListValues(&values, &labels, &icons, &ids); | 118 InsertDataListValues(&values, &labels, &icons, &ids); |
| 93 | 119 |
| 120 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 121 if (values.empty() && |
| 122 manager_->ShouldShowAccessAddressBookSuggestion(query_form_, |
| 123 query_field_)) { |
| 124 values.push_back( |
| 125 l10n_util::GetStringUTF16(IDS_AUTOFILL_ACCESS_MAC_CONTACTS)); |
| 126 labels.push_back(base::string16()); |
| 127 icons.push_back(base::ASCIIToUTF16("macContactsIcon")); |
| 128 ids.push_back(POPUP_ITEM_ID_MAC_ACCESS_CONTACTS); |
| 129 |
| 130 EmitHistogram(SHOWED_ACCESS_ADDRESS_BOOK_ENTRY); |
| 131 } |
| 132 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 133 |
| 94 if (values.empty()) { | 134 if (values.empty()) { |
| 95 // No suggestions, any popup currently showing is obsolete. | 135 // No suggestions, any popup currently showing is obsolete. |
| 96 manager_->client()->HideAutofillPopup(); | 136 manager_->client()->HideAutofillPopup(); |
| 97 return; | 137 return; |
| 98 } | 138 } |
| 99 | 139 |
| 100 // Send to display. | 140 // Send to display. |
| 101 if (query_field_.is_focusable) { | 141 if (query_field_.is_focusable) { |
| 102 manager_->client()->ShowAutofillPopup(element_bounds_, | 142 manager_->client()->ShowAutofillPopup(element_bounds_, |
| 103 query_field_.text_direction, | 143 query_field_.text_direction, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 } else if (identifier == POPUP_ITEM_ID_CLEAR_FORM) { | 188 } else if (identifier == POPUP_ITEM_ID_CLEAR_FORM) { |
| 149 // User selected 'Clear form'. | 189 // User selected 'Clear form'. |
| 150 driver_->RendererShouldClearFilledForm(); | 190 driver_->RendererShouldClearFilledForm(); |
| 151 } else if (identifier == POPUP_ITEM_ID_PASSWORD_ENTRY) { | 191 } else if (identifier == POPUP_ITEM_ID_PASSWORD_ENTRY) { |
| 152 NOTREACHED(); // Should be handled elsewhere. | 192 NOTREACHED(); // Should be handled elsewhere. |
| 153 } else if (identifier == POPUP_ITEM_ID_DATALIST_ENTRY) { | 193 } else if (identifier == POPUP_ITEM_ID_DATALIST_ENTRY) { |
| 154 driver_->RendererShouldAcceptDataListSuggestion(value); | 194 driver_->RendererShouldAcceptDataListSuggestion(value); |
| 155 } else if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) { | 195 } else if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) { |
| 156 // User selected an Autocomplete, so we fill directly. | 196 // User selected an Autocomplete, so we fill directly. |
| 157 driver_->RendererShouldFillFieldWithValue(value); | 197 driver_->RendererShouldFillFieldWithValue(value); |
| 198 } else if (identifier == POPUP_ITEM_ID_MAC_ACCESS_CONTACTS) { |
| 199 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 200 EmitHistogram(SELECTED_ACCESS_ADDRESS_BOOK_ENTRY); |
| 201 |
| 202 // User wants to give Chrome access to user's address book. |
| 203 manager_->AccessAddressBook(); |
| 204 |
| 205 // There is no deterministic method for deciding whether a blocking dialog |
| 206 // was presented. The following comments and code assume that a blocking |
| 207 // dialog was presented, but still behave correctly if no dialog was |
| 208 // presented. |
| 209 |
| 210 // A blocking dialog was presented, and the user has already responded to |
| 211 // the dialog. The presentation of the dialog added an NSEvent to the |
| 212 // NSRunLoop which will cause all windows to lose focus. When the NSEvent |
| 213 // is processed, it will be sent to the renderer which will cause the text |
| 214 // field to lose focus. This returns an IPC to Chrome which will dismiss |
| 215 // the Autofill popup. We post a task which we expect to run after the |
| 216 // NSEvent has been processed by the NSRunLoop. It pings the renderer, |
| 217 // which returns an IPC acknowledging the ping. At that time, redisplay |
| 218 // the popup. FIFO processing of IPCs ensures that all side effects of the |
| 219 // NSEvent will have been processed. |
| 220 |
| 221 // 10ms sits nicely under the 16ms threshold for 60 fps, and likely gives |
| 222 // the NSApplication run loop sufficient time to process the NSEvent. In |
| 223 // testing, a delay of 0ms was always sufficient. |
| 224 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); |
| 225 base::MessageLoop::current()->PostDelayedTask( |
| 226 FROM_HERE, |
| 227 base::Bind(&AutofillExternalDelegate::PingRenderer, GetWeakPtr()), |
| 228 delay); |
| 229 #else |
| 230 NOTREACHED(); |
| 231 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 158 } else { | 232 } else { |
| 159 FillAutofillFormData(identifier, false); | 233 FillAutofillFormData(identifier, false); |
| 160 } | 234 } |
| 161 | 235 |
| 162 manager_->client()->HideAutofillPopup(); | 236 manager_->client()->HideAutofillPopup(); |
| 163 } | 237 } |
| 164 | 238 |
| 165 void AutofillExternalDelegate::RemoveSuggestion(const base::string16& value, | 239 void AutofillExternalDelegate::RemoveSuggestion(const base::string16& value, |
| 166 int identifier) { | 240 int identifier) { |
| 167 if (identifier > 0) | 241 if (identifier > 0) |
| 168 manager_->RemoveAutofillProfileOrCreditCard(identifier); | 242 manager_->RemoveAutofillProfileOrCreditCard(identifier); |
| 169 else | 243 else |
| 170 manager_->RemoveAutocompleteEntry(query_field_.name, value); | 244 manager_->RemoveAutocompleteEntry(query_field_.name, value); |
| 171 } | 245 } |
| 172 | 246 |
| 173 void AutofillExternalDelegate::DidEndTextFieldEditing() { | 247 void AutofillExternalDelegate::DidEndTextFieldEditing() { |
| 174 manager_->client()->HideAutofillPopup(); | 248 manager_->client()->HideAutofillPopup(); |
| 175 | 249 |
| 176 has_shown_popup_for_current_edit_ = false; | 250 has_shown_popup_for_current_edit_ = false; |
| 177 } | 251 } |
| 178 | 252 |
| 179 void AutofillExternalDelegate::ClearPreviewedForm() { | 253 void AutofillExternalDelegate::ClearPreviewedForm() { |
| 180 driver_->RendererShouldClearPreviewedForm(); | 254 driver_->RendererShouldClearPreviewedForm(); |
| 181 } | 255 } |
| 182 | 256 |
| 183 void AutofillExternalDelegate::Reset() { | 257 void AutofillExternalDelegate::Reset() { |
| 184 manager_->client()->HideAutofillPopup(); | 258 manager_->client()->HideAutofillPopup(); |
| 185 } | 259 } |
| 186 | 260 |
| 261 void AutofillExternalDelegate::OnPingAck() { |
| 262 // Reissue the most recent query, which will reopen the Autofill popup. |
| 263 manager_->OnQueryFormFieldAutofill(query_id_, |
| 264 query_form_, |
| 265 query_field_, |
| 266 element_bounds_, |
| 267 display_warning_if_disabled_); |
| 268 } |
| 269 |
| 187 base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() { | 270 base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() { |
| 188 return weak_ptr_factory_.GetWeakPtr(); | 271 return weak_ptr_factory_.GetWeakPtr(); |
| 189 } | 272 } |
| 190 | 273 |
| 191 void AutofillExternalDelegate::FillAutofillFormData(int unique_id, | 274 void AutofillExternalDelegate::FillAutofillFormData(int unique_id, |
| 192 bool is_preview) { | 275 bool is_preview) { |
| 193 // If the selected element is a warning we don't want to do anything. | 276 // If the selected element is a warning we don't want to do anything. |
| 194 if (unique_id == POPUP_ITEM_ID_WARNING_MESSAGE) | 277 if (unique_id == POPUP_ITEM_ID_WARNING_MESSAGE) |
| 195 return; | 278 return; |
| 196 | 279 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 210 void AutofillExternalDelegate::ApplyAutofillWarnings( | 293 void AutofillExternalDelegate::ApplyAutofillWarnings( |
| 211 std::vector<base::string16>* values, | 294 std::vector<base::string16>* values, |
| 212 std::vector<base::string16>* labels, | 295 std::vector<base::string16>* labels, |
| 213 std::vector<base::string16>* icons, | 296 std::vector<base::string16>* icons, |
| 214 std::vector<int>* unique_ids) { | 297 std::vector<int>* unique_ids) { |
| 215 if (!query_field_.should_autocomplete) { | 298 if (!query_field_.should_autocomplete) { |
| 216 // Autofill is disabled. If there were some profile or credit card | 299 // Autofill is disabled. If there were some profile or credit card |
| 217 // suggestions to show, show a warning instead. Otherwise, clear out the | 300 // suggestions to show, show a warning instead. Otherwise, clear out the |
| 218 // list of suggestions. | 301 // list of suggestions. |
| 219 if (!unique_ids->empty() && (*unique_ids)[0] > 0) { | 302 if (!unique_ids->empty() && (*unique_ids)[0] > 0) { |
| 220 // If autofill is disabled and we had suggestions, show a warning instead. | 303 // If Autofill is disabled and we had suggestions, show a warning instead. |
| 221 values->assign( | 304 values->assign( |
| 222 1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED)); | 305 1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED)); |
| 223 labels->assign(1, base::string16()); | 306 labels->assign(1, base::string16()); |
| 224 icons->assign(1, base::string16()); | 307 icons->assign(1, base::string16()); |
| 225 unique_ids->assign(1, POPUP_ITEM_ID_WARNING_MESSAGE); | 308 unique_ids->assign(1, POPUP_ITEM_ID_WARNING_MESSAGE); |
| 226 } else { | 309 } else { |
| 227 values->clear(); | 310 values->clear(); |
| 228 labels->clear(); | 311 labels->clear(); |
| 229 icons->clear(); | 312 icons->clear(); |
| 230 unique_ids->clear(); | 313 unique_ids->clear(); |
| 231 } | 314 } |
| 232 } else if (unique_ids->size() > 1 && | 315 } else if (unique_ids->size() > 1 && |
| 233 (*unique_ids)[0] == POPUP_ITEM_ID_WARNING_MESSAGE) { | 316 (*unique_ids)[0] == POPUP_ITEM_ID_WARNING_MESSAGE) { |
| 234 // If we received a warning instead of suggestions from autofill but regular | 317 // If we received a warning instead of suggestions from Autofill but regular |
| 235 // suggestions from autocomplete, don't show the autofill warning. | 318 // suggestions from autocomplete, don't show the Autofill warning. |
| 236 values->erase(values->begin()); | 319 values->erase(values->begin()); |
| 237 labels->erase(labels->begin()); | 320 labels->erase(labels->begin()); |
| 238 icons->erase(icons->begin()); | 321 icons->erase(icons->begin()); |
| 239 unique_ids->erase(unique_ids->begin()); | 322 unique_ids->erase(unique_ids->begin()); |
| 240 } | 323 } |
| 241 | 324 |
| 242 // If we were about to show a warning and we shouldn't, don't. | 325 // If we were about to show a warning and we shouldn't, don't. |
| 243 if (!unique_ids->empty() && | 326 if (!unique_ids->empty() && |
| 244 (*unique_ids)[0] == POPUP_ITEM_ID_WARNING_MESSAGE && | 327 (*unique_ids)[0] == POPUP_ITEM_ID_WARNING_MESSAGE && |
| 245 !display_warning_if_disabled_) { | 328 !display_warning_if_disabled_) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 | 382 |
| 300 // Set the values that all datalist elements share. | 383 // Set the values that all datalist elements share. |
| 301 icons->insert(icons->begin(), | 384 icons->insert(icons->begin(), |
| 302 data_list_values_.size(), | 385 data_list_values_.size(), |
| 303 base::string16()); | 386 base::string16()); |
| 304 unique_ids->insert(unique_ids->begin(), | 387 unique_ids->insert(unique_ids->begin(), |
| 305 data_list_values_.size(), | 388 data_list_values_.size(), |
| 306 POPUP_ITEM_ID_DATALIST_ENTRY); | 389 POPUP_ITEM_ID_DATALIST_ENTRY); |
| 307 } | 390 } |
| 308 | 391 |
| 392 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 393 void AutofillExternalDelegate::PingRenderer() { |
| 394 driver_->PingRenderer(); |
| 395 } |
| 396 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 397 |
| 309 } // namespace autofill | 398 } // namespace autofill |
| OLD | NEW |