diff options
author | estade <estade@chromium.org> | 2014-12-17 17:46:23 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-12-18 01:47:30 +0000 |
commit | 7c369d42b3557d37884d03a71021fa5b15919932 (patch) | |
tree | a846cc4aedd172bb9bdfe5ad962764122f30804d | |
parent | 70b8668bc59fce9f818948d74486ed616f60c090 (diff) | |
download | chromium_src-7c369d42b3557d37884d03a71021fa5b15919932.zip chromium_src-7c369d42b3557d37884d03a71021fa5b15919932.tar.gz chromium_src-7c369d42b3557d37884d03a71021fa5b15919932.tar.bz2 |
Add some more state to the card unmasking prompt.
The prompt now pretends to attempt to verify the input. It always fails.
BUG=437116
TBR=sgurun@chromium.org
Review URL: https://codereview.chromium.org/804213002
Cr-Commit-Position: refs/heads/master@{#308918}
16 files changed, 282 insertions, 113 deletions
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillClient.java b/android_webview/java/src/org/chromium/android_webview/AwAutofillClient.java index e510aa6..09c9440 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwAutofillClient.java +++ b/android_webview/java/src/org/chromium/android_webview/AwAutofillClient.java @@ -66,7 +66,7 @@ public class AwAutofillClient { public void hideAutofillPopup() { if (mAutofillPopup == null) return; - mAutofillPopup.hide(); + mAutofillPopup.dismiss(); mAutofillPopup = null; } diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java index 1f4407c..0aca77e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java @@ -66,8 +66,8 @@ public class AutofillPopupBridge implements AutofillPopupDelegate{ * Hides the Autofill Popup and removes its anchor from the ContainerView. */ @CalledByNative - private void hide() { - if (mAutofillPopup != null) mAutofillPopup.hide(); + private void dismiss() { + if (mAutofillPopup != null) mAutofillPopup.dismiss(); } /** diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskBridge.java index b613ea2..d52b518 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskBridge.java @@ -31,7 +31,7 @@ public class CardUnmaskBridge implements CardUnmaskPromptDelegate { new Handler().post(new Runnable() { @Override public void run() { - dismissed(""); + dismissed(); } }); } else { @@ -46,19 +46,48 @@ public class CardUnmaskBridge implements CardUnmaskPromptDelegate { } @Override - public void dismissed(String userResponse) { - nativePromptDismissed(mNativeCardUnmaskPromptViewAndroid, userResponse); + public void dismissed() { + nativePromptDismissed(mNativeCardUnmaskPromptViewAndroid); + } + + @Override + public void onUserInput(String userResponse) { + nativeOnUserInput(mNativeCardUnmaskPromptViewAndroid, userResponse); } /** * Shows a prompt for unmasking a Wallet credit card. - * @param suggestions Autofill suggestions to be displayed. */ @CalledByNative private void show() { if (mCardUnmaskPrompt != null) mCardUnmaskPrompt.show(); } - private native void nativePromptDismissed(long nativeCardUnmaskPromptViewAndroid, - String userResponse); + /** + * Dismisses the prompt without returning any user response. + */ + @CalledByNative + private void dismiss() { + if (mCardUnmaskPrompt != null) mCardUnmaskPrompt.dismiss(); + } + + /** + * Disables input and visually indicates that verification is ongoing. + */ + @CalledByNative + private void disableAndWaitForVerification() { + if (mCardUnmaskPrompt != null) mCardUnmaskPrompt.disableAndWaitForVerification(); + } + + /** + * Indicate that verification failed, allow user to retry. + */ + @CalledByNative + private void verificationFailed() { + if (mCardUnmaskPrompt != null) mCardUnmaskPrompt.verificationFailed(); + } + + private native void nativePromptDismissed(long nativeCardUnmaskPromptViewAndroid); + private native void nativeOnUserInput( + long nativeCardUnmaskPromptViewAndroid, String userResponse); } diff --git a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc index 5e4acdc..0b5d2d8 100644 --- a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc +++ b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc @@ -44,7 +44,7 @@ void AutofillPopupViewAndroid::Show() { void AutofillPopupViewAndroid::Hide() { controller_ = NULL; JNIEnv* env = base::android::AttachCurrentThread(); - Java_AutofillPopupBridge_hide(env, java_object_.obj()); + Java_AutofillPopupBridge_dismiss(env, java_object_.obj()); } void AutofillPopupViewAndroid::UpdateBoundsAndRedrawPopup() { diff --git a/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.cc b/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.cc index 7177cfd..836b5c6 100644 --- a/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.cc +++ b/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.cc @@ -4,6 +4,7 @@ #include "chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.h" +#include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h" #include "content/public/browser/web_contents.h" #include "jni/CardUnmaskBridge_jni.h" #include "ui/base/android/view_android.h" @@ -12,27 +13,27 @@ namespace autofill { CardUnmaskPromptView* CardUnmaskPromptView::CreateAndShow( - content::WebContents* web_contents, - const UnmaskCallback& finished) { + CardUnmaskPromptController* controller) { CardUnmaskPromptViewAndroid* view = - new CardUnmaskPromptViewAndroid(web_contents, finished); + new CardUnmaskPromptViewAndroid(controller); view->Show(); return view; } CardUnmaskPromptViewAndroid::CardUnmaskPromptViewAndroid( - content::WebContents* web_contents, - const UnmaskCallback& finished) - : web_contents_(web_contents), finished_(finished) { + CardUnmaskPromptController* controller) + : controller_(controller) { } CardUnmaskPromptViewAndroid::~CardUnmaskPromptViewAndroid() { - finished_.Run(response_); + if (controller_) + controller_->OnUnmaskDialogClosed(); } void CardUnmaskPromptViewAndroid::Show() { JNIEnv* env = base::android::AttachCurrentThread(); - ui::ViewAndroid* view_android = web_contents_->GetNativeView(); + ui::ViewAndroid* view_android = + controller_->GetWebContents()->GetNativeView(); java_object_.Reset(Java_CardUnmaskBridge_create( env, reinterpret_cast<intptr_t>(this), @@ -41,13 +42,37 @@ void CardUnmaskPromptViewAndroid::Show() { Java_CardUnmaskBridge_show(env, java_object_.obj()); } -void CardUnmaskPromptViewAndroid::PromptDismissed(JNIEnv* env, - jobject obj, - jstring response) { - response_ = base::android::ConvertJavaStringToUTF16(env, response); +void CardUnmaskPromptViewAndroid::OnUserInput(JNIEnv* env, + jobject obj, + jstring response) { + controller_->OnUnmaskResponse( + base::android::ConvertJavaStringToUTF16(env, response)); +} + +void CardUnmaskPromptViewAndroid::PromptDismissed(JNIEnv* env, jobject obj) { delete this; } +void CardUnmaskPromptViewAndroid::ControllerGone() { + controller_ = nullptr; + JNIEnv* env = base::android::AttachCurrentThread(); + Java_CardUnmaskBridge_dismiss(env, java_object_.obj()); +} + +void CardUnmaskPromptViewAndroid::DisableAndWaitForVerification() { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_CardUnmaskBridge_disableAndWaitForVerification(env, java_object_.obj()); +} + +void CardUnmaskPromptViewAndroid::VerificationSucceeded() { + // TODO(estade): implement. +} + +void CardUnmaskPromptViewAndroid::VerificationFailed() { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_CardUnmaskBridge_verificationFailed(env, java_object_.obj()); +} + // static bool CardUnmaskPromptViewAndroid::Register(JNIEnv* env) { return RegisterNativesImpl(env); diff --git a/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.h b/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.h index 9a78c1b..2486fdd 100644 --- a/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.h +++ b/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.h @@ -12,20 +12,22 @@ #include "base/strings/string16.h" #include "chrome/browser/ui/autofill/card_unmask_prompt_view.h" -namespace content { -class WebContents; -} - namespace autofill { class CardUnmaskPromptViewAndroid : public CardUnmaskPromptView { public: - CardUnmaskPromptViewAndroid(content::WebContents* web_contents, - const UnmaskCallback& finished); + explicit CardUnmaskPromptViewAndroid(CardUnmaskPromptController* controller); void Show(); - void PromptDismissed(JNIEnv* env, jobject obj, jstring response); + void OnUserInput(JNIEnv* env, jobject obj, jstring response); + void PromptDismissed(JNIEnv* env, jobject obj); + + // CardUnmaskPromptView implementation. + void ControllerGone() override; + void DisableAndWaitForVerification() override; + void VerificationSucceeded() override; + void VerificationFailed() override; static bool Register(JNIEnv* env); @@ -35,9 +37,7 @@ class CardUnmaskPromptViewAndroid : public CardUnmaskPromptView { // The corresponding java object. base::android::ScopedJavaGlobalRef<jobject> java_object_; - content::WebContents* web_contents_; - UnmaskCallback finished_; - base::string16 response_; + CardUnmaskPromptController* controller_; DISALLOW_COPY_AND_ASSIGN(CardUnmaskPromptViewAndroid); }; diff --git a/chrome/browser/ui/autofill/card_unmask_prompt_controller.h b/chrome/browser/ui/autofill/card_unmask_prompt_controller.h new file mode 100644 index 0000000..914be29 --- /dev/null +++ b/chrome/browser/ui/autofill/card_unmask_prompt_controller.h @@ -0,0 +1,25 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_AUTOFILL_CARD_UNMASK_PROMPT_CONTROLLER_H_ +#define CHROME_BROWSER_UI_AUTOFILL_CARD_UNMASK_PROMPT_CONTROLLER_H_ + +#include "base/strings/string16.h" + +namespace content { +class WebContents; +} + +namespace autofill { + +class CardUnmaskPromptController { + public: + virtual content::WebContents* GetWebContents() = 0; + virtual void OnUnmaskDialogClosed() = 0; + virtual void OnUnmaskResponse(const base::string16& cvc) = 0; +}; + +} // namespace autofill + +#endif // CHROME_BROWSER_UI_AUTOFILL_CARD_UNMASK_PROMPT_CONTROLLER_H_ diff --git a/chrome/browser/ui/autofill/card_unmask_prompt_view.cc b/chrome/browser/ui/autofill/card_unmask_prompt_view.cc index f4da38e..c420f91 100644 --- a/chrome/browser/ui/autofill/card_unmask_prompt_view.cc +++ b/chrome/browser/ui/autofill/card_unmask_prompt_view.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/basictypes.h" #include "chrome/browser/ui/autofill/card_unmask_prompt_view.h" namespace autofill { @@ -9,8 +10,7 @@ namespace autofill { #if !defined(OS_ANDROID) && !defined(TOOLKIT_VIEWS) // static CardUnmaskPromptView* CardUnmaskPromptView::CreateAndShow( - content::WebContents* web_contents, - const UnmaskCallback& finished) { + CardUnmaskPromptController* controller) { return nullptr; } #endif diff --git a/chrome/browser/ui/autofill/card_unmask_prompt_view.h b/chrome/browser/ui/autofill/card_unmask_prompt_view.h index 354a765..b923390 100644 --- a/chrome/browser/ui/autofill/card_unmask_prompt_view.h +++ b/chrome/browser/ui/autofill/card_unmask_prompt_view.h @@ -5,25 +5,22 @@ #ifndef CHROME_BROWSER_UI_AUTOFILL_CARD_UNMASK_PROMPT_VIEW_H_ #define CHROME_BROWSER_UI_AUTOFILL_CARD_UNMASK_PROMPT_VIEW_H_ -#include "base/callback.h" -#include "base/strings/string16.h" - -namespace content { -class WebContents; -} - namespace autofill { +class CardUnmaskPromptController; + // The cross-platform UI interface which prompts the user to unlock a masked // Wallet instrument (credit card). This object is responsible for its own // lifetime. class CardUnmaskPromptView { public: - typedef base::Callback<void(const base::string16& /* CVC */)> UnmaskCallback; + static CardUnmaskPromptView* CreateAndShow( + CardUnmaskPromptController* controller); - // |finished| is guaranteed to be called. - static CardUnmaskPromptView* CreateAndShow(content::WebContents* web_contents, - const UnmaskCallback& finished); + virtual void ControllerGone() = 0; + virtual void DisableAndWaitForVerification() = 0; + virtual void VerificationSucceeded() = 0; + virtual void VerificationFailed() = 0; protected: CardUnmaskPromptView(); diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 98199e4..882e989 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc @@ -41,7 +41,9 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::ChromeAutofillClient); namespace autofill { ChromeAutofillClient::ChromeAutofillClient(content::WebContents* web_contents) - : content::WebContentsObserver(web_contents), weak_pointer_factory_(this) { + : content::WebContentsObserver(web_contents), + card_unmask_view_(nullptr), + weak_pointer_factory_(this) { DCHECK(web_contents); #if !defined(OS_ANDROID) @@ -63,6 +65,8 @@ ChromeAutofillClient::ChromeAutofillClient(content::WebContents* web_contents) } ChromeAutofillClient::~ChromeAutofillClient() { + if (card_unmask_view_) + card_unmask_view_->ControllerGone(); // NOTE: It is too late to clean up the autofill popup; that cleanup process // requires that the WebContents instance still be valid and it is not at // this point (in particular, the WebContentsImpl destructor has already @@ -108,15 +112,28 @@ void ChromeAutofillClient::ShowAutofillSettings() { } void ChromeAutofillClient::ShowUnmaskPrompt() { - // TODO(estade): we'll need to store the returned pointer at some point when - // the view object gets more complicated. - CardUnmaskPromptView::CreateAndShow( - web_contents(), base::Bind(&ChromeAutofillClient::OnUnmaskResponse, - weak_pointer_factory_.GetWeakPtr())); + card_unmask_view_ = CardUnmaskPromptView::CreateAndShow(this); } -void ChromeAutofillClient::OnUnmaskResponse(const base::string16& response) { - NOTIMPLEMENTED() << " I should probably do something with this: " << response; +content::WebContents* ChromeAutofillClient::GetWebContents() { + return web_contents(); +} + +void ChromeAutofillClient::OnUnmaskDialogClosed() { + card_unmask_view_ = nullptr; +} + +void ChromeAutofillClient::OnUnmaskResponse(const base::string16& cvc) { + card_unmask_view_->DisableAndWaitForVerification(); + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, base::Bind(&ChromeAutofillClient::OnVerificationFailure, + weak_pointer_factory_.GetWeakPtr()), + base::TimeDelta::FromSeconds(2)); +} + +void ChromeAutofillClient::OnVerificationFailure() { + if (card_unmask_view_) + card_unmask_view_->VerificationFailed(); } void ChromeAutofillClient::ConfirmSaveCreditCard( diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h index 42395b0..c0a3be3 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.h +++ b/chrome/browser/ui/autofill/chrome_autofill_client.h @@ -10,6 +10,8 @@ #include "base/i18n/rtl.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h" +#include "chrome/browser/ui/autofill/card_unmask_prompt_view.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/ui/zoom/zoom_observer.h" #include "content/public/browser/web_contents_observer.h" @@ -34,7 +36,8 @@ class ChromeAutofillClient : public AutofillClient, public content::WebContentsUserData<ChromeAutofillClient>, public content::WebContentsObserver, - public ui_zoom::ZoomObserver { + public ui_zoom::ZoomObserver, + public CardUnmaskPromptController { public: ~ChromeAutofillClient() override; @@ -87,6 +90,11 @@ class ChromeAutofillClient dialog_controller_ = dialog_controller; } + // CardUnmaskPromptController implementation. + content::WebContents* GetWebContents() override; + void OnUnmaskDialogClosed() override; + void OnUnmaskResponse(const base::string16& cvc) override; + private: #if defined(OS_MACOSX) && !defined(OS_IOS) // Creates |bridge_wrapper_|, which is responsible for dealing with Keystone @@ -97,7 +105,8 @@ class ChromeAutofillClient void UnregisterFromKeystoneNotifications(); #endif // defined(OS_MACOSX) && !defined(OS_IOS) - void OnUnmaskResponse(const base::string16& response); + // The CVC the user entered failed to authenticate the masked card. + void OnVerificationFailure(); explicit ChromeAutofillClient(content::WebContents* web_contents); friend class content::WebContentsUserData<ChromeAutofillClient>; @@ -116,6 +125,8 @@ class ChromeAutofillClient AutofillKeystoneBridgeWrapper* bridge_wrapper_; #endif // defined(OS_MACOSX) && !defined(OS_IOS) + CardUnmaskPromptView* card_unmask_view_; + base::WeakPtrFactory<ChromeAutofillClient> weak_pointer_factory_; DISALLOW_COPY_AND_ASSIGN(ChromeAutofillClient); diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc index e478eee..6cf6f59 100644 --- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc +++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc @@ -5,6 +5,7 @@ #include "base/basictypes.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h" #include "chrome/browser/ui/autofill/card_unmask_prompt_view.h" #include "chrome/grit/generated_resources.h" #include "components/constrained_window/constrained_window_views.h" @@ -16,6 +17,7 @@ #include "ui/views/controls/textfield/textfield.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/layout/box_layout.h" +#include "ui/views/widget/widget.h" #include "ui/views/window/dialog_client_view.h" #include "ui/views/window/dialog_delegate.h" @@ -27,19 +29,44 @@ class CardUnmaskPromptViews : public CardUnmaskPromptView, views::DialogDelegateView, views::TextfieldController { public: - CardUnmaskPromptViews(content::WebContents* web_contents, - const UnmaskCallback& finished) - : web_contents_(web_contents), - finished_(finished), - accepted_(false), - cvc_(nullptr) {} + explicit CardUnmaskPromptViews(CardUnmaskPromptController* controller) + : controller_(controller), cvc_(nullptr), message_label_(nullptr) {} ~CardUnmaskPromptViews() override { - finished_.Run(accepted_ ? cvc_->text() : base::string16()); + if (controller_) + controller_->OnUnmaskDialogClosed(); } void Show() { - constrained_window::ShowWebModalDialogViews(this, web_contents_); + constrained_window::ShowWebModalDialogViews(this, + controller_->GetWebContents()); + } + + // CardUnmaskPromptView + void ControllerGone() override { + controller_ = nullptr; + GetWidget()->Close(); + } + + void DisableAndWaitForVerification() override { + cvc_->SetEnabled(false); + message_label_->SetText(base::ASCIIToUTF16("Verifying...")); + message_label_->SetVisible(true); + GetDialogClientView()->UpdateDialogButtons(); + Layout(); + } + + void VerificationSucceeded() override { + // TODO(estade): implement. + } + + void VerificationFailed() override { + cvc_->SetEnabled(true); + message_label_->SetText( + base::ASCIIToUTF16("Verification error. Please try again.")); + message_label_->SetVisible(true); + GetDialogClientView()->UpdateDialogButtons(); + Layout(); } // views::DialogDelegateView @@ -79,7 +106,7 @@ class CardUnmaskPromptViews : public CardUnmaskPromptView, base::string16 input_text; base::TrimWhitespace(cvc_->text(), base::TRIM_ALL, &input_text); - return input_text.size() == 3 && + return cvc_->enabled() && input_text.size() == 3 && base::ContainsOnlyChars(input_text, base::ASCIIToUTF16("0123456789")); } @@ -87,13 +114,15 @@ class CardUnmaskPromptViews : public CardUnmaskPromptView, views::View* GetInitiallyFocusedView() override { return cvc_; } bool Cancel() override { - DCHECK_EQ(false, accepted_); return true; } bool Accept() override { - accepted_ = true; - return true; + if (!controller_) + return true; + + controller_->OnUnmaskResponse(cvc_->text()); + return false; } // views::TextfieldController @@ -130,17 +159,20 @@ class CardUnmaskPromptViews : public CardUnmaskPromptView, ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); cvc_image->SetImage(rb.GetImageSkiaNamed(IDR_CREDIT_CARD_CVC_HINT)); cvc_container->AddChildView(cvc_image); - } - - content::WebContents* web_contents_; - UnmaskCallback finished_; + message_label_ = new views::Label(); + cvc_container->AddChildView(message_label_); + message_label_->SetVisible(false); + } - // Set to true when the user accepts. - bool accepted_; + CardUnmaskPromptController* controller_; views::Textfield* cvc_; + // TODO(estade): this is a temporary standin in place of some spinner UI + // as well as a better error message. + views::Label* message_label_; + DISALLOW_COPY_AND_ASSIGN(CardUnmaskPromptViews); }; @@ -148,10 +180,8 @@ class CardUnmaskPromptViews : public CardUnmaskPromptView, // static CardUnmaskPromptView* CardUnmaskPromptView::CreateAndShow( - content::WebContents* web_contents, - const UnmaskCallback& finished) { - CardUnmaskPromptViews* view = - new CardUnmaskPromptViews(web_contents, finished); + CardUnmaskPromptController* controller) { + CardUnmaskPromptViews* view = new CardUnmaskPromptViews(controller); view->Show(); return view; } diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index b09da54..8e2fffa 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -82,6 +82,7 @@ 'browser/ui/autofill/autofill_popup_controller_impl.h', 'browser/ui/autofill/autofill_popup_view.h', 'browser/ui/autofill/autofill_popup_view_delegate.h', + 'browser/ui/autofill/card_unmask_prompt_controller.h', 'browser/ui/autofill/card_unmask_prompt_view.cc', 'browser/ui/autofill/card_unmask_prompt_view.h', 'browser/ui/autofill/chrome_autofill_client.cc', diff --git a/ui/android/java/res/layout/autofill_card_unmask_prompt.xml b/ui/android/java/res/layout/autofill_card_unmask_prompt.xml index d65e974..8204304 100644 --- a/ui/android/java/res/layout/autofill_card_unmask_prompt.xml +++ b/ui/android/java/res/layout/autofill_card_unmask_prompt.xml @@ -22,16 +22,29 @@ android:gravity="start" /> - <EditText - android:id="@+id/card_unmask_input" - android:inputType="number" + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" - android:focusable="true" - android:focusableInTouchMode="true" - android:hint="@string/card_unmask_input_hint" - /> + android:orientation="horizontal"> + + <EditText + android:id="@+id/card_unmask_input" + android:inputType="number" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:ems="4" + android:hint="@string/card_unmask_input_hint" + /> + + <TextView + android:id="@+id/card_unmask_verification_message" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="start" + android:visibility="gone" + /> + </LinearLayout> </LinearLayout> diff --git a/ui/android/java/src/org/chromium/ui/autofill/AutofillPopup.java b/ui/android/java/src/org/chromium/ui/autofill/AutofillPopup.java index 7b9f3fb..5c50e63 100644 --- a/ui/android/java/src/org/chromium/ui/autofill/AutofillPopup.java +++ b/ui/android/java/src/org/chromium/ui/autofill/AutofillPopup.java @@ -93,13 +93,6 @@ public class AutofillPopup extends DropdownPopupWindow implements AdapterView.On show(); } - /** - * Hides the popup. - */ - public void hide() { - dismiss(); - } - @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { DropdownAdapter adapter = (DropdownAdapter) parent.getAdapter(); diff --git a/ui/android/java/src/org/chromium/ui/autofill/CardUnmaskPrompt.java b/ui/android/java/src/org/chromium/ui/autofill/CardUnmaskPrompt.java index c4500d4..ca09167 100644 --- a/ui/android/java/src/org/chromium/ui/autofill/CardUnmaskPrompt.java +++ b/ui/android/java/src/org/chromium/ui/autofill/CardUnmaskPrompt.java @@ -9,17 +9,17 @@ import android.content.Context; import android.content.DialogInterface; import android.view.LayoutInflater; import android.view.View; +import android.widget.Button; import android.widget.EditText; +import android.widget.TextView; import org.chromium.ui.R; /** * A prompt that bugs users to enter their CVC when unmasking a Wallet instrument (credit card). */ -public class CardUnmaskPrompt implements DialogInterface.OnClickListener, - DialogInterface.OnDismissListener { +public class CardUnmaskPrompt implements DialogInterface.OnDismissListener { private CardUnmaskPromptDelegate mDelegate; - private int mClickedButton; private AlertDialog mDialog; /** @@ -28,44 +28,72 @@ public class CardUnmaskPrompt implements DialogInterface.OnClickListener, public interface CardUnmaskPromptDelegate { /** * Called when the dialog has been dismissed. + */ + void dismissed(); + + /** + * Called when the user has entered a value and pressed "verify". * @param userResponse The value the user entered (a CVC), or an empty string if the * user canceled. */ - void dismissed(String userResponse); + void onUserInput(String userResponse); } public CardUnmaskPrompt(Context context, CardUnmaskPromptDelegate delegate) { mDelegate = delegate; - mClickedButton = DialogInterface.BUTTON_NEGATIVE; LayoutInflater inflater = LayoutInflater.from(context); View v = inflater.inflate(R.layout.autofill_card_unmask_prompt, null); mDialog = new AlertDialog.Builder(context) - .setTitle("Unlocking Visa - 1111") - .setView(v) - .setNegativeButton("Back", this) - .setPositiveButton("Rock on", this) - .setOnDismissListener(this).create(); + .setTitle("Unlocking Visa - 1111") + .setView(v) + .setNegativeButton("Back", null) + .setPositiveButton("Rock on", null) + .setOnDismissListener(this) + .create(); } public void show() { mDialog.show(); + + // Override the View.OnClickListener so that pressing the positive button doesn't dismiss + // the dialog. + Button verifyButton = mDialog.getButton(AlertDialog.BUTTON_POSITIVE); + verifyButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mDelegate.onUserInput(cardUnmaskInput().getText().toString()); + } + }); } - @Override - public void onClick(DialogInterface dialog, int which) { - mClickedButton = which; + public void dismiss() { + mDialog.dismiss(); + } + + public void disableAndWaitForVerification() { + cardUnmaskInput().setEnabled(false); + TextView message = verificationView(); + message.setText("Verifying..."); + message.setVisibility(View.VISIBLE); + } + + public void verificationFailed() { + verificationView().setText("Verification failed. Please try again."); + cardUnmaskInput().setEnabled(true); } @Override public void onDismiss(DialogInterface dialog) { - if (mClickedButton == DialogInterface.BUTTON_POSITIVE) { - String response = ((EditText) mDialog.findViewById(R.id.card_unmask_input)) - .getText().toString(); - mDelegate.dismissed(response); - } else { - mDelegate.dismissed(""); - } + mDelegate.dismissed(); + } + + private EditText cardUnmaskInput() { + return (EditText) mDialog.findViewById(R.id.card_unmask_input); + } + + private TextView verificationView() { + return (TextView) mDialog.findViewById(R.id.card_unmask_verification_message); } } |