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 |