autofill_external_delegate.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/autofill/core/browser/autofill_external_delegate.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop/message_loop.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/autofill/core/browser/autocomplete_history_manager.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/autofill/core/browser/autofill_driver.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/autofill/core/browser/autofill_manager.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "components/autofill/core/browser/popup_item_ids.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/components_strings.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) && !defined(OS_IOS)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum AccessAddressBookEventType {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An Autofill entry was shown that prompts the user to give Chrome access to
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the user's Address Book.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHOWED_ACCESS_ADDRESS_BOOK_ENTRY = 0,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The user selected the Autofill entry which prompts Chrome to access the
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // user's Address Book.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SELECTED_ACCESS_ADDRESS_BOOK_ENTRY = 1,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always keep this at the end.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ACCESS_ADDRESS_BOOK_ENTRY_MAX,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Emits an entry for the histogram.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmitHistogram(AccessAddressBookEventType type) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Autofill.MacAddressBook", type, ACCESS_ADDRESS_BOOK_ENTRY_MAX);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace autofill {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutofillExternalDelegate::AutofillExternalDelegate(AutofillManager* manager,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   AutofillDriver* driver)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : manager_(manager),
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      driver_(driver),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      query_id_(0),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_warning_if_disabled_(false),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_suggestion_(false),
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_shown_popup_for_current_edit_(false),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_ptr_factory_(this) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(manager);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutofillExternalDelegate::~AutofillExternalDelegate() {}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillExternalDelegate::OnQuery(int query_id,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const FormData& form,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const FormFieldData& field,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const gfx::RectF& element_bounds,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool display_warning_if_disabled) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query_form_ = form;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query_field_ = field;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  display_warning_if_disabled_ = display_warning_if_disabled;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query_id_ = query_id;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  element_bounds_ = element_bounds;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutofillExternalDelegate::OnSuggestionsReturned(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int query_id,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<base::string16>& suggested_values,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<base::string16>& suggested_labels,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<base::string16>& suggested_icons,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<int>& suggested_unique_ids) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (query_id != query_id_)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::string16> values(suggested_values);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::string16> labels(suggested_labels);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::string16> icons(suggested_icons);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> ids(suggested_unique_ids);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add or hide warnings as appropriate.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ApplyAutofillWarnings(&values, &labels, &icons, &ids);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a separator to go between the values and menu items.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  values.push_back(base::string16());
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  labels.push_back(base::string16());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icons.push_back(base::string16());
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ids.push_back(POPUP_ITEM_ID_SEPARATOR);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only include "Autofill Options" special menu item if we have Autofill
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // suggestions.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_suggestion_ = false;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ids.size(); ++i) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ids[i] > 0) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_suggestion_ = true;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_suggestion_)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ApplyAutofillOptions(&values, &labels, &icons, &ids);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the separator if it is the last element.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(ids.size(), 0U);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ids.back() == POPUP_ITEM_ID_SEPARATOR) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    values.pop_back();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    labels.pop_back();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icons.pop_back();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ids.pop_back();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If anything else is added to modify the values after inserting the data
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // list, AutofillPopupControllerImpl::UpdateDataListValues will need to be
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // updated to match.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InsertDataListValues(&values, &labels, &icons, &ids);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) && !defined(OS_IOS)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (values.empty() &&
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      manager_->ShouldShowAccessAddressBookSuggestion(query_form_,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      query_field_)) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    values.push_back(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        l10n_util::GetStringUTF16(IDS_AUTOFILL_ACCESS_MAC_CONTACTS));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    labels.push_back(base::string16());
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icons.push_back(base::ASCIIToUTF16("macContactsIcon"));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ids.push_back(POPUP_ITEM_ID_MAC_ACCESS_CONTACTS);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EmitHistogram(SHOWED_ACCESS_ADDRESS_BOOK_ENTRY);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (values.empty()) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No suggestions, any popup currently showing is obsolete.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager_->client()->HideAutofillPopup();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send to display.
141  if (query_field_.is_focusable) {
142    manager_->client()->ShowAutofillPopup(element_bounds_,
143                                          query_field_.text_direction,
144                                          values,
145                                          labels,
146                                          icons,
147                                          ids,
148                                          GetWeakPtr());
149  }
150}
151
152void AutofillExternalDelegate::SetCurrentDataListValues(
153    const std::vector<base::string16>& data_list_values,
154    const std::vector<base::string16>& data_list_labels) {
155  data_list_values_ = data_list_values;
156  data_list_labels_ = data_list_labels;
157
158  manager_->client()->UpdateAutofillPopupDataListValues(data_list_values,
159                                                        data_list_labels);
160}
161
162void AutofillExternalDelegate::OnPopupShown() {
163  manager_->DidShowSuggestions(
164      has_suggestion_ && !has_shown_popup_for_current_edit_);
165  has_shown_popup_for_current_edit_ |= has_suggestion_;
166}
167
168void AutofillExternalDelegate::OnPopupHidden() {
169}
170
171void AutofillExternalDelegate::DidSelectSuggestion(
172    const base::string16& value,
173    int identifier) {
174  ClearPreviewedForm();
175
176  // Only preview the data if it is a profile.
177  if (identifier > 0)
178    FillAutofillFormData(identifier, true);
179  else if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY)
180    driver_->RendererShouldPreviewFieldWithValue(value);
181}
182
183void AutofillExternalDelegate::DidAcceptSuggestion(const base::string16& value,
184                                                   int identifier) {
185  if (identifier == POPUP_ITEM_ID_AUTOFILL_OPTIONS) {
186    // User selected 'Autofill Options'.
187    manager_->ShowAutofillSettings();
188  } else if (identifier == POPUP_ITEM_ID_CLEAR_FORM) {
189    // User selected 'Clear form'.
190    driver_->RendererShouldClearFilledForm();
191  } else if (identifier == POPUP_ITEM_ID_PASSWORD_ENTRY) {
192    NOTREACHED();  // Should be handled elsewhere.
193  } else if (identifier == POPUP_ITEM_ID_DATALIST_ENTRY) {
194    driver_->RendererShouldAcceptDataListSuggestion(value);
195  } else if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) {
196    // User selected an Autocomplete, so we fill directly.
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)
232  } else {
233    FillAutofillFormData(identifier, false);
234  }
235
236  manager_->client()->HideAutofillPopup();
237}
238
239void AutofillExternalDelegate::RemoveSuggestion(const base::string16& value,
240                                                int identifier) {
241  if (identifier > 0)
242    manager_->RemoveAutofillProfileOrCreditCard(identifier);
243  else
244    manager_->RemoveAutocompleteEntry(query_field_.name, value);
245}
246
247void AutofillExternalDelegate::DidEndTextFieldEditing() {
248  manager_->client()->HideAutofillPopup();
249
250  has_shown_popup_for_current_edit_ = false;
251}
252
253void AutofillExternalDelegate::ClearPreviewedForm() {
254  driver_->RendererShouldClearPreviewedForm();
255}
256
257void AutofillExternalDelegate::Reset() {
258  manager_->client()->HideAutofillPopup();
259}
260
261void 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
270base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() {
271  return weak_ptr_factory_.GetWeakPtr();
272}
273
274void AutofillExternalDelegate::FillAutofillFormData(int unique_id,
275                                                    bool is_preview) {
276  // If the selected element is a warning we don't want to do anything.
277  if (unique_id == POPUP_ITEM_ID_WARNING_MESSAGE)
278    return;
279
280  AutofillDriver::RendererFormDataAction renderer_action = is_preview ?
281      AutofillDriver::FORM_DATA_ACTION_PREVIEW :
282      AutofillDriver::FORM_DATA_ACTION_FILL;
283
284  DCHECK(driver_->RendererIsAvailable());
285  // Fill the values for the whole form.
286  manager_->FillOrPreviewForm(renderer_action,
287                              query_id_,
288                              query_form_,
289                              query_field_,
290                              unique_id);
291}
292
293void AutofillExternalDelegate::ApplyAutofillWarnings(
294    std::vector<base::string16>* values,
295    std::vector<base::string16>* labels,
296    std::vector<base::string16>* icons,
297    std::vector<int>* unique_ids) {
298  if (!query_field_.should_autocomplete) {
299    // Autofill is disabled.  If there were some profile or credit card
300    // suggestions to show, show a warning instead.  Otherwise, clear out the
301    // list of suggestions.
302    if (!unique_ids->empty() && (*unique_ids)[0] > 0) {
303      // If Autofill is disabled and we had suggestions, show a warning instead.
304      values->assign(
305          1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED));
306      labels->assign(1, base::string16());
307      icons->assign(1, base::string16());
308      unique_ids->assign(1, POPUP_ITEM_ID_WARNING_MESSAGE);
309    } else {
310      values->clear();
311      labels->clear();
312      icons->clear();
313      unique_ids->clear();
314    }
315  } else if (unique_ids->size() > 1 &&
316             (*unique_ids)[0] == POPUP_ITEM_ID_WARNING_MESSAGE) {
317    // If we received a warning instead of suggestions from Autofill but regular
318    // suggestions from autocomplete, don't show the Autofill warning.
319    values->erase(values->begin());
320    labels->erase(labels->begin());
321    icons->erase(icons->begin());
322    unique_ids->erase(unique_ids->begin());
323  }
324
325  // If we were about to show a warning and we shouldn't, don't.
326  if (!unique_ids->empty() &&
327      (*unique_ids)[0] == POPUP_ITEM_ID_WARNING_MESSAGE &&
328      !display_warning_if_disabled_) {
329    values->clear();
330    labels->clear();
331    icons->clear();
332    unique_ids->clear();
333  }
334}
335
336void AutofillExternalDelegate::ApplyAutofillOptions(
337    std::vector<base::string16>* values,
338    std::vector<base::string16>* labels,
339    std::vector<base::string16>* icons,
340    std::vector<int>* unique_ids) {
341  // The form has been auto-filled, so give the user the chance to clear the
342  // form.  Append the 'Clear form' menu item.
343  if (query_field_.is_autofilled) {
344    values->push_back(
345        l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM));
346    labels->push_back(base::string16());
347    icons->push_back(base::string16());
348    unique_ids->push_back(POPUP_ITEM_ID_CLEAR_FORM);
349  }
350
351  // Append the 'Chrome Autofill options' menu item;
352  values->push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_POPUP));
353  labels->push_back(base::string16());
354  icons->push_back(base::string16());
355  unique_ids->push_back(POPUP_ITEM_ID_AUTOFILL_OPTIONS);
356}
357
358void AutofillExternalDelegate::InsertDataListValues(
359    std::vector<base::string16>* values,
360    std::vector<base::string16>* labels,
361    std::vector<base::string16>* icons,
362    std::vector<int>* unique_ids) {
363  if (data_list_values_.empty())
364    return;
365
366  // Insert the separator between the datalist and Autofill values (if there
367  // are any).
368  if (!values->empty()) {
369    values->insert(values->begin(), base::string16());
370    labels->insert(labels->begin(), base::string16());
371    icons->insert(icons->begin(), base::string16());
372    unique_ids->insert(unique_ids->begin(), POPUP_ITEM_ID_SEPARATOR);
373  }
374
375  // Insert the datalist elements.
376  values->insert(values->begin(),
377                 data_list_values_.begin(),
378                 data_list_values_.end());
379  labels->insert(labels->begin(),
380                 data_list_labels_.begin(),
381                 data_list_labels_.end());
382
383  // Set the values that all datalist elements share.
384  icons->insert(icons->begin(),
385                data_list_values_.size(),
386                base::string16());
387  unique_ids->insert(unique_ids->begin(),
388                     data_list_values_.size(),
389                     POPUP_ITEM_ID_DATALIST_ENTRY);
390}
391
392#if defined(OS_MACOSX) && !defined(OS_IOS)
393void AutofillExternalDelegate::PingRenderer() {
394  driver_->PingRenderer();
395}
396#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
397
398}  // namespace autofill
399