Revert "Fix broken channel icon in chrome://help on CrOS" and try again
[chromium-blink-merge.git] / components / autofill / core / browser / autofill_external_delegate.cc
blob82b7396c7c8f999ac184d9885014910a9f031e49
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.
5 #include "components/autofill/core/browser/autofill_external_delegate.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/i18n/case_conversion.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "base/metrics/sparse_histogram.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "components/autofill/core/browser/autocomplete_history_manager.h"
16 #include "components/autofill/core/browser/autofill_driver.h"
17 #include "components/autofill/core/browser/autofill_manager.h"
18 #include "components/autofill/core/browser/autofill_metrics.h"
19 #include "components/autofill/core/browser/popup_item_ids.h"
20 #include "components/autofill/core/common/autofill_util.h"
21 #include "grit/components_strings.h"
22 #include "ui/base/l10n/l10n_util.h"
24 namespace autofill {
26 AutofillExternalDelegate::AutofillExternalDelegate(AutofillManager* manager,
27 AutofillDriver* driver)
28 : manager_(manager),
29 driver_(driver),
30 query_id_(0),
31 has_suggestion_(false),
32 has_shown_popup_for_current_edit_(false),
33 should_show_scan_credit_card_(false),
34 has_shown_address_book_prompt(false),
35 weak_ptr_factory_(this) {
36 DCHECK(manager);
39 AutofillExternalDelegate::~AutofillExternalDelegate() {}
41 void AutofillExternalDelegate::OnQuery(int query_id,
42 const FormData& form,
43 const FormFieldData& field,
44 const gfx::RectF& element_bounds) {
45 if (!query_form_.SameFormAs(form))
46 has_shown_address_book_prompt = false;
48 query_form_ = form;
49 query_field_ = field;
50 query_id_ = query_id;
51 element_bounds_ = element_bounds;
52 should_show_scan_credit_card_ =
53 manager_->ShouldShowScanCreditCard(query_form_, query_field_);
56 void AutofillExternalDelegate::OnSuggestionsReturned(
57 int query_id,
58 const std::vector<Suggestion>& input_suggestions) {
59 if (query_id != query_id_)
60 return;
62 std::vector<Suggestion> suggestions(input_suggestions);
64 // Add or hide warnings as appropriate.
65 ApplyAutofillWarnings(&suggestions);
67 #if !defined(OS_ANDROID)
68 // Add a separator to go between the values and menu items.
69 suggestions.push_back(Suggestion());
70 suggestions.back().frontend_id = POPUP_ITEM_ID_SEPARATOR;
71 #endif
73 if (should_show_scan_credit_card_) {
74 Suggestion scan_credit_card(
75 l10n_util::GetStringUTF16(IDS_AUTOFILL_SCAN_CREDIT_CARD));
76 scan_credit_card.frontend_id = POPUP_ITEM_ID_SCAN_CREDIT_CARD;
77 scan_credit_card.icon = base::ASCIIToUTF16("scanCreditCardIcon");
78 suggestions.push_back(scan_credit_card);
80 if (!has_shown_popup_for_current_edit_) {
81 AutofillMetrics::LogScanCreditCardPromptMetric(
82 AutofillMetrics::SCAN_CARD_ITEM_SHOWN);
86 // Only include "Autofill Options" special menu item if we have Autofill
87 // suggestions.
88 has_suggestion_ = false;
89 for (size_t i = 0; i < suggestions.size(); ++i) {
90 if (suggestions[i].frontend_id > 0) {
91 has_suggestion_ = true;
92 break;
96 if (has_suggestion_)
97 ApplyAutofillOptions(&suggestions);
99 #if !defined(OS_ANDROID)
100 // Remove the separator if it is the last element.
101 DCHECK_GT(suggestions.size(), 0U);
102 if (suggestions.back().frontend_id == POPUP_ITEM_ID_SEPARATOR)
103 suggestions.pop_back();
104 #endif
106 // If anything else is added to modify the values after inserting the data
107 // list, AutofillPopupControllerImpl::UpdateDataListValues will need to be
108 // updated to match.
109 InsertDataListValues(&suggestions);
111 if (suggestions.empty()) {
112 // No suggestions, any popup currently showing is obsolete.
113 manager_->client()->HideAutofillPopup();
114 return;
117 // Send to display.
118 if (query_field_.is_focusable) {
119 manager_->client()->ShowAutofillPopup(element_bounds_,
120 query_field_.text_direction,
121 suggestions,
122 GetWeakPtr());
126 void AutofillExternalDelegate::SetCurrentDataListValues(
127 const std::vector<base::string16>& data_list_values,
128 const std::vector<base::string16>& data_list_labels) {
129 data_list_values_ = data_list_values;
130 data_list_labels_ = data_list_labels;
132 manager_->client()->UpdateAutofillPopupDataListValues(data_list_values,
133 data_list_labels);
136 void AutofillExternalDelegate::OnPopupShown() {
137 manager_->DidShowSuggestions(
138 has_suggestion_ && !has_shown_popup_for_current_edit_,
139 query_form_,
140 query_field_);
141 has_shown_popup_for_current_edit_ |= has_suggestion_;
144 void AutofillExternalDelegate::OnPopupHidden() {
145 driver_->PopupHidden();
148 void AutofillExternalDelegate::DidSelectSuggestion(
149 const base::string16& value,
150 int identifier) {
151 ClearPreviewedForm();
153 // Only preview the data if it is a profile.
154 if (identifier > 0)
155 FillAutofillFormData(identifier, true);
156 else if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY)
157 driver_->RendererShouldPreviewFieldWithValue(value);
160 void AutofillExternalDelegate::DidAcceptSuggestion(const base::string16& value,
161 int identifier,
162 int position) {
163 if (identifier == POPUP_ITEM_ID_AUTOFILL_OPTIONS) {
164 // User selected 'Autofill Options'.
165 manager_->ShowAutofillSettings();
166 } else if (identifier == POPUP_ITEM_ID_CLEAR_FORM) {
167 // User selected 'Clear form'.
168 driver_->RendererShouldClearFilledForm();
169 } else if (identifier == POPUP_ITEM_ID_PASSWORD_ENTRY) {
170 NOTREACHED(); // Should be handled elsewhere.
171 } else if (identifier == POPUP_ITEM_ID_DATALIST_ENTRY) {
172 driver_->RendererShouldAcceptDataListSuggestion(value);
173 } else if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) {
174 // User selected an Autocomplete, so we fill directly.
175 driver_->RendererShouldFillFieldWithValue(value);
176 } else if (identifier == POPUP_ITEM_ID_SCAN_CREDIT_CARD) {
177 manager_->client()->ScanCreditCard(base::Bind(
178 &AutofillExternalDelegate::OnCreditCardScanned, GetWeakPtr()));
179 } else {
180 if (identifier > 0) // Denotes an Autofill suggestion.
181 AutofillMetrics::LogSuggestionAcceptedIndex(position);
183 FillAutofillFormData(identifier, false);
186 if (should_show_scan_credit_card_) {
187 AutofillMetrics::LogScanCreditCardPromptMetric(
188 identifier == POPUP_ITEM_ID_SCAN_CREDIT_CARD
189 ? AutofillMetrics::SCAN_CARD_ITEM_SELECTED
190 : AutofillMetrics::SCAN_CARD_OTHER_ITEM_SELECTED);
193 manager_->client()->HideAutofillPopup();
196 bool AutofillExternalDelegate::GetDeletionConfirmationText(
197 const base::string16& value,
198 int identifier,
199 base::string16* title,
200 base::string16* body) {
201 return manager_->GetDeletionConfirmationText(value, identifier, title, body);
204 bool AutofillExternalDelegate::RemoveSuggestion(const base::string16& value,
205 int identifier) {
206 if (identifier > 0)
207 return manager_->RemoveAutofillProfileOrCreditCard(identifier);
209 if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) {
210 manager_->RemoveAutocompleteEntry(query_field_.name, value);
211 return true;
214 return false;
217 void AutofillExternalDelegate::DidEndTextFieldEditing() {
218 manager_->client()->HideAutofillPopup();
220 has_shown_popup_for_current_edit_ = false;
223 void AutofillExternalDelegate::ClearPreviewedForm() {
224 driver_->RendererShouldClearPreviewedForm();
227 void AutofillExternalDelegate::Reset() {
228 manager_->client()->HideAutofillPopup();
231 void AutofillExternalDelegate::OnPingAck() {
232 // Reissue the most recent query, which will reopen the Autofill popup.
233 manager_->OnQueryFormFieldAutofill(query_id_, query_form_, query_field_,
234 element_bounds_);
237 base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() {
238 return weak_ptr_factory_.GetWeakPtr();
241 void AutofillExternalDelegate::OnCreditCardScanned(
242 const base::string16& card_number,
243 int expiration_month,
244 int expiration_year) {
245 manager_->FillCreditCardForm(
246 query_id_, query_form_, query_field_,
247 CreditCard(card_number, expiration_month, expiration_year));
250 void AutofillExternalDelegate::FillAutofillFormData(int unique_id,
251 bool is_preview) {
252 // If the selected element is a warning we don't want to do anything.
253 if (unique_id == POPUP_ITEM_ID_WARNING_MESSAGE)
254 return;
256 AutofillDriver::RendererFormDataAction renderer_action = is_preview ?
257 AutofillDriver::FORM_DATA_ACTION_PREVIEW :
258 AutofillDriver::FORM_DATA_ACTION_FILL;
260 DCHECK(driver_->RendererIsAvailable());
261 // Fill the values for the whole form.
262 manager_->FillOrPreviewForm(renderer_action,
263 query_id_,
264 query_form_,
265 query_field_,
266 unique_id);
269 void AutofillExternalDelegate::ApplyAutofillWarnings(
270 std::vector<Suggestion>* suggestions) {
271 if (suggestions->size() > 1 &&
272 (*suggestions)[0].frontend_id == POPUP_ITEM_ID_WARNING_MESSAGE) {
273 // If we received a warning instead of suggestions from Autofill but regular
274 // suggestions from autocomplete, don't show the Autofill warning.
275 suggestions->erase(suggestions->begin());
279 void AutofillExternalDelegate::ApplyAutofillOptions(
280 std::vector<Suggestion>* suggestions) {
281 // The form has been auto-filled, so give the user the chance to clear the
282 // form. Append the 'Clear form' menu item.
283 if (query_field_.is_autofilled) {
284 base::string16 value =
285 l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM);
286 // TODO(rouslan): Remove manual upper-casing when keyboard accessory becomes
287 // default on Android.
288 if (IsKeyboardAccessoryEnabled())
289 value = base::i18n::ToUpper(value);
291 suggestions->push_back(Suggestion(value));
292 suggestions->back().frontend_id = POPUP_ITEM_ID_CLEAR_FORM;
295 // Append the 'Chrome Autofill options' menu item;
296 suggestions->push_back(Suggestion(
297 l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_POPUP)));
298 suggestions->back().frontend_id = POPUP_ITEM_ID_AUTOFILL_OPTIONS;
299 if (IsKeyboardAccessoryEnabled())
300 suggestions->back().icon = base::ASCIIToUTF16("settings");
303 void AutofillExternalDelegate::InsertDataListValues(
304 std::vector<Suggestion>* suggestions) {
305 if (data_list_values_.empty())
306 return;
308 #if !defined(OS_ANDROID)
309 // Insert the separator between the datalist and Autofill values (if there
310 // are any).
311 if (!suggestions->empty()) {
312 suggestions->insert(suggestions->begin(), Suggestion());
313 (*suggestions)[0].frontend_id = POPUP_ITEM_ID_SEPARATOR;
315 #endif
317 // Insert the datalist elements at the beginning.
318 suggestions->insert(suggestions->begin(), data_list_values_.size(),
319 Suggestion());
320 for (size_t i = 0; i < data_list_values_.size(); i++) {
321 (*suggestions)[i].value = data_list_values_[i];
322 (*suggestions)[i].label = data_list_labels_[i];
323 (*suggestions)[i].frontend_id = POPUP_ITEM_ID_DATALIST_ENTRY;
327 } // namespace autofill