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" |
7 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
8 #include "components/autofill/core/browser/autocomplete_history_manager.h" | 9 #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_driver.h" |
10 #include "components/autofill/core/browser/autofill_manager.h" | 11 #include "components/autofill/core/browser/autofill_manager.h" |
11 #include "components/autofill/core/browser/popup_item_ids.h" | 12 #include "components/autofill/core/browser/popup_item_ids.h" |
12 #include "grit/components_strings.h" | 13 #include "grit/components_strings.h" |
13 #include "ui/base/l10n/l10n_util.h" | 14 #include "ui/base/l10n/l10n_util.h" |
14 | 15 |
15 namespace autofill { | 16 namespace autofill { |
16 | 17 |
17 AutofillExternalDelegate::AutofillExternalDelegate( | 18 AutofillExternalDelegate::AutofillExternalDelegate(AutofillManager* manager, |
18 AutofillManager* manager, | 19 AutofillDriver* driver) |
19 AutofillDriver* driver) | |
20 : manager_(manager), | 20 : manager_(manager), |
21 driver_(driver), | 21 driver_(driver), |
22 query_id_(0), | 22 query_id_(0), |
23 display_warning_if_disabled_(false), | 23 display_warning_if_disabled_(false), |
24 has_suggestion_(false), | 24 has_suggestion_(false), |
25 has_shown_popup_for_current_edit_(false), | 25 has_shown_popup_for_current_edit_(false), |
26 weak_ptr_factory_(this) { | 26 weak_ptr_factory_(this) { |
27 DCHECK(manager); | 27 DCHECK(manager); |
28 } | 28 } |
29 | 29 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 labels.pop_back(); | 84 labels.pop_back(); |
85 icons.pop_back(); | 85 icons.pop_back(); |
86 ids.pop_back(); | 86 ids.pop_back(); |
87 } | 87 } |
88 | 88 |
89 // If anything else is added to modify the values after inserting the data | 89 // If anything else is added to modify the values after inserting the data |
90 // list, AutofillPopupControllerImpl::UpdateDataListValues will need to be | 90 // list, AutofillPopupControllerImpl::UpdateDataListValues will need to be |
91 // updated to match. | 91 // updated to match. |
92 InsertDataListValues(&values, &labels, &icons, &ids); | 92 InsertDataListValues(&values, &labels, &icons, &ids); |
93 | 93 |
| 94 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 95 if (values.empty() && |
| 96 manager_->ShouldShowAccessAddressBookSuggestion(query_form_, |
| 97 query_field_)) { |
| 98 values.push_back( |
| 99 l10n_util::GetStringUTF16(IDS_AUTOFILL_ACCESS_MAC_CONTACTS)); |
| 100 labels.push_back(base::string16()); |
| 101 icons.push_back(base::string16()); |
| 102 ids.push_back(POPUP_ITEM_ID_MAC_ACCESS_CONTACTS); |
| 103 } |
| 104 #endif |
| 105 |
94 if (values.empty()) { | 106 if (values.empty()) { |
95 // No suggestions, any popup currently showing is obsolete. | 107 // No suggestions, any popup currently showing is obsolete. |
96 manager_->delegate()->HideAutofillPopup(); | 108 manager_->delegate()->HideAutofillPopup(); |
97 return; | 109 return; |
98 } | 110 } |
99 | 111 |
100 // Send to display. | 112 // Send to display. |
101 if (query_field_.is_focusable) { | 113 if (query_field_.is_focusable) { |
102 manager_->delegate()->ShowAutofillPopup( | 114 manager_->delegate()->ShowAutofillPopup( |
103 element_bounds_, | 115 element_bounds_, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 } else if (identifier == POPUP_ITEM_ID_CLEAR_FORM) { | 162 } else if (identifier == POPUP_ITEM_ID_CLEAR_FORM) { |
151 // User selected 'Clear form'. | 163 // User selected 'Clear form'. |
152 driver_->RendererShouldClearFilledForm(); | 164 driver_->RendererShouldClearFilledForm(); |
153 } else if (identifier == POPUP_ITEM_ID_PASSWORD_ENTRY) { | 165 } else if (identifier == POPUP_ITEM_ID_PASSWORD_ENTRY) { |
154 NOTREACHED(); // Should be handled elsewhere. | 166 NOTREACHED(); // Should be handled elsewhere. |
155 } else if (identifier == POPUP_ITEM_ID_DATALIST_ENTRY) { | 167 } else if (identifier == POPUP_ITEM_ID_DATALIST_ENTRY) { |
156 driver_->RendererShouldAcceptDataListSuggestion(value); | 168 driver_->RendererShouldAcceptDataListSuggestion(value); |
157 } else if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) { | 169 } else if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) { |
158 // User selected an Autocomplete, so we fill directly. | 170 // User selected an Autocomplete, so we fill directly. |
159 driver_->RendererShouldFillFieldWithValue(value); | 171 driver_->RendererShouldFillFieldWithValue(value); |
| 172 } else if (identifier == POPUP_ITEM_ID_MAC_ACCESS_CONTACTS) { |
| 173 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 174 // User wants to give Chrome access to user's address book. |
| 175 manager_->AccessAddressBook(); |
| 176 |
| 177 // There is no deterministic method for deciding whether a blocking dialog |
| 178 // was presented. The following comments and code assume that a blocking |
| 179 // dialog was presented, but still behave correctly if no dialog was |
| 180 // presented. |
| 181 |
| 182 // A blocking dialog was presented, and the user has already responded to |
| 183 // the dialog. The presentation of the dialog added an NSEvent to the |
| 184 // NSRunLoop which will cause all windows to lose focus. When the NSEvent |
| 185 // is processed, it will be sent to the renderer which will cause the text |
| 186 // field to lose focus. This returns an IPC to Chrome which will dismiss |
| 187 // the autofill popup. We post a task which we expect to run after the |
| 188 // NSEvent has been processed by the NSRunLoop. It pings the renderer, |
| 189 // which returns an IPC acknowledging the ping. At that time, redisplay |
| 190 // the popup. FIFO processing of IPCs ensures that all side effects of the |
| 191 // NSEvent will have been processed. |
| 192 |
| 193 // 10ms sits nicely under the 16ms threshold for 60 fps, and likely gives |
| 194 // the NSApplication run loop sufficient time to process the NSEvent. In |
| 195 // testing, a delay of 0ms was always sufficient. |
| 196 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); |
| 197 base::MessageLoop::current()->PostDelayedTask( |
| 198 FROM_HERE, |
| 199 base::Bind(&AutofillExternalDelegate::PingRenderer, GetWeakPtr()), |
| 200 delay); |
| 201 #else |
| 202 NOTREACHED(); |
| 203 #endif |
160 } else { | 204 } else { |
161 FillAutofillFormData(identifier, false); | 205 FillAutofillFormData(identifier, false); |
162 } | 206 } |
163 | 207 |
164 manager_->delegate()->HideAutofillPopup(); | 208 manager_->delegate()->HideAutofillPopup(); |
165 } | 209 } |
166 | 210 |
167 void AutofillExternalDelegate::RemoveSuggestion(const base::string16& value, | 211 void AutofillExternalDelegate::RemoveSuggestion(const base::string16& value, |
168 int identifier) { | 212 int identifier) { |
169 if (identifier > 0) | 213 if (identifier > 0) |
170 manager_->RemoveAutofillProfileOrCreditCard(identifier); | 214 manager_->RemoveAutofillProfileOrCreditCard(identifier); |
171 else | 215 else |
172 manager_->RemoveAutocompleteEntry(query_field_.name, value); | 216 manager_->RemoveAutocompleteEntry(query_field_.name, value); |
173 } | 217 } |
174 | 218 |
175 void AutofillExternalDelegate::DidEndTextFieldEditing() { | 219 void AutofillExternalDelegate::DidEndTextFieldEditing() { |
176 manager_->delegate()->HideAutofillPopup(); | 220 manager_->delegate()->HideAutofillPopup(); |
177 | 221 |
178 has_shown_popup_for_current_edit_ = false; | 222 has_shown_popup_for_current_edit_ = false; |
179 } | 223 } |
180 | 224 |
181 void AutofillExternalDelegate::ClearPreviewedForm() { | 225 void AutofillExternalDelegate::ClearPreviewedForm() { |
182 driver_->RendererShouldClearPreviewedForm(); | 226 driver_->RendererShouldClearPreviewedForm(); |
183 } | 227 } |
184 | 228 |
185 void AutofillExternalDelegate::Reset() { | 229 void AutofillExternalDelegate::Reset() { |
186 manager_->delegate()->HideAutofillPopup(); | 230 manager_->delegate()->HideAutofillPopup(); |
187 } | 231 } |
188 | 232 |
| 233 void AutofillExternalDelegate::OnPingAck() { |
| 234 // Reissue the most recent query, which will reopen the autofill popup. |
| 235 manager_->OnQueryFormFieldAutofill(query_id_, |
| 236 query_form_, |
| 237 query_field_, |
| 238 element_bounds_, |
| 239 display_warning_if_disabled_); |
| 240 } |
| 241 |
189 base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() { | 242 base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() { |
190 return weak_ptr_factory_.GetWeakPtr(); | 243 return weak_ptr_factory_.GetWeakPtr(); |
191 } | 244 } |
192 | 245 |
193 void AutofillExternalDelegate::FillAutofillFormData(int unique_id, | 246 void AutofillExternalDelegate::FillAutofillFormData(int unique_id, |
194 bool is_preview) { | 247 bool is_preview) { |
195 // If the selected element is a warning we don't want to do anything. | 248 // If the selected element is a warning we don't want to do anything. |
196 if (unique_id == POPUP_ITEM_ID_WARNING_MESSAGE) | 249 if (unique_id == POPUP_ITEM_ID_WARNING_MESSAGE) |
197 return; | 250 return; |
198 | 251 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 | 354 |
302 // Set the values that all datalist elements share. | 355 // Set the values that all datalist elements share. |
303 icons->insert(icons->begin(), | 356 icons->insert(icons->begin(), |
304 data_list_values_.size(), | 357 data_list_values_.size(), |
305 base::string16()); | 358 base::string16()); |
306 unique_ids->insert(unique_ids->begin(), | 359 unique_ids->insert(unique_ids->begin(), |
307 data_list_values_.size(), | 360 data_list_values_.size(), |
308 POPUP_ITEM_ID_DATALIST_ENTRY); | 361 POPUP_ITEM_ID_DATALIST_ENTRY); |
309 } | 362 } |
310 | 363 |
| 364 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 365 void AutofillExternalDelegate::PingRenderer() { |
| 366 driver_->PingRenderer(); |
| 367 } |
| 368 #endif |
| 369 |
311 } // namespace autofill | 370 } // namespace autofill |
OLD | NEW |