diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-30 19:41:09 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-30 19:41:09 +0000 |
commit | a0e73db0048a7c2a18e3c07e88a4bb4761e8b25d (patch) | |
tree | d31e558ffed2163c6c1bf4f9808e1e663897df80 | |
parent | 1b42e64d59379b4f34960c9e974a74f1c102b065 (diff) | |
download | chromium_src-a0e73db0048a7c2a18e3c07e88a4bb4761e8b25d.zip chromium_src-a0e73db0048a7c2a18e3c07e88a4bb4761e8b25d.tar.gz chromium_src-a0e73db0048a7c2a18e3c07e88a4bb4761e8b25d.tar.bz2 |
rAc: better Wallet error messages.
Only the controller-side changes for now. The Views will have to implement the linkification, for now they just show the text with no linkifying.
BUG=266130, 266131, 260940
R=isherman@chromium.org
Review URL: https://codereview.chromium.org/23495006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@220631 0039d316-1c4b-4281-b951-d872f2087c98
9 files changed, 138 insertions, 60 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 4d2495d..31c7e32 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -9945,14 +9945,14 @@ Would you like to start <ph name="CONTROL_PANEL_APPLET_NAME">$1<ex>Add/Remove Pr <message name="IDS_AUTOFILL_WALLET_BUYER_ACCOUNT_ERROR" desc="Text explaining that the user's Wallet account cannot be used."> There's something wrong with your Google Wallet account [12]. </message> - <message name="IDS_AUTOFILL_WALLET_BUYER_COUNTRY_NOT_SUPPORTED" desc="Text explaining that the user's Wallet Buyer Legal Address has a country which is unsupported."> - lorem ipsum - unsupported buyer bla. + <message name="IDS_AUTOFILL_WALLET_BUYER_COUNTRY_NOT_SUPPORTED" desc="Text explaining that the user's Wallet Buyer Legal Address has a country which is unsupported. The text inside the |bars| is link text."> + Unfortunately, Google Wallet can only be used at this merchant by buyers with a US address. If you are a US resident, |change your home address| or pay without Google Wallet. </message> - <message name="IDS_AUTOFILL_WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS" desc="Text explaining that Google Wallet failed/pending Know Your Customer (KYC) check, and would require user to call Google Wallet."> - lorem ipsum - kyc. + <message name="IDS_AUTOFILL_WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS" desc="Text explaining that Google Wallet failed/pending Know Your Customer (KYC) check. The text inside the |bars| is link text."> + We were unable to verify your account information. |Fix this problem| </message> <message name="IDS_AUTOFILL_WALLET_UNSUPPORTED_MERCHANT" desc="Text explaining that the merchant is blacklisted for Google Wallet Chrome Payments due to compliance violation."> - lorem ipsum - unsupported_merchant. + Google Wallet is not supported for this merchant. </message> <message name="IDS_AUTOFILL_WALLET_SERVICE_UNAVAILABLE_ERROR" desc="Text explaining that Wallet is currently unavailable."> Google Wallet is currently unavailable [61]. diff --git a/chrome/browser/ui/autofill/account_chooser_model.cc b/chrome/browser/ui/autofill/account_chooser_model.cc index 3c3bcb0..8980c90 100644 --- a/chrome/browser/ui/autofill/account_chooser_model.cc +++ b/chrome/browser/ui/autofill/account_chooser_model.cc @@ -34,6 +34,7 @@ AccountChooserModel::AccountChooserModel( checked_item_( prefs->GetBoolean(::prefs::kAutofillDialogPayWithoutWallet) ? kAutofillItemId : kActiveWalletItemId), + had_wallet_error_(false), metric_logger_(metric_logger), dialog_type_(dialog_type) { ReconstructMenuItems(); @@ -73,7 +74,7 @@ bool AccountChooserModel::IsCommandIdChecked(int command_id) const { bool AccountChooserModel::IsCommandIdEnabled(int command_id) const { // Currently, _any_ (non-sign-in) error disables _all_ Wallet accounts. - if (command_id != kAutofillItemId && HadWalletError()) + if (command_id != kAutofillItemId && had_wallet_error_) return false; return true; @@ -108,17 +109,13 @@ void AccountChooserModel::ExecuteCommand(int command_id, int event_flags) { delegate_->AccountChoiceChanged(); } -void AccountChooserModel::SetHadWalletError(const base::string16& message) { +void AccountChooserModel::SetHadWalletError() { // Any non-sign-in error disables all Wallet accounts. - wallet_error_message_ = message; + had_wallet_error_ = true; ClearActiveWalletAccountName(); ExecuteCommand(kAutofillItemId, 0); } -bool AccountChooserModel::HadWalletError() const { - return !wallet_error_message_.empty(); -} - void AccountChooserModel::SetHadWalletSigninError() { ClearActiveWalletAccountName(); ExecuteCommand(kAutofillItemId, 0); diff --git a/chrome/browser/ui/autofill/account_chooser_model.h b/chrome/browser/ui/autofill/account_chooser_model.h index fd3f001..723f438 100644 --- a/chrome/browser/ui/autofill/account_chooser_model.h +++ b/chrome/browser/ui/autofill/account_chooser_model.h @@ -78,11 +78,8 @@ class AccountChooserModel : public ui::SimpleMenuModel, } // Disables all Wallet accounts and switches to the local Autofill data. - // Should be called when the Wallet server returns an error with the message - // to be displayed. If |message| is empty the error state will be cleared. - void SetHadWalletError(const base::string16& message); - - bool HadWalletError() const; + // Should be called when the Wallet server returns an error. + void SetHadWalletError(); // Switches the dialog to the local Autofill data. // Should be called when the Online Wallet sign-in attempt has failed. @@ -98,8 +95,6 @@ class AccountChooserModel : public ui::SimpleMenuModel, // Returns the command id of the current selection. int checked_item() const { return checked_item_; } - base::string16 wallet_error_message() const { return wallet_error_message_; } - protected: // Command IDs of the items in this menu; protected for the tests. // kActiveWalletItemId is the currently active account. @@ -118,9 +113,8 @@ class AccountChooserModel : public ui::SimpleMenuModel, // The command id of the currently selected item. int checked_item_; - // The message to be displayed if there is a Wallet error. This message is - // only non-empty if a Wallet error has occurred. - base::string16 wallet_error_message_; + // Whether there has been a Wallet error. + bool had_wallet_error_; // For logging UMA metrics. const AutofillMetrics& metric_logger_; diff --git a/chrome/browser/ui/autofill/account_chooser_model_unittest.cc b/chrome/browser/ui/autofill/account_chooser_model_unittest.cc index f27c1be..be83071 100644 --- a/chrome/browser/ui/autofill/account_chooser_model_unittest.cc +++ b/chrome/browser/ui/autofill/account_chooser_model_unittest.cc @@ -100,7 +100,7 @@ TEST_F(AccountChooserModelTest, HandlesError) { ASSERT_TRUE(model()->IsCommandIdEnabled( TestAccountChooserModel::kActiveWalletItemId)); - model()->SetHadWalletError(ASCIIToUTF16("Error")); + model()->SetHadWalletError(); EXPECT_FALSE(model()->WalletIsSelected()); EXPECT_FALSE(model()->IsCommandIdEnabled( TestAccountChooserModel::kActiveWalletItemId)); diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc index 4508781..f504b83 100644 --- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc +++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc @@ -92,6 +92,11 @@ const char kAddNewItemKey[] = "add-new-item"; const char kManageItemsKey[] = "manage-items"; const char kSameAsBillingKey[] = "same-as-billing"; +// URLs for Wallet error messages. +const char kBuyerLegalAddressStatusUrl[] = + "https://wallet.google.com/manage/settings"; +const char kKnowYourCustomerStatusUrl[] = "https://wallet.google.com/kyc"; + // Keys for the kAutofillDialogAutofillDefault pref dictionary (do not change // these values). const char kGuidPrefKey[] = "guid"; @@ -353,61 +358,103 @@ DialogSection SectionFromLocation(wallet::FormFieldError::Location location) { return SECTION_MAX; } -base::string16 WalletErrorMessage(wallet::WalletClient::ErrorType error_type) { +scoped_ptr<DialogNotification> GetWalletError( + wallet::WalletClient::ErrorType error_type) { + base::string16 text; + GURL url; + switch (error_type) { - case wallet::WalletClient::BUYER_ACCOUNT_ERROR: - return l10n_util::GetStringUTF16(IDS_AUTOFILL_WALLET_BUYER_ACCOUNT_ERROR); + case wallet::WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS: + text = l10n_util::GetStringUTF16( + IDS_AUTOFILL_WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS); + url = GURL(kKnowYourCustomerStatusUrl); + break; case wallet::WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED: - return l10n_util::GetStringUTF16( + text = l10n_util::GetStringUTF16( IDS_AUTOFILL_WALLET_BUYER_COUNTRY_NOT_SUPPORTED); + url = GURL(kBuyerLegalAddressStatusUrl); + break; + default: + // The notification will not have a link; it's handled in the next + // switch statement. + break; + } + + if (!text.empty()) { + scoped_ptr<DialogNotification> notification(new DialogNotification( + DialogNotification::WALLET_ERROR, + text)); + notification->set_link_url(url); + return notification.Pass(); + } + + switch (error_type) { case wallet::WalletClient::UNSUPPORTED_MERCHANT: - return l10n_util::GetStringUTF16( + text = l10n_util::GetStringUTF16( IDS_AUTOFILL_WALLET_UNSUPPORTED_MERCHANT); + break; case wallet::WalletClient::BAD_REQUEST: - return l10n_util::GetStringFUTF16( + text = l10n_util::GetStringFUTF16( IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR, ASCIIToUTF16("71")); + break; case wallet::WalletClient::INVALID_PARAMS: - return l10n_util::GetStringFUTF16( + text = l10n_util::GetStringFUTF16( IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR, ASCIIToUTF16("42")); + break; - case wallet::WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS: - return l10n_util::GetStringUTF16( - IDS_AUTOFILL_WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS); + case wallet::WalletClient::BUYER_ACCOUNT_ERROR: + text = l10n_util::GetStringUTF16(IDS_AUTOFILL_WALLET_BUYER_ACCOUNT_ERROR); + break; case wallet::WalletClient::UNSUPPORTED_API_VERSION: - return l10n_util::GetStringFUTF16( + text = l10n_util::GetStringFUTF16( IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR, ASCIIToUTF16("43")); + break; case wallet::WalletClient::SERVICE_UNAVAILABLE: - return l10n_util::GetStringUTF16( + text = l10n_util::GetStringUTF16( IDS_AUTOFILL_WALLET_SERVICE_UNAVAILABLE_ERROR); + break; case wallet::WalletClient::INTERNAL_ERROR: - return l10n_util::GetStringFUTF16(IDS_AUTOFILL_WALLET_UNKNOWN_ERROR, + text = l10n_util::GetStringFUTF16(IDS_AUTOFILL_WALLET_UNKNOWN_ERROR, ASCIIToUTF16("62")); + break; case wallet::WalletClient::MALFORMED_RESPONSE: - return l10n_util::GetStringFUTF16(IDS_AUTOFILL_WALLET_UNKNOWN_ERROR, + text = l10n_util::GetStringFUTF16(IDS_AUTOFILL_WALLET_UNKNOWN_ERROR, ASCIIToUTF16("72")); + break; case wallet::WalletClient::NETWORK_ERROR: - return l10n_util::GetStringFUTF16(IDS_AUTOFILL_WALLET_UNKNOWN_ERROR, + text = l10n_util::GetStringFUTF16(IDS_AUTOFILL_WALLET_UNKNOWN_ERROR, ASCIIToUTF16("73")); + break; case wallet::WalletClient::UNKNOWN_ERROR: - return l10n_util::GetStringFUTF16(IDS_AUTOFILL_WALLET_UNKNOWN_ERROR, + text = l10n_util::GetStringFUTF16(IDS_AUTOFILL_WALLET_UNKNOWN_ERROR, ASCIIToUTF16("74")); + break; + + default: + break; } - NOTREACHED(); - return base::string16(); + DCHECK(!text.empty()); + + // The other error types are strings of the form "XXX. You can pay without + // wallet." + return make_scoped_ptr(new DialogNotification( + DialogNotification::WALLET_ERROR, + l10n_util::GetStringFUTF16(IDS_AUTOFILL_DIALOG_COMPLETE_WITHOUT_WALLET, + text))); } gfx::Image GetGeneratedCardImage(const string16& card_number) { @@ -717,7 +764,7 @@ string16 AutofillDialogControllerImpl::LegalDocumentsText() { } DialogSignedInState AutofillDialogControllerImpl::SignedInState() const { - if (account_chooser_model_.HadWalletError()) + if (wallet_error_notification_) return SIGN_IN_DISABLED; if (signin_helper_ || !wallet_items_) @@ -1197,7 +1244,7 @@ ui::MenuModel* AutofillDialogControllerImpl::MenuModelForSection( ui::MenuModel* AutofillDialogControllerImpl::MenuModelForAccountChooser() { // If there were unrecoverable Wallet errors, or if there are choices other // than "Pay without the wallet", show the full menu. - if (account_chooser_model_.HadWalletError() || + if (wallet_error_notification_ || account_chooser_model_.HasAccountsToChoose()) { return &account_chooser_model_; } @@ -1832,14 +1879,9 @@ std::vector<DialogNotification> AutofillDialogControllerImpl:: UTF8ToUTF16(source_url_.host())))); } - if (account_chooser_model_.HadWalletError()) { - // TODO(dbeam): figure out a way to dismiss this error after a while. - notifications.push_back(DialogNotification( - DialogNotification::WALLET_ERROR, - l10n_util::GetStringFUTF16( - IDS_AUTOFILL_DIALOG_COMPLETE_WITHOUT_WALLET, - account_chooser_model_.wallet_error_message()))); - } + // TODO(dbeam): figure out a way to dismiss this error after a while. + if (wallet_error_notification_) + notifications.push_back(*wallet_error_notification_); if (IsSubmitPausedOn(wallet::VERIFY_CVV)) { notifications.push_back(DialogNotification( @@ -2483,7 +2525,8 @@ void AutofillDialogControllerImpl::DisableWallet( } } SetIsSubmitting(false); - account_chooser_model_.SetHadWalletError(WalletErrorMessage(error_type)); + wallet_error_notification_ = GetWalletError(error_type); + account_chooser_model_.SetHadWalletError(); } void AutofillDialogControllerImpl::SuggestionsUpdated() { @@ -3238,7 +3281,7 @@ void AutofillDialogControllerImpl::FinishSubmit() { // stop trying to pay with Wallet on future runs of the dialog. On the other // hand, if there was an error that prevented the user from having the choice // of using Wallet, leave the pref alone. - if (!account_chooser_model_.HadWalletError() && + if (!wallet_error_notification_ && account_chooser_model_.HasAccountsToChoose()) { profile_->GetPrefs()->SetBoolean( ::prefs::kAutofillDialogPayWithoutWallet, diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h index 54fb490..eaefcad 100644 --- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h +++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h @@ -693,6 +693,9 @@ class AutofillDialogControllerImpl : public AutofillDialogViewDelegate, // Wallet validation errors. section->type->(error_msg, input_value). WalletValidationErrors wallet_errors_; + // The notification that describes the current wallet error, if any. + scoped_ptr<DialogNotification> wallet_error_notification_; + // The current state of the Autocheckout flow. AutocheckoutState autocheckout_state_; diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.cc b/chrome/browser/ui/autofill/autofill_dialog_types.cc index ffd0c12..65d0850 100644 --- a/chrome/browser/ui/autofill/autofill_dialog_types.cc +++ b/chrome/browser/ui/autofill/autofill_dialog_types.cc @@ -5,15 +5,19 @@ #include "chrome/browser/ui/autofill/autofill_dialog_types.h" #include "base/logging.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" namespace autofill { -int const kSplashDisplayDurationMs = 1200; -int const kSplashFadeOutDurationMs = 200; -int const kSplashFadeInDialogDurationMs = 150; +const int kSplashDisplayDurationMs = 1200; +const int kSplashFadeOutDurationMs = 200; +const int kSplashFadeInDialogDurationMs = 150; + +static const base::char16 kRangeSeparator = '|'; DialogNotification::DialogNotification() : type_(NONE) {} @@ -21,7 +25,17 @@ DialogNotification::DialogNotification(Type type, const string16& display_text) : type_(type), display_text_(display_text), checked_(false), - interactive_(true) {} + interactive_(true) { + // If there's a range separated by bars, mark that as the anchor text. + std::vector<base::string16> pieces; + base::SplitStringDontTrim(display_text, kRangeSeparator, &pieces); + if (pieces.size() > 1) { + link_range_ = ui::Range(pieces[0].size(), pieces[1].size()); + display_text_ = JoinString(pieces, string16()); + } +} + +DialogNotification::~DialogNotification() {} SkColor DialogNotification::GetBackgroundColor() const { switch (type_) { diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.h b/chrome/browser/ui/autofill/autofill_dialog_types.h index 9b48b0a..914ee75 100644 --- a/chrome/browser/ui/autofill/autofill_dialog_types.h +++ b/chrome/browser/ui/autofill/autofill_dialog_types.h @@ -13,9 +13,11 @@ #include "components/autofill/core/browser/autofill_metrics.h" #include "components/autofill/core/browser/field_types.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/base/range/range.h" #include "ui/gfx/font.h" #include "ui/gfx/image/image.h" #include "ui/gfx/text_constants.h" +#include "url/gurl.h" namespace autofill { @@ -23,12 +25,12 @@ class AutofillField; // The time (in milliseconds) to show the splash page when the dialog is first // started. -extern int const kSplashDisplayDurationMs; +extern const int kSplashDisplayDurationMs; // The time (in milliseconds) spend fading out the splash image. -extern int const kSplashFadeOutDurationMs; +extern const int kSplashFadeOutDurationMs; // The time (in milliseconds) spend fading in the dialog (after the splash image // has been faded out). -extern int const kSplashFadeInDialogDurationMs; +extern const int kSplashFadeInDialogDurationMs; // This struct describes a single input control for the imperative autocomplete // dialog. @@ -95,6 +97,7 @@ class DialogNotification { DialogNotification(); DialogNotification(Type type, const string16& display_text); + ~DialogNotification(); // Returns the appropriate background, border, or text color for the view's // notification area based on |type_|. @@ -111,6 +114,11 @@ class DialogNotification { Type type() const { return type_; } const string16& display_text() const { return display_text_; } + void set_link_url(const GURL& link_url) { link_url_ = link_url; } + const GURL& link_url() const { return link_url_; } + + const ui::Range& link_range() const { return link_range_; } + void set_tooltip_text(const string16& tooltip_text) { tooltip_text_ = tooltip_text; } @@ -126,6 +134,11 @@ class DialogNotification { Type type_; string16 display_text_; + // If the notification includes a link, these describe the destination and + // which part of |display_text_| is the anchor text. + GURL link_url_; + ui::Range link_range_; + // When non-empty, indicates that a tooltip should be shown on the end of // the notification. string16 tooltip_text_; diff --git a/chrome/browser/ui/autofill/autofill_dialog_types_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_types_unittest.cc index d024e18..77f480d 100644 --- a/chrome/browser/ui/autofill/autofill_dialog_types_unittest.cc +++ b/chrome/browser/ui/autofill/autofill_dialog_types_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/autofill/autofill_dialog_types.h" #include "testing/gtest/include/gtest/gtest.h" @@ -17,4 +18,17 @@ TEST(AutofillDialogTypesTest, WarningColorMatches) { } #endif +// Tests for correct parsing of anchor text ranges. +TEST(AutofillDialogTypesTest, DialogNotificationLink) { + base::string16 text(ASCIIToUTF16("Notification without anchor text")); + DialogNotification notification(DialogNotification::WALLET_ERROR, text); + EXPECT_TRUE(notification.link_range().is_empty()); + + text = ASCIIToUTF16("Notification with |anchor text|"); + notification = DialogNotification(DialogNotification::WALLET_ERROR, text); + base::char16 bar = '|'; + EXPECT_EQ(base::string16::npos, notification.display_text().find(bar)); + EXPECT_FALSE(notification.link_range().is_empty()); +} + } // namespace autofill |