1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_IMPL_H_
6 #define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_IMPL_H_
11 #include "base/gtest_prod_util.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/strings/string16.h"
15 #include "base/time/time.h"
16 #include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
17 #include "chrome/browser/ui/autofill/autofill_dialog_models.h"
18 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
19 #include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h"
20 #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
21 #include "chrome/browser/ui/autofill/country_combobox_model.h"
22 #include "components/autofill/core/browser/autofill_client.h"
23 #include "components/autofill/core/browser/autofill_metrics.h"
24 #include "components/autofill/core/browser/autofill_popup_delegate.h"
25 #include "components/autofill/core/browser/field_types.h"
26 #include "components/autofill/core/browser/form_structure.h"
27 #include "components/autofill/core/browser/personal_data_manager.h"
28 #include "components/autofill/core/browser/personal_data_manager_observer.h"
29 #include "content/public/browser/notification_observer.h"
30 #include "content/public/browser/notification_registrar.h"
31 #include "content/public/browser/web_contents_observer.h"
32 #include "content/public/common/ssl_status.h"
33 #include "third_party/libaddressinput/chromium/chrome_address_validator.h"
34 #include "third_party/skia/include/core/SkColor.h"
35 #include "ui/base/models/simple_menu_model.h"
36 #include "ui/base/ui_base_types.h"
37 #include "ui/gfx/animation/animation_delegate.h"
38 #include "ui/gfx/animation/linear_animation.h"
48 namespace addressinput
{
55 class AutofillDataModel
;
56 class AutofillDialogView
;
57 class AutofillPopupControllerImpl
;
58 class DataModelWrapper
;
65 class WalletSigninHelper
;
68 // This class drives the dialog that appears when a site uses the imperative
69 // autocomplete API to fill out a form.
70 class AutofillDialogControllerImpl
71 : public AutofillDialogViewDelegate
,
72 public AutofillDialogController
,
73 public AutofillPopupDelegate
,
74 public content::WebContentsObserver
,
75 public SuggestionsMenuModelDelegate
,
76 public PersonalDataManagerObserver
,
77 public LoadRulesListener
{
79 ~AutofillDialogControllerImpl() override
;
81 static base::WeakPtr
<AutofillDialogControllerImpl
> Create(
82 content::WebContents
* contents
,
83 const FormData
& form_structure
,
84 const GURL
& source_url
,
85 const AutofillClient::ResultCallback
& callback
);
87 // AutofillDialogController implementation.
90 void TabActivated() override
;
92 // AutofillDialogViewDelegate implementation.
93 base::string16
DialogTitle() const override
;
94 base::string16
EditSuggestionText() const override
;
95 base::string16
CancelButtonText() const override
;
96 base::string16
ConfirmButtonText() const override
;
97 base::string16
SaveLocallyText() const override
;
98 base::string16
SaveLocallyTooltip() const override
;
99 bool ShouldOfferToSaveInChrome() const override
;
100 bool ShouldSaveInChrome() const override
;
101 int GetDialogButtons() const override
;
102 bool IsDialogButtonEnabled(ui::DialogButton button
) const override
;
103 bool SectionIsActive(DialogSection section
) const override
;
104 const DetailInputs
& RequestedFieldsForSection(
105 DialogSection section
) const override
;
106 ui::ComboboxModel
* ComboboxModelForAutofillType(
107 ServerFieldType type
) override
;
108 ui::MenuModel
* MenuModelForSection(DialogSection section
) override
;
109 base::string16
LabelForSection(DialogSection section
) const override
;
110 SuggestionState
SuggestionStateForSection(DialogSection section
) override
;
111 FieldIconMap
IconsForFields(const FieldValueMap
& user_inputs
) const override
;
112 bool FieldControlsIcons(ServerFieldType type
) const override
;
113 base::string16
TooltipForField(ServerFieldType type
) const override
;
114 base::string16
InputValidityMessage(DialogSection section
,
115 ServerFieldType type
,
116 const base::string16
& value
) override
;
117 ValidityMessages
InputsAreValid(DialogSection section
,
118 const FieldValueMap
& inputs
) override
;
119 void UserEditedOrActivatedInput(DialogSection section
,
120 ServerFieldType type
,
121 gfx::NativeView parent_view
,
122 const gfx::Rect
& content_bounds
,
123 const base::string16
& field_contents
,
124 bool was_edit
) override
;
125 bool HandleKeyPressEventInInput(
126 const content::NativeWebKeyboardEvent
& event
) override
;
127 void FocusMoved() override
;
128 bool ShouldShowErrorBubble() const override
;
129 void ViewClosed() override
;
130 std::vector
<DialogNotification
> CurrentNotifications() override
;
131 void LinkClicked(const GURL
& url
) override
;
132 void OnCancel() override
;
133 void OnAccept() override
;
134 Profile
* profile() override
;
135 content::WebContents
* GetWebContents() override
;
137 // AutofillPopupDelegate implementation.
138 void OnPopupShown() override
;
139 void OnPopupHidden() override
;
140 void DidSelectSuggestion(const base::string16
& value
,
141 int identifier
) override
;
142 void DidAcceptSuggestion(const base::string16
& value
,
144 int position
) override
;
145 bool GetDeletionConfirmationText(const base::string16
& value
,
147 base::string16
* title
,
148 base::string16
* body
) override
;
149 bool RemoveSuggestion(const base::string16
& value
, int identifier
) override
;
150 void ClearPreviewedForm() override
;
153 // SuggestionsMenuModelDelegate implementation.
154 void SuggestionItemSelected(SuggestionsMenuModel
* model
,
155 size_t index
) override
;
157 // PersonalDataManagerObserver implementation.
158 void OnPersonalDataChanged() override
;
160 // LoadRulesListener implementation.
161 void OnAddressValidationRulesLoaded(const std::string
& country_code
,
162 bool success
) override
;
165 // Exposed for testing.
166 AutofillDialogControllerImpl(content::WebContents
* contents
,
167 const FormData
& form_structure
,
168 const GURL
& source_url
,
169 const AutofillClient::ResultCallback
& callback
);
171 // Exposed for testing.
172 AutofillDialogView
* view() { return view_
.get(); }
173 virtual AutofillDialogView
* CreateView();
174 ServerFieldType
popup_input_type() const {
175 return popup_input_type_
;
178 // Returns the PersonalDataManager for |profile_|.
179 virtual PersonalDataManager
* GetManager() const;
181 // Returns an address validation helper. May be NULL during tests.
182 virtual AddressValidator
* GetValidator();
184 // Opens the given URL in a new foreground tab.
185 virtual void OpenTabWithUrl(const GURL
& url
);
187 // The active billing section for the current state of the dialog (e.g. when
188 // paying for wallet, the combined credit card + billing address section).
189 DialogSection
ActiveBillingSection() const;
191 // Whether |section| was sent into edit mode based on existing data. This
192 // happens when a user clicks "Edit" or a suggestion is invalid.
193 virtual bool IsEditingExistingData(DialogSection section
) const;
195 // Whether the user has chosen to enter all new data in |section|. This
196 // happens via choosing "Add a new X..." from a section's suggestion menu.
197 bool IsManuallyEditingSection(DialogSection section
) const;
199 // Shows a new credit card saved bubble and passes ownership of |new_card| and
200 // |billing_profile| to the bubble. Exposed for testing.
201 virtual void ShowNewCreditCardBubble(
202 scoped_ptr
<CreditCard
> new_card
,
203 scoped_ptr
<AutofillProfile
> billing_profile
);
205 // Delays enabling submit button for a short period of time. Exposed for
207 virtual void SubmitButtonDelayBegin();
211 // Ends the delay for enabling the submit button. Called only from tests.
212 // Without this method, the tests would have to wait for the delay timer to
213 // finish, which would be flaky.
214 void SubmitButtonDelayEndForTesting();
217 FRIEND_TEST_ALL_PREFIXES(AutofillDialogControllerI18nTest
,
218 CorrectCountryFromInputs
);
219 FRIEND_TEST_ALL_PREFIXES(AutofillDialogControllerTest
,
221 FRIEND_TEST_ALL_PREFIXES(AutofillDialogControllerTest
,
222 TransactionAmountReadonly
);
224 // Initializes or updates |suggested_cc_| et al.
225 void SuggestionsUpdated();
227 // Starts fetching the wallet items from Online Wallet.
228 void GetWalletItems();
230 // Clears previously entered manual input and removes |section| from
231 // |section_editing_state_|. Does not update the view.
232 void ResetSectionInput(DialogSection section
);
234 // Force |section| into edit mode if the current suggestion is invalid.
235 void ShowEditUiIfBadSuggestion(DialogSection section
);
237 // Whether the |value| of |input| should be preserved on account change.
238 bool InputWasEdited(ServerFieldType type
,
239 const base::string16
& value
);
241 // Takes a snapshot of the newly inputted user data in |view_| (if it exists).
242 FieldValueMap
TakeUserInputSnapshot();
244 // Fills the detail inputs from a previously taken user input snapshot. Does
245 // not update the view.
246 void RestoreUserInputFromSnapshot(const FieldValueMap
& snapshot
);
248 // Tells the view to update |section|.
249 void UpdateSection(DialogSection section
);
251 // Tells |view_| to update the validity status of its detail inputs (if
252 // |view_| is non-null). Currently this is used solely for highlighting
253 // invalid suggestions, so if no sections are based on existing data,
254 // |view_->UpdateForErrors()| is not called.
255 void UpdateForErrors();
257 // Creates a DataModelWrapper item for the item that's checked in the
258 // suggestion model for |section|. This may represent Autofill
259 // data or Wallet data, depending on whether Wallet is currently enabled.
260 scoped_ptr
<DataModelWrapper
> CreateWrapper(DialogSection section
);
262 // Fills in |section|-related fields in |output_| according to the state of
264 void FillOutputForSection(DialogSection section
);
265 // As above, but uses |compare| to determine whether a DetailInput matches
266 // a field. Saves any new Autofill data to the PersonalDataManager.
267 void FillOutputForSectionWithComparator(
268 DialogSection section
,
269 const FormStructure::InputFieldComparator
& compare
);
271 // Returns whether |form_structure|_| has any fields that match the fieldset
272 // represented by |section|.
273 bool FormStructureCaresAboutSection(DialogSection section
) const;
275 // Finds all fields of the given |type| in |form_structure_|, if any, and sets
276 // each field's value to |output|.
277 void SetOutputForFieldsOfType(ServerFieldType type
,
278 const base::string16
& output
);
280 // Gets the value for |type| in |section|, whether it comes from manual user
281 // input or the active suggestion.
282 base::string16
GetValueFromSection(DialogSection section
,
283 ServerFieldType type
);
285 // Returns whether the given section can accept an address with the given
287 bool CanAcceptCountry(DialogSection section
, const std::string
& country_code
);
289 // Whether |profile| should be suggested for |section|.
290 bool ShouldSuggestProfile(DialogSection section
,
291 const AutofillProfile
& profile
);
293 // Gets the SuggestionsMenuModel for |section|.
294 SuggestionsMenuModel
* SuggestionsMenuModelForSection(DialogSection section
);
295 const SuggestionsMenuModel
* SuggestionsMenuModelForSection(
296 DialogSection section
) const;
298 DialogSection
SectionForSuggestionsMenuModel(
299 const SuggestionsMenuModel
& model
);
301 // Gets the CountryComboboxModel for |section|.
302 CountryComboboxModel
* CountryComboboxModelForSection(DialogSection section
);
304 // Clears and builds the inputs in |section| for |country_name|.
305 // When |should_clobber| is false, and the view's country value matches
306 // |country_name|, the inputs won't be rebuilt.
307 bool RebuildInputsForCountry(DialogSection section
,
308 const base::string16
& country_name
,
309 bool should_clobber
);
311 // Suggested text and icons for sections. Suggestion text is used to show an
312 // abridged overview of the currently used suggestion. Extra text is used when
313 // part of a section is suggested but part must be manually input (e.g. during
314 // a CVC challenge or when using Autofill's CC section [never stores CVC]).
315 bool SuggestionTextForSection(DialogSection section
,
316 base::string16
* vertically_compact
,
317 base::string16
* horizontally_compact
);
318 gfx::Image
SuggestionIconForSection(DialogSection section
);
319 base::string16
ExtraSuggestionTextForSection(DialogSection section
) const;
320 gfx::Image
ExtraSuggestionIconForSection(DialogSection section
);
322 // Suggests address completions using the downloaded i18n validation rules.
323 // Stores the suggestions in |i18n_validator_suggestions_|.
324 void GetI18nValidatorSuggestions(
325 DialogSection section
,
326 ServerFieldType type
,
327 std::vector
<autofill::Suggestion
>* popup_suggestions
);
329 // Like RequestedFieldsForSection, but returns a pointer.
330 DetailInputs
* MutableRequestedFieldsForSection(DialogSection section
);
332 // Returns a pointer to the language code that should be used for formatting
333 // the address in |section| for display. Returns NULL for a non-address
335 std::string
* MutableAddressLanguageCodeForSection(DialogSection section
);
337 // Returns the language code that should be used for formatting the address in
338 // |section|. Returns an empty string for a non-address |section|.
339 std::string
AddressLanguageCodeForSection(DialogSection section
);
341 // Returns just the |type| attributes of RequestedFieldsForSection(section).
342 std::vector
<ServerFieldType
> RequestedTypesForSection(DialogSection section
)
345 // Returns the country code (e.g. "US") for |section|.
346 std::string
CountryCodeForSection(DialogSection section
);
348 // Hides |popup_controller_|'s popup view, if it exists.
351 // Set whether the currently editing |section| was originally based on
352 // existing Wallet or Autofill data.
353 void SetEditingExistingData(DialogSection section
, bool editing
);
355 // Whether the user has chosen to enter all new data in at least one section.
356 bool IsManuallyEditingAnySection() const;
358 // Returns validity message for a given credit card number.
359 base::string16
CreditCardNumberValidityMessage(
360 const base::string16
& number
) const;
362 // Whether all of the input fields currently showing in the dialog have valid
363 // contents. This validates only by checking "sure" messages, i.e. messages
364 // that would have been displayed to the user during editing, as opposed to
366 bool AllSectionsAreValid();
368 // Whether all of the input fields currently showing in the given |section| of
369 // the dialog have valid contents. This validates only by checking "sure"
370 // messages - see AllSectionsAreValid.
371 bool SectionIsValid(DialogSection section
);
373 // Whether validation rules for |section| are loaded.
374 bool RulesAreLoaded(DialogSection section
);
376 // Whether the currently active credit card expiration date is valid.
377 bool IsCreditCardExpirationValid(const base::string16
& year
,
378 const base::string16
& month
) const;
380 // Returns true if we should reject the given credit card brand. |type| should
381 // be a display string, such as "Visa".
382 bool ShouldDisallowCcType(const base::string16
& type
) const;
384 // Returns true if |profile| has an address we can be sure is invalid.
385 // Profiles with invalid addresses are not suggested in the dropdown menu for
386 // billing and shipping addresses.
387 bool HasInvalidAddress(const AutofillProfile
& profile
);
389 // Returns true if |key| refers to a suggestion, as opposed to some control
391 bool IsASuggestionItemKey(const std::string
& key
) const;
393 // Returns whether Autofill is enabled for |profile_|.
394 bool IsAutofillEnabled() const;
396 // Whether the billing section should be used to fill in the shipping details.
397 bool ShouldUseBillingForShipping();
399 // Whether the user wishes to save information locally to Autofill.
400 bool ShouldSaveDetailsLocally();
402 // Writes to prefs the choice of AutofillDataModel for |section|.
403 void PersistAutofillChoice(DialogSection section
,
404 const std::string
& guid
);
406 // Sets the outparams to the default AutofillDataModel for |section| (which is
407 // the first one in the menu that is a suggestion item).
408 void GetDefaultAutofillChoice(DialogSection section
,
411 // Reads from prefs the choice of AutofillDataModel for |section|. Returns
412 // whether there was a setting to read.
413 bool GetAutofillChoice(DialogSection section
,
416 // Logs metrics when the dialog is submitted.
417 void LogOnFinishSubmitMetrics();
419 // Logs metrics when the dialog is canceled.
420 void LogOnCancelMetrics();
422 // Logs metrics when the edit ui is shown for the given |section|.
423 void LogEditUiShownMetric(DialogSection section
);
425 // Logs metrics when a suggestion item from the given |model| is selected.
426 void LogSuggestionItemSelectedMetric(const SuggestionsMenuModel
& model
);
428 // Logs the time elapsed from when the dialog was shown to when the user could
430 void LogDialogLatencyToShow();
432 // Returns the metric corresponding to the user's initial state when
433 // interacting with this dialog.
434 AutofillMetrics::DialogInitialUserStateMetric
GetInitialUserState() const;
436 // Shows an educational bubble if a new credit card was saved or the first few
437 // times an Online Wallet fronting card was generated.
438 void MaybeShowCreditCardBubble();
440 // Called when the delay for enabling the submit button ends.
441 void OnSubmitButtonDelayEnd();
443 // The |profile| for |contents_|.
444 Profile
* const profile_
;
446 // For logging UMA metrics.
447 base::Time dialog_shown_timestamp_
;
448 AutofillMetrics::DialogInitialUserStateMetric initial_user_state_
;
450 FormStructure form_structure_
;
452 // Whether the URL visible to the user when this dialog was requested to be
453 // invoked is the same as |source_url_|.
454 bool invoked_from_same_origin_
;
456 // The URL of the invoking site.
459 // The callback via which we return the collected data.
460 AutofillClient::ResultCallback callback_
;
462 // A helper to validate international address input.
463 scoped_ptr
<AddressValidator
> validator_
;
465 // The default active instrument and shipping address object IDs as of the
466 // last time Wallet items were fetched. These variables are only set
467 // (i.e. non-empty) when the Wallet items are being re-fetched.
468 std::string previous_default_instrument_id_
;
469 std::string previous_default_shipping_address_id_
;
470 // The last active instrument and shipping address object IDs. These
471 // variables are only set (i.e. non-empty) when the Wallet items are being
473 std::string previously_selected_instrument_id_
;
474 std::string previously_selected_shipping_address_id_
;
476 // When the Wallet items were last fetched.
477 base::TimeTicks last_wallet_items_fetch_timestamp_
;
479 // Local machine signals to pass along on each request to trigger (or
480 // discourage) risk challenges; sent if the user is up to date on legal docs.
481 std::string risk_data_
;
483 // The text to display when the user is accepting new terms of service, etc.
484 base::string16 legal_documents_text_
;
485 // The ranges within |legal_documents_text_| to linkify.
486 std::vector
<gfx::Range
> legal_document_link_ranges_
;
488 // The instrument and address IDs from the Online Wallet server to be used
489 // when getting a full wallet.
490 std::string active_instrument_id_
;
491 std::string active_address_id_
;
493 // The fields for billing and shipping which the page has actually requested.
494 DetailInputs requested_cc_fields_
;
495 DetailInputs requested_billing_fields_
;
496 DetailInputs requested_cc_billing_fields_
;
497 DetailInputs requested_shipping_fields_
;
499 // The BCP 47 language codes used for formatting the addresses for display.
500 std::string billing_address_language_code_
;
501 std::string shipping_address_language_code_
;
503 // Models for the credit card expiration inputs.
504 MonthComboboxModel cc_exp_month_combobox_model_
;
505 YearComboboxModel cc_exp_year_combobox_model_
;
507 // Models for country input.
508 scoped_ptr
<CountryComboboxModel
> billing_country_combobox_model_
;
509 scoped_ptr
<CountryComboboxModel
> shipping_country_combobox_model_
;
511 // Models for the suggestion views.
512 SuggestionsMenuModel suggested_cc_
;
513 SuggestionsMenuModel suggested_billing_
;
514 SuggestionsMenuModel suggested_shipping_
;
516 // The set of values for cc-type that the site accepts. Empty means all types
518 std::set
<base::string16
> acceptable_cc_types_
;
520 // |DialogSection|s that are in edit mode that are based on existing data.
521 std::set
<DialogSection
> section_editing_state_
;
523 // Sections that need to be validated when their validation rules load.
524 std::set
<DialogSection
> needs_validation_
;
526 // Whether |form_structure_| has asked for any details that would indicate
527 // we should show a shipping section.
528 bool cares_about_shipping_
;
530 // Site-provided transaction amount and currency. No attempt to validate this
531 // input; it's passed directly to Wallet.
532 base::string16 transaction_amount_
;
533 base::string16 transaction_currency_
;
535 // The IDs for the currently showing unverified profiles popup. This will
536 // be the first section in the list. The rest of the items will be the
537 // i18n_validator_suggestions_.
538 std::vector
<std::string
> popup_suggestion_ids_
;
540 // The autofill suggestions based on downloaded i18n validation rules.
541 std::vector
< ::i18n::addressinput::AddressData
> i18n_validator_suggestions_
;
543 // The controller for the currently showing popup (which helps users when
544 // they're manually filling the dialog).
545 base::WeakPtr
<AutofillPopupControllerImpl
> popup_controller_
;
547 // The type of the visible Autofill popup input (or UNKNOWN_TYPE if none).
548 ServerFieldType popup_input_type_
;
550 // The section of the dialog that's showing a popup, undefined if no popup
552 DialogSection popup_section_
;
554 scoped_ptr
<AutofillDialogView
> view_
;
556 // A NotificationRegistrar for tracking the completion of sign-in.
557 content::NotificationRegistrar signin_registrar_
;
559 // The countries the form structure can accept for shipping.
560 std::set
<base::string16
> acceptable_shipping_countries_
;
562 // Whether |callback_| was Run() with a filled |form_structure_|.
563 bool data_was_passed_back_
;
565 typedef std::map
<ServerFieldType
,
566 std::pair
<base::string16
, base::string16
> > TypeErrorInputMap
;
567 // Whether the latency to display to the UI was logged to UMA yet.
568 bool was_ui_latency_logged_
;
570 // A map from dialog sections to the GUID of a newly saved Autofill data
571 // models for that section. No entries present that don't have newly saved
573 std::map
<DialogSection
, std::string
> newly_saved_data_model_guids_
;
575 // Populated if the user chose to save a newly inputted credit card. Used to
576 // show a bubble as the dialog closes to confirm a user's new card info was
577 // saved. Never populated while incognito (as nothing's actually saved).
578 scoped_ptr
<CreditCard
> newly_saved_card_
;
580 // The timer that delays enabling submit button for a short period of time on
582 base::OneShotTimer
<AutofillDialogControllerImpl
> submit_button_delay_timer_
;
584 base::WeakPtrFactory
<AutofillDialogControllerImpl
> weak_ptr_factory_
;
586 DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerImpl
);
589 } // namespace autofill
591 #endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_IMPL_H_