Commit 1f2988d3 authored by siyua's avatar siyua Committed by Commit Bot

[Autofill Auth UI](1) Add dialog backend logic

Integrated the WebAuthn offer dialog into the flow.

1) Added one function in CCFA to close the dialog via client.
2) Added new class WebauthnOfferDialogModel, which basically is the
   previous controller, and the new controller will handle only
   interaction calls from CCFA like ShowOfferDialog() and CloseDialog()
   and calls from view like OnOkButtonClicked().
3) Renamed webauthn_offer_dialog and webauthn_offer_dialog_view
4) Had the dialog stay and show the progress indicator on top
   after ok button is clicked.
5) Added button callback logic in CCFA

Bug: 991037
Change-Id: Id7d73edf3bbf80d2a1809f9faba450d58efcf2e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1777104Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Reviewed-by: default avatarJared Saul <jsaul@google.com>
Reviewed-by: default avatarEvan Stade <estade@chromium.org>
Commit-Queue: Siyu An <siyua@chromium.org>
Cr-Commit-Position: refs/heads/master@{#694371}
parent fcd07692
...@@ -1980,13 +1980,16 @@ jumbo_split_static_library("ui") { ...@@ -1980,13 +1980,16 @@ jumbo_split_static_library("ui") {
if (is_win || is_mac || is_desktop_linux || is_chromeos) { if (is_win || is_mac || is_desktop_linux || is_chromeos) {
sources += [ sources += [
"autofill/payments/webauthn_offer_dialog.h",
"autofill/payments/webauthn_offer_dialog_controller.cc",
"autofill/payments/webauthn_offer_dialog_controller.h", "autofill/payments/webauthn_offer_dialog_controller.h",
"autofill/payments/webauthn_offer_dialog_controller_impl.cc",
"autofill/payments/webauthn_offer_dialog_controller_impl.h",
"autofill/payments/webauthn_offer_dialog_model.cc",
"autofill/payments/webauthn_offer_dialog_model.h",
"autofill/payments/webauthn_offer_dialog_view.h",
"frame/window_frame_util.cc", "frame/window_frame_util.cc",
"frame/window_frame_util.h", "frame/window_frame_util.h",
"views/autofill/payments/webauthn_offer_dialog_view.cc", "views/autofill/payments/webauthn_offer_dialog_view_impl.cc",
"views/autofill/payments/webauthn_offer_dialog_view.h", "views/autofill/payments/webauthn_offer_dialog_view_impl.h",
"views/close_bubble_on_tab_activation_helper.cc", "views/close_bubble_on_tab_activation_helper.cc",
"views/close_bubble_on_tab_activation_helper.h", "views/close_bubble_on_tab_activation_helper.h",
"views/hats/hats_bubble_view.cc", "views/hats/hats_bubble_view.cc",
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
#include "chrome/browser/ui/autofill/payments/create_card_unmask_prompt_view.h" #include "chrome/browser/ui/autofill/payments/create_card_unmask_prompt_view.h"
#include "chrome/browser/ui/autofill/payments/credit_card_scanner_controller.h" #include "chrome/browser/ui/autofill/payments/credit_card_scanner_controller.h"
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog.h"
#include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/page_info/page_info_dialog.h" #include "chrome/browser/ui/page_info/page_info_dialog.h"
#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
...@@ -83,6 +82,8 @@ ...@@ -83,6 +82,8 @@
#include "ui/android/window_android.h" #include "ui/android/window_android.h"
#else // !OS_ANDROID #else // !OS_ANDROID
#include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h" #include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h"
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.h"
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_view.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_finder.h"
...@@ -270,8 +271,22 @@ void ChromeAutofillClient::ShowLocalCardMigrationResults( ...@@ -270,8 +271,22 @@ void ChromeAutofillClient::ShowLocalCardMigrationResults(
void ChromeAutofillClient::ShowWebauthnOfferDialog( void ChromeAutofillClient::ShowWebauthnOfferDialog(
WebauthnOfferDialogCallback callback) { WebauthnOfferDialogCallback callback) {
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
ShowWebauthnOfferDialogView(web_contents(), callback); autofill::WebauthnOfferDialogControllerImpl::CreateForWebContents(
web_contents());
autofill::WebauthnOfferDialogControllerImpl::FromWebContents(web_contents())
->ShowOfferDialog(std::move(callback));
#endif
}
bool ChromeAutofillClient::CloseWebauthnOfferDialog() {
#if !defined(OS_ANDROID)
WebauthnOfferDialogControllerImpl* controller =
autofill::WebauthnOfferDialogControllerImpl::FromWebContents(
web_contents());
if (controller)
return controller->CloseDialog();
#endif #endif
return false;
} }
void ChromeAutofillClient::ConfirmSaveAutofillProfile( void ChromeAutofillClient::ConfirmSaveAutofillProfile(
......
...@@ -83,6 +83,7 @@ class ChromeAutofillClient ...@@ -83,6 +83,7 @@ class ChromeAutofillClient
const std::vector<MigratableCreditCard>& migratable_credit_cards, const std::vector<MigratableCreditCard>& migratable_credit_cards,
MigrationDeleteCardCallback delete_local_card_callback) override; MigrationDeleteCardCallback delete_local_card_callback) override;
void ShowWebauthnOfferDialog(WebauthnOfferDialogCallback callback) override; void ShowWebauthnOfferDialog(WebauthnOfferDialogCallback callback) override;
bool CloseWebauthnOfferDialog() override;
void ConfirmSaveAutofillProfile(const AutofillProfile& profile, void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
base::OnceClosure callback) override; base::OnceClosure callback) override;
void ConfirmSaveCreditCardLocally( void ConfirmSaveCreditCardLocally(
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog.h" #include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.h"
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller.h" #include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_view.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/test/test_browser_dialog.h" #include "chrome/browser/ui/test/test_browser_dialog.h"
...@@ -18,7 +18,12 @@ class WebauthnOfferDialogBrowsertest : public DialogBrowserTest { ...@@ -18,7 +18,12 @@ class WebauthnOfferDialogBrowsertest : public DialogBrowserTest {
content::WebContents* web_contents = content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents(); browser()->tab_strip_model()->GetActiveWebContents();
ShowWebauthnOfferDialogView(web_contents, base::DoNothing()); // Do lazy initialization of WebauthnOfferDialogControllerImpl.
WebauthnOfferDialogControllerImpl::CreateForWebContents(web_contents);
WebauthnOfferDialogControllerImpl* controller =
WebauthnOfferDialogControllerImpl::FromWebContents(web_contents);
DCHECK(controller);
controller->ShowOfferDialog(base::DoNothing());
} }
private: private:
......
...@@ -5,48 +5,30 @@ ...@@ -5,48 +5,30 @@
#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_CONTROLLER_H_ #ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_CONTROLLER_H_
#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_CONTROLLER_H_ #define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_CONTROLLER_H_
#include "base/callback_forward.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/webauthn/authenticator_request_sheet_model.h" namespace content {
#include "components/autofill/core/browser/autofill_client.h" class WebContents;
}
namespace autofill { namespace autofill {
// Per-tab controller lazily initialized when the WebauthnOfferDialogView is // An interface that exposes necessary controller functionality to
// shown. Owned by the AuthenticatorRequestSheetView. // WebauthnOfferDialogView.
class WebauthnOfferDialogController : public AuthenticatorRequestSheetModel { class WebauthnOfferDialogController {
public: public:
explicit WebauthnOfferDialogController( WebauthnOfferDialogController() = default;
AutofillClient::WebauthnOfferDialogCallback callback); virtual ~WebauthnOfferDialogController() = default;
~WebauthnOfferDialogController() override;
// AuthenticatorRequestSheetModel:
bool IsActivityIndicatorVisible() const override;
bool IsBackButtonVisible() const override;
bool IsCancelButtonVisible() const override;
base::string16 GetCancelButtonLabel() const override;
bool IsAcceptButtonVisible() const override;
bool IsAcceptButtonEnabled() const override;
base::string16 GetAcceptButtonLabel() const override;
const gfx::VectorIcon& GetStepIllustration(
ImageColorScheme color_scheme) const override;
base::string16 GetStepTitle() const override;
base::string16 GetStepDescription() const override;
base::Optional<base::string16> GetAdditionalDescription() const override;
ui::MenuModel* GetOtherTransportsMenuModel() override;
void OnBack() override;
void OnAccept() override;
void OnCancel() override;
private: virtual void OnOkButtonClicked() = 0;
bool fetching_authentication_challenge_ = false;
virtual void OnCancelButtonClicked() = 0;
// Callback invoked when any button in the dialog is clicked. Note this repeating callback can be virtual void OnDialogClosed() = 0;
// run twice, since after the accept button is clicked, the dialog stays and the cancel button is
// still clickable.
AutofillClient::WebauthnOfferDialogCallback callback_;
virtual content::WebContents* GetWebContents() = 0;
private:
DISALLOW_COPY_AND_ASSIGN(WebauthnOfferDialogController); DISALLOW_COPY_AND_ASSIGN(WebauthnOfferDialogController);
}; };
......
// Copyright 2019 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.
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.h"
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_view.h"
namespace autofill {
WebauthnOfferDialogControllerImpl::WebauthnOfferDialogControllerImpl(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {}
WebauthnOfferDialogControllerImpl::~WebauthnOfferDialogControllerImpl() =
default;
void WebauthnOfferDialogControllerImpl::ShowOfferDialog(
AutofillClient::WebauthnOfferDialogCallback callback) {
DCHECK(!dialog_view_);
offer_dialog_callback_ = std::move(callback);
dialog_view_ = WebauthnOfferDialogView::CreateAndShow(this);
}
bool WebauthnOfferDialogControllerImpl::CloseDialog() {
if (!dialog_view_)
return false;
dialog_view_->Hide();
return true;
}
void WebauthnOfferDialogControllerImpl::OnOkButtonClicked() {
DCHECK(offer_dialog_callback_);
offer_dialog_callback_.Run(/*did_accept=*/true);
dialog_view_->RefreshContent();
}
void WebauthnOfferDialogControllerImpl::OnCancelButtonClicked() {
DCHECK(offer_dialog_callback_);
offer_dialog_callback_.Run(/*did_accept=*/false);
}
void WebauthnOfferDialogControllerImpl::OnDialogClosed() {
dialog_view_ = nullptr;
offer_dialog_callback_.Reset();
}
content::WebContents* WebauthnOfferDialogControllerImpl::GetWebContents() {
return web_contents();
}
WEB_CONTENTS_USER_DATA_KEY_IMPL(WebauthnOfferDialogControllerImpl)
} // namespace autofill
// Copyright 2019 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_PAYMENTS_WEBAUTHN_OFFER_DIALOG_CONTROLLER_IMPL_H_
#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_CONTROLLER_IMPL_H_
#include "base/macros.h"
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
namespace autofill {
class WebauthnOfferDialogView;
// Implementation of the per-tab controller to control the
// WebauthnOfferDialogView. Lazily initialized when used.
class WebauthnOfferDialogControllerImpl
: public WebauthnOfferDialogController,
public content::WebContentsObserver,
public content::WebContentsUserData<WebauthnOfferDialogControllerImpl> {
public:
~WebauthnOfferDialogControllerImpl() override;
void ShowOfferDialog(AutofillClient::WebauthnOfferDialogCallback callback);
bool CloseDialog();
// WebauthnOfferDialogController:
void OnOkButtonClicked() override;
void OnCancelButtonClicked() override;
void OnDialogClosed() override;
content::WebContents* GetWebContents() override;
protected:
explicit WebauthnOfferDialogControllerImpl(
content::WebContents* web_contents);
private:
friend class content::WebContentsUserData<WebauthnOfferDialogControllerImpl>;
// Callback invoked when any button in the dialog is clicked. Note this
// repeating callback can be run twice, since after the accept button is
// clicked, the dialog stays and the cancel button is still clickable.
AutofillClient::WebauthnOfferDialogCallback offer_dialog_callback_;
// Reference to the dialog, which is owned by the view hierarchy.
WebauthnOfferDialogView* dialog_view_ = nullptr;
WEB_CONTENTS_USER_DATA_KEY_DECL();
DISALLOW_COPY_AND_ASSIGN(WebauthnOfferDialogControllerImpl);
};
} // namespace autofill
#endif // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_CONTROLLER_IMPL_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller.h" #include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_model.h"
#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/app/vector_icons/vector_icons.h"
#include "components/strings/grit/components_strings.h" #include "components/strings/grit/components_strings.h"
...@@ -10,79 +10,73 @@ ...@@ -10,79 +10,73 @@
namespace autofill { namespace autofill {
WebauthnOfferDialogController::WebauthnOfferDialogController( WebauthnOfferDialogModel::WebauthnOfferDialogModel() {
AutofillClient::WebauthnOfferDialogCallback callback) state_ = kOffer;
: callback_(callback) {}
WebauthnOfferDialogController::~WebauthnOfferDialogController() {
callback_.Reset();
} }
bool WebauthnOfferDialogController::IsActivityIndicatorVisible() const { WebauthnOfferDialogModel::~WebauthnOfferDialogModel() = default;
return fetching_authentication_challenge_;
bool WebauthnOfferDialogModel::IsActivityIndicatorVisible() const {
return state_ == kPending;
} }
bool WebauthnOfferDialogController::IsBackButtonVisible() const { bool WebauthnOfferDialogModel::IsBackButtonVisible() const {
return false; return false;
} }
bool WebauthnOfferDialogController::IsCancelButtonVisible() const { bool WebauthnOfferDialogModel::IsCancelButtonVisible() const {
return true; return true;
} }
base::string16 WebauthnOfferDialogController::GetCancelButtonLabel() const { base::string16 WebauthnOfferDialogModel::GetCancelButtonLabel() const {
return l10n_util::GetStringUTF16( return l10n_util::GetStringUTF16(
IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_CANCEL_BUTTON_LABEL); IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_CANCEL_BUTTON_LABEL);
} }
bool WebauthnOfferDialogController::IsAcceptButtonVisible() const { bool WebauthnOfferDialogModel::IsAcceptButtonVisible() const {
return true; return true;
} }
bool WebauthnOfferDialogController::IsAcceptButtonEnabled() const { bool WebauthnOfferDialogModel::IsAcceptButtonEnabled() const {
return !fetching_authentication_challenge_; return state_ != kPending;
} }
base::string16 WebauthnOfferDialogController::GetAcceptButtonLabel() const { base::string16 WebauthnOfferDialogModel::GetAcceptButtonLabel() const {
return l10n_util::GetStringUTF16( return l10n_util::GetStringUTF16(
IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_OK_BUTTON_LABEL); IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_OK_BUTTON_LABEL);
} }
const gfx::VectorIcon& WebauthnOfferDialogController::GetStepIllustration( const gfx::VectorIcon& WebauthnOfferDialogModel::GetStepIllustration(
ImageColorScheme color_scheme) const { ImageColorScheme color_scheme) const {
return color_scheme == ImageColorScheme::kDark return color_scheme == ImageColorScheme::kDark
? kWebauthnOfferDialogHeaderDarkIcon ? kWebauthnOfferDialogHeaderDarkIcon
: kWebauthnOfferDialogHeaderIcon; : kWebauthnOfferDialogHeaderIcon;
} }
base::string16 WebauthnOfferDialogController::GetStepTitle() const { base::string16 WebauthnOfferDialogModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_TITLE); return l10n_util::GetStringUTF16(IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_TITLE);
} }
base::string16 WebauthnOfferDialogController::GetStepDescription() const { base::string16 WebauthnOfferDialogModel::GetStepDescription() const {
return l10n_util::GetStringUTF16( return l10n_util::GetStringUTF16(
IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_INSTRUCTION); IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_INSTRUCTION);
} }
base::Optional<base::string16> base::Optional<base::string16>
WebauthnOfferDialogController::GetAdditionalDescription() const { WebauthnOfferDialogModel::GetAdditionalDescription() const {
return base::nullopt; return base::nullopt;
} }
ui::MenuModel* WebauthnOfferDialogController::GetOtherTransportsMenuModel() { ui::MenuModel* WebauthnOfferDialogModel::GetOtherTransportsMenuModel() {
return nullptr; return nullptr;
} }
void WebauthnOfferDialogController::OnBack() {} void WebauthnOfferDialogModel::OnBack() {}
void WebauthnOfferDialogController::OnAccept() { void WebauthnOfferDialogModel::OnAccept() {
DCHECK(callback_); state_ = kPending;
callback_.Run(true);
} }
void WebauthnOfferDialogController::OnCancel() { void WebauthnOfferDialogModel::OnCancel() {}
DCHECK(callback_);
callback_.Run(false);
}
} // namespace autofill } // namespace autofill
// Copyright 2019 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_PAYMENTS_WEBAUTHN_OFFER_DIALOG_MODEL_H_
#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_MODEL_H_
#include "base/macros.h"
#include "chrome/browser/ui/webauthn/authenticator_request_sheet_model.h"
namespace autofill {
// The model for WebauthnOfferDialogView determining what content is shown.
// Owned by the AuthenticatorRequestSheetView.
class WebauthnOfferDialogModel : public AuthenticatorRequestSheetModel {
public:
enum DialogState {
kUnknown,
// The option of using platform authenticator is being offered.
kOffer,
// Offer was accepted, fetching authentication challenge.
kPending,
// TODO(crbug.com/991037): Add error state.
};
WebauthnOfferDialogModel();
~WebauthnOfferDialogModel() override;
// AuthenticatorRequestSheetModel:
bool IsActivityIndicatorVisible() const override;
bool IsBackButtonVisible() const override;
bool IsCancelButtonVisible() const override;
base::string16 GetCancelButtonLabel() const override;
bool IsAcceptButtonVisible() const override;
bool IsAcceptButtonEnabled() const override;
base::string16 GetAcceptButtonLabel() const override;
const gfx::VectorIcon& GetStepIllustration(
ImageColorScheme color_scheme) const override;
base::string16 GetStepTitle() const override;
base::string16 GetStepDescription() const override;
base::Optional<base::string16> GetAdditionalDescription() const override;
ui::MenuModel* GetOtherTransportsMenuModel() override;
void OnBack() override;
void OnAccept() override;
void OnCancel() override;
private:
DialogState state_ = kUnknown;
DISALLOW_COPY_AND_ASSIGN(WebauthnOfferDialogModel);
};
} // namespace autofill
#endif // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_MODEL_H_
...@@ -2,24 +2,26 @@ ...@@ -2,24 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_H_ #ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_VIEW_H_
#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_H_ #define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_VIEW_H_
#include "base/memory/weak_ptr.h" namespace autofill {
#include "components/autofill/core/browser/autofill_client.h"
namespace content { class WebauthnOfferDialogController;
class WebContents;
}
namespace autofill { // An interface which displays the dialog to offer the option of using device's
// platform authenticator instead of CVC to verify the card in the future.
class WebauthnOfferDialogView {
public:
static WebauthnOfferDialogView* CreateAndShow(
WebauthnOfferDialogController* controller);
virtual void Hide() = 0;
// Creates and shows the dialog to offer the option of using device's platform // Reinitializes the content in the dialog and resizes.
// authenticator instead of CVC to verify the card in the future. virtual void RefreshContent() = 0;
void ShowWebauthnOfferDialogView( };
content::WebContents* web_contents,
AutofillClient::WebauthnOfferDialogCallback callback);
} // namespace autofill } // namespace autofill
#endif // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_H_ #endif // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_VIEW_H_
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view.h" #include "chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view_impl.h"
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller.h"
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_model.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h" #include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
#include "chrome/browser/ui/views/webauthn/sheet_view_factory.h" #include "chrome/browser/ui/views/webauthn/sheet_view_factory.h"
...@@ -14,86 +16,107 @@ ...@@ -14,86 +16,107 @@
namespace autofill { namespace autofill {
WebauthnOfferDialogView::WebauthnOfferDialogView( WebauthnOfferDialogViewImpl::WebauthnOfferDialogViewImpl(
content::WebContents* web_contents, WebauthnOfferDialogController* controller)
AutofillClient::WebauthnOfferDialogCallback callback) { : controller_(controller) {
SetLayoutManager(std::make_unique<views::FillLayout>()); SetLayoutManager(std::make_unique<views::FillLayout>());
std::unique_ptr<WebauthnOfferDialogController> controller = std::unique_ptr<WebauthnOfferDialogModel> model =
std::make_unique<WebauthnOfferDialogController>(callback); std::make_unique<WebauthnOfferDialogModel>();
controller_ = controller.get(); model_ = model.get();
sheet_view_ = sheet_view_ =
AddChildView(CreateSheetViewForAutofillWebAuthn(std::move(controller))); AddChildView(CreateSheetViewForAutofillWebAuthn(std::move(model)));
sheet_view_->ReInitChildViews(); sheet_view_->ReInitChildViews();
} }
WebauthnOfferDialogView::~WebauthnOfferDialogView() = default; WebauthnOfferDialogViewImpl::~WebauthnOfferDialogViewImpl() = default;
// static // static
void ShowWebauthnOfferDialogView( WebauthnOfferDialogView* WebauthnOfferDialogView::CreateAndShow(
content::WebContents* web_contents, WebauthnOfferDialogController* controller) {
AutofillClient::WebauthnOfferDialogCallback callback) { WebauthnOfferDialogViewImpl* dialog =
WebauthnOfferDialogView* dialog = new WebauthnOfferDialogViewImpl(controller);
new WebauthnOfferDialogView(web_contents, callback); constrained_window::ShowWebModalDialogViews(dialog,
constrained_window::ShowWebModalDialogViews(dialog, web_contents); controller->GetWebContents());
return dialog;
} }
gfx::Size WebauthnOfferDialogView::CalculatePreferredSize() const { void WebauthnOfferDialogViewImpl::Hide() {
GetWidget()->Close();
}
// TODO(crbug.com/991037): Need to resize the dialog after reinitializing the
// dialog to error dialog since the string content in the error dialog is
// different.
void WebauthnOfferDialogViewImpl::RefreshContent() {
sheet_view_->ReInitChildViews();
sheet_view_->InvalidateLayout();
Layout();
DialogModelChanged();
}
gfx::Size WebauthnOfferDialogViewImpl::CalculatePreferredSize() const {
const int width = ChromeLayoutProvider::Get()->GetDistanceMetric( const int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH); DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH);
return gfx::Size(width, GetHeightForWidth(width)); return gfx::Size(width, GetHeightForWidth(width));
} }
bool WebauthnOfferDialogView::Accept() { bool WebauthnOfferDialogViewImpl::Accept() {
controller_->OnAccept(); model_->OnAccept();
// TODO(crbug.com/991037): Make the dialog stay and show the progression controller_->OnOkButtonClicked();
// indicator. return false;
return true;
} }
bool WebauthnOfferDialogView::Cancel() { bool WebauthnOfferDialogViewImpl::Cancel() {
controller_->OnCancel(); model_->OnCancel();
controller_->OnCancelButtonClicked();
return true; return true;
} }
bool WebauthnOfferDialogView::Close() { bool WebauthnOfferDialogViewImpl::Close() {
return true; return true;
} }
// TODO(crbug.com/991037): Fetching authentication challenge will send a request // TODO(crbug.com/991037): Fetching authentication challenge will send a request
// to Payments server, and it can fail sometimes. For the error case, the dialog // to Payments server, and it can fail sometimes. For the error case, the dialog
// should be updated and the OK button should not be shown. // should be updated and the OK button should not be shown.
int WebauthnOfferDialogView::GetDialogButtons() const { int WebauthnOfferDialogViewImpl::GetDialogButtons() const {
DCHECK(controller_->IsAcceptButtonVisible() && DCHECK(model_->IsAcceptButtonVisible() && model_->IsCancelButtonVisible());
controller_->IsCancelButtonVisible());
return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL; return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
} }
base::string16 WebauthnOfferDialogView::GetDialogButtonLabel( base::string16 WebauthnOfferDialogViewImpl::GetDialogButtonLabel(
ui::DialogButton button) const { ui::DialogButton button) const {
return button == ui::DIALOG_BUTTON_OK ? controller_->GetAcceptButtonLabel() return button == ui::DIALOG_BUTTON_OK ? model_->GetAcceptButtonLabel()
: controller_->GetCancelButtonLabel(); : model_->GetCancelButtonLabel();
} }
bool WebauthnOfferDialogView::IsDialogButtonEnabled( bool WebauthnOfferDialogViewImpl::IsDialogButtonEnabled(
ui::DialogButton button) const { ui::DialogButton button) const {
return button == ui::DIALOG_BUTTON_OK ? controller_->IsAcceptButtonEnabled() return button == ui::DIALOG_BUTTON_OK ? model_->IsAcceptButtonEnabled()
: true; : true;
} }
ui::ModalType WebauthnOfferDialogView::GetModalType() const { ui::ModalType WebauthnOfferDialogViewImpl::GetModalType() const {
return ui::MODAL_TYPE_CHILD; return ui::MODAL_TYPE_CHILD;
} }
base::string16 WebauthnOfferDialogView::GetWindowTitle() const { base::string16 WebauthnOfferDialogViewImpl::GetWindowTitle() const {
return controller_->GetStepTitle(); return model_->GetStepTitle();
} }
bool WebauthnOfferDialogView::ShouldShowWindowTitle() const { bool WebauthnOfferDialogViewImpl::ShouldShowWindowTitle() const {
return false; return false;
} }
bool WebauthnOfferDialogView::ShouldShowCloseButton() const { bool WebauthnOfferDialogViewImpl::ShouldShowCloseButton() const {
return false; return false;
} }
void WebauthnOfferDialogViewImpl::WindowClosing() {
if (controller_) {
controller_->OnDialogClosed();
controller_ = nullptr;
}
}
} // namespace autofill } // namespace autofill
...@@ -2,30 +2,33 @@ ...@@ -2,30 +2,33 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_VIEW_H_ #ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_VIEW_IMPL_H_
#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_VIEW_H_ #define CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_VIEW_IMPL_H_
#include "base/macros.h" #include "base/macros.h"
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller.h" #include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_view.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "ui/views/window/dialog_delegate.h" #include "ui/views/window/dialog_delegate.h"
class AuthenticatorRequestSheetView; class AuthenticatorRequestSheetView;
namespace content {
class WebContents;
}
namespace autofill { namespace autofill {
class WebauthnOfferDialogController;
class WebauthnOfferDialogModel;
// The view of the dialog that offers the option to use device's platform // The view of the dialog that offers the option to use device's platform
// authenticator. It is shown automatically after card unmasked details are // authenticator. It is shown automatically after card unmasked details are
// obtained and filled into the form. // obtained and filled into the form.
class WebauthnOfferDialogView : public views::DialogDelegateView { class WebauthnOfferDialogViewImpl : public WebauthnOfferDialogView,
public views::DialogDelegateView {
public: public:
WebauthnOfferDialogView(content::WebContents* web_contents, explicit WebauthnOfferDialogViewImpl(
AutofillClient::WebauthnOfferDialogCallback callback); WebauthnOfferDialogController* controller);
~WebauthnOfferDialogView() override; ~WebauthnOfferDialogViewImpl() override;
// WebauthnOfferDialogView:
void Hide() override;
void RefreshContent() override;
// views::DialogDelegateView: // views::DialogDelegateView:
gfx::Size CalculatePreferredSize() const override; gfx::Size CalculatePreferredSize() const override;
...@@ -39,21 +42,20 @@ class WebauthnOfferDialogView : public views::DialogDelegateView { ...@@ -39,21 +42,20 @@ class WebauthnOfferDialogView : public views::DialogDelegateView {
base::string16 GetWindowTitle() const override; base::string16 GetWindowTitle() const override;
bool ShouldShowWindowTitle() const override; bool ShouldShowWindowTitle() const override;
bool ShouldShowCloseButton() const override; bool ShouldShowCloseButton() const override;
void WindowClosing() override;
private: private:
friend void ShowWebauthnOfferDialogView(
content::WebContents* web_contents,
AutofillClient::WebauthnOfferDialogCallback callback);
// Reference to the controller. The controller is owned by the
// AuthenticatorRequestSheetView. Since this dialog view owns the sheet view,
// the controller is destroyed only when the dialog is.
WebauthnOfferDialogController* controller_ = nullptr; WebauthnOfferDialogController* controller_ = nullptr;
AuthenticatorRequestSheetView* sheet_view_ = nullptr; AuthenticatorRequestSheetView* sheet_view_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(WebauthnOfferDialogView); // Dialog model owned by |sheet_view_|. Since this dialog owns the
// |sheet_view_|, the model_ will always be valid.
WebauthnOfferDialogModel* model_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(WebauthnOfferDialogViewImpl);
}; };
} // namespace autofill } // namespace autofill
#endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_VIEW_H_ #endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_WEBAUTHN_OFFER_DIALOG_VIEW_IMPL_H_
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include "chrome/browser/ui/views/webauthn/sheet_view_factory.h" #include "chrome/browser/ui/views/webauthn/sheet_view_factory.h"
#include "base/logging.h" #include "base/logging.h"
#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller.h" #include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_model.h"
#include "chrome/browser/ui/views/webauthn/authenticator_ble_pin_entry_sheet_view.h" #include "chrome/browser/ui/views/webauthn/authenticator_ble_pin_entry_sheet_view.h"
#include "chrome/browser/ui/views/webauthn/authenticator_client_pin_entry_sheet_view.h" #include "chrome/browser/ui/views/webauthn/authenticator_client_pin_entry_sheet_view.h"
#include "chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.h" #include "chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.h"
...@@ -200,6 +200,6 @@ std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf( ...@@ -200,6 +200,6 @@ std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf(
std::unique_ptr<AuthenticatorRequestSheetView> std::unique_ptr<AuthenticatorRequestSheetView>
CreateSheetViewForAutofillWebAuthn( CreateSheetViewForAutofillWebAuthn(
std::unique_ptr<autofill::WebauthnOfferDialogController> controller) { std::unique_ptr<autofill::WebauthnOfferDialogModel> model) {
return std::make_unique<AuthenticatorRequestSheetView>(std::move(controller)); return std::make_unique<AuthenticatorRequestSheetView>(std::move(model));
} }
...@@ -11,7 +11,7 @@ class AuthenticatorRequestSheetView; ...@@ -11,7 +11,7 @@ class AuthenticatorRequestSheetView;
class AuthenticatorRequestDialogModel; class AuthenticatorRequestDialogModel;
namespace autofill { namespace autofill {
class WebauthnOfferDialogController; class WebauthnOfferDialogModel;
} }
// Creates the appropriate AuthenticatorRequestSheetView subclass instance, // Creates the appropriate AuthenticatorRequestSheetView subclass instance,
...@@ -24,6 +24,6 @@ std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf( ...@@ -24,6 +24,6 @@ std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf(
// WebauthnOfferDialogView. // WebauthnOfferDialogView.
std::unique_ptr<AuthenticatorRequestSheetView> std::unique_ptr<AuthenticatorRequestSheetView>
CreateSheetViewForAutofillWebAuthn( CreateSheetViewForAutofillWebAuthn(
std::unique_ptr<autofill::WebauthnOfferDialogController> controller); std::unique_ptr<autofill::WebauthnOfferDialogModel> model);
#endif // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_SHEET_VIEW_FACTORY_H_ #endif // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_SHEET_VIEW_FACTORY_H_
...@@ -23,4 +23,8 @@ LogManager* AutofillClient::GetLogManager() const { ...@@ -23,4 +23,8 @@ LogManager* AutofillClient::GetLogManager() const {
return nullptr; return nullptr;
} }
bool AutofillClient::CloseWebauthnOfferDialog() {
return false;
}
} // namespace autofill } // namespace autofill
...@@ -311,6 +311,10 @@ class AutofillClient : public RiskDataLoader { ...@@ -311,6 +311,10 @@ class AutofillClient : public RiskDataLoader {
virtual void ShowWebauthnOfferDialog( virtual void ShowWebauthnOfferDialog(
WebauthnOfferDialogCallback callback) = 0; WebauthnOfferDialogCallback callback) = 0;
// Will close the WebAuthn offer dialog. Returns true if dialog was visible
// and has been closed. Implemented only on desktop.
virtual bool CloseWebauthnOfferDialog();
// Runs |callback| if the |profile| should be imported as personal data. // Runs |callback| if the |profile| should be imported as personal data.
virtual void ConfirmSaveAutofillProfile(const AutofillProfile& profile, virtual void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
base::OnceClosure callback) = 0; base::OnceClosure callback) = 0;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/containers/flat_set.h" #include "base/containers/flat_set.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/payments/payments_client.h" #include "components/autofill/core/browser/payments/payments_client.h"
...@@ -171,6 +172,16 @@ void CreditCardFIDOAuthenticator::MakeCredential( ...@@ -171,6 +172,16 @@ void CreditCardFIDOAuthenticator::MakeCredential(
PublicKeyCredentialCreationOptionsPtr creation_options) { PublicKeyCredentialCreationOptionsPtr creation_options) {
autofill_driver_->ConnectToAuthenticator( autofill_driver_->ConnectToAuthenticator(
authenticator_.BindNewPipeAndPassReceiver()); authenticator_.BindNewPipeAndPassReceiver());
#if !defined(OS_ANDROID)
// On desktop, close the WebAuthn offer dialog and get ready to show the OS
// level authentication dialog. If dialog is already closed, then the offer
// was declined during the fetching challenge process, and thus returned
// early.
if (!autofill_client_->CloseWebauthnOfferDialog()) {
current_flow_ = NONE_FLOW;
return;
}
#endif
authenticator_->MakeCredential( authenticator_->MakeCredential(
std::move(creation_options), std::move(creation_options),
base::BindOnce(&CreditCardFIDOAuthenticator::OnDidMakeCredential, base::BindOnce(&CreditCardFIDOAuthenticator::OnDidMakeCredential,
...@@ -253,8 +264,12 @@ void CreditCardFIDOAuthenticator::OnDidGetOptChangeResult( ...@@ -253,8 +264,12 @@ void CreditCardFIDOAuthenticator::OnDidGetOptChangeResult(
void CreditCardFIDOAuthenticator::OnWebauthnOfferDialogUserResponse( void CreditCardFIDOAuthenticator::OnWebauthnOfferDialogUserResponse(
bool did_accept) { bool did_accept) {
// TODO(crbug.com/): Register and start fetching authentication challenge if if (did_accept) {
// |did_accept|, otherwise cancel any ongoing request. Register();
} else {
payments_client_->CancelRequest();
current_flow_ = NONE_FLOW;
}
} }
void CreditCardFIDOAuthenticator::OnFullCardRequestSucceeded( void CreditCardFIDOAuthenticator::OnFullCardRequestSucceeded(
......
...@@ -110,6 +110,10 @@ void TestAutofillClient::ShowLocalCardMigrationResults( ...@@ -110,6 +110,10 @@ void TestAutofillClient::ShowLocalCardMigrationResults(
void TestAutofillClient::ShowWebauthnOfferDialog( void TestAutofillClient::ShowWebauthnOfferDialog(
WebauthnOfferDialogCallback callback) {} WebauthnOfferDialogCallback callback) {}
bool TestAutofillClient::CloseWebauthnOfferDialog() {
return true;
}
void TestAutofillClient::ConfirmSaveAutofillProfile( void TestAutofillClient::ConfirmSaveAutofillProfile(
const AutofillProfile& profile, const AutofillProfile& profile,
base::OnceClosure callback) { base::OnceClosure callback) {
......
...@@ -65,6 +65,7 @@ class TestAutofillClient : public AutofillClient { ...@@ -65,6 +65,7 @@ class TestAutofillClient : public AutofillClient {
const std::vector<MigratableCreditCard>& migratable_credit_cards, const std::vector<MigratableCreditCard>& migratable_credit_cards,
MigrationDeleteCardCallback delete_local_card_callback) override; MigrationDeleteCardCallback delete_local_card_callback) override;
void ShowWebauthnOfferDialog(WebauthnOfferDialogCallback callback) override; void ShowWebauthnOfferDialog(WebauthnOfferDialogCallback callback) override;
bool CloseWebauthnOfferDialog() override;
void ConfirmSaveAutofillProfile(const AutofillProfile& profile, void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
base::OnceClosure callback) override; base::OnceClosure callback) override;
void ConfirmSaveCreditCardLocally( void ConfirmSaveCreditCardLocally(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment