Commit 696cec7b authored by Balazs Engedy's avatar Balazs Engedy Committed by Commit Bot

Introduce sheet models, and sheet view factory.

This CL introduces AuthenticatorSheetModelBase, which will serve as a
base class for sheets, and implement the shared behavior used on most
sheets, as well as maintaining a weak pointer to the dialog model.

Also introduce CreateSheetViewForCurrentStepOf, a factory method that
constructs the appropriate SheetView subclass, along with the
appropriate SheetModel subclass.

Bug: 849323
Change-Id: Iaedb3da6aa3f3fdc932b57cc5795143acab7d4c5
Reviewed-on: https://chromium-review.googlesource.com/1104422Reviewed-by: default avatarKim Paulhamus <kpaulhamus@chromium.org>
Reviewed-by: default avatarJun Choi <hongjunchoi@chromium.org>
Commit-Queue: Balazs Engedy <engedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568114}
parent 607c9b73
......@@ -2996,7 +2996,11 @@ split_static_library("ui") {
"views/webauthn/authenticator_request_dialog_view.h",
"views/webauthn/authenticator_request_sheet_view.cc",
"views/webauthn/authenticator_request_sheet_view.h",
"views/webauthn/sheet_view_factory.cc",
"views/webauthn/sheet_view_factory.h",
"webauthn/authenticator_request_sheet_model.h",
"webauthn/sheet_models.cc",
"webauthn/sheet_models.h",
]
deps += [
"//chrome/browser/ui/views",
......
......@@ -12,7 +12,9 @@
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/test/test_browser_dialog.h"
#include "chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.h"
#include "chrome/browser/ui/views/webauthn/authenticator_request_dialog_view_test_api.h"
#include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
#include "chrome/browser/ui/webauthn/authenticator_request_dialog.h"
#include "chrome/browser/ui/webauthn/authenticator_request_sheet_model.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
......
......@@ -8,6 +8,8 @@
#include "base/strings/string16.h"
#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
#include "chrome/browser/ui/views/harmony/chrome_typography.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/webauthn/authenticator_request_sheet_model.h"
#include "chrome/grit/generated_resources.h"
#include "components/constrained_window/constrained_window_views.h"
......@@ -17,46 +19,6 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/layout/fill_layout.h"
namespace {
// Defines a static sheet with no additional step-specific content and no button
// enabled other than `Cancel`.
class SimpleStaticSheetModel : public AuthenticatorRequestSheetModel {
public:
SimpleStaticSheetModel() = default;
private:
// AuthenticatorRequestSheetModel:
bool IsBackButtonVisible() const override { return false; }
bool IsCancelButtonVisible() const override { return true; }
base::string16 GetCancelButtonLabel() const override {
return l10n_util::GetStringUTF16(IDS_CANCEL);
}
bool IsAcceptButtonVisible() const override { return false; }
bool IsAcceptButtonEnabled() const override { return false; }
base::string16 GetAcceptButtonLabel() const override {
return base::string16();
}
base::string16 GetStepTitle() const override {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_DIALOG_TITLE);
}
base::string16 GetStepDescription() const override {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_DIALOG_DESCRIPTION);
}
void OnBack() override { NOTREACHED(); }
void OnAccept() override { NOTREACHED(); }
void OnCancel() override {}
DISALLOW_COPY_AND_ASSIGN(SimpleStaticSheetModel);
};
} // namespace
// static
void ShowAuthenticatorRequestDialog(
content::WebContents* web_contents,
......@@ -82,11 +44,12 @@ void ShowAuthenticatorRequestDialog(
constrained_window::ShowWebModalDialogViews(dialog.release(), web_contents);
}
// TODO(engedy): Create the sheet based on the model here.
AuthenticatorRequestDialogView::AuthenticatorRequestDialogView(
content::WebContents* web_contents,
std::unique_ptr<AuthenticatorRequestDialogModel> model)
: content::WebContentsObserver(web_contents), model_(std::move(model)) {
: content::WebContentsObserver(web_contents),
model_(std::move(model)),
sheet_(nullptr) {
model_->AddObserver(this);
// Currently, all sheets have a label on top and controls at the bottom.
......@@ -95,12 +58,7 @@ AuthenticatorRequestDialogView::AuthenticatorRequestDialogView(
views::LayoutProvider::Get()->GetDialogInsetsForContentType(
views::TEXT, views::CONTROL)));
SetLayoutManager(std::make_unique<views::FillLayout>());
auto sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
std::make_unique<SimpleStaticSheetModel>());
sheet_view->InitChildViews();
sheet_ = sheet_view.get();
AddChildView(sheet_view.release());
OnStepTransition();
}
AuthenticatorRequestDialogView::~AuthenticatorRequestDialogView() {
......@@ -199,6 +157,8 @@ void AuthenticatorRequestDialogView::OnModelDestroyed() {
}
void AuthenticatorRequestDialogView::OnStepTransition() {
ReplaceCurrentSheetWith(CreateSheetViewForCurrentStepOf(model_.get()));
if (model_->current_step() ==
AuthenticatorRequestDialogModel::Step::kCompleted) {
if (!GetWidget())
......@@ -209,6 +169,8 @@ void AuthenticatorRequestDialogView::OnStepTransition() {
void AuthenticatorRequestDialogView::ReplaceCurrentSheetWith(
std::unique_ptr<AuthenticatorRequestSheetView> new_sheet) {
DCHECK(new_sheet);
delete sheet_;
DCHECK(!has_children());
......
......@@ -7,8 +7,8 @@
#include <memory>
#include "base/logging.h"
#include "base/macros.h"
#include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/views/window/dialog_delegate.h"
......@@ -21,6 +21,8 @@ namespace test {
class AuthenticatorRequestDialogViewTestApi;
}
class AuthenticatorRequestSheetView;
// A tab-modal dialog shown while a Web Authentication API request is active.
//
// This UI first allows the user the select the transport protocol they wish to
......@@ -39,12 +41,16 @@ class AuthenticatorRequestDialogView
protected:
// Replaces the |sheet_| currently being shown in the dialog with |new_sheet|,
// destroying the old sheet. Also triggers updating the dialog buttons, window
// title (using the data provided by the new sheet), and size/position.
// destroying the old sheet. Also triggers updating the state of the buttons
// on the dialog, the accessibility window title (using the data provided by
// the new sheet), and the dialog size and position.
void ReplaceCurrentSheetWith(
std::unique_ptr<AuthenticatorRequestSheetView> new_sheet);
AuthenticatorRequestSheetView* sheet() const { return sheet_; }
AuthenticatorRequestSheetView* sheet() const {
DCHECK(sheet_);
return sheet_;
}
// views::DialogDelegateView:
gfx::Size CalculatePreferredSize() const override;
......
......@@ -7,6 +7,7 @@
#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
#include "chrome/browser/ui/views/harmony/chrome_typography.h"
#include "chrome/browser/ui/webauthn/authenticator_request_sheet_model.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
#include "components/strings/grit/components_strings.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/base/l10n/l10n_util.h"
......
......@@ -49,12 +49,12 @@ class AuthenticatorRequestSheetView : public views::View,
std::unique_ptr<AuthenticatorRequestSheetModel> model);
~AuthenticatorRequestSheetView() override;
AuthenticatorRequestSheetModel* model() { return model_.get(); }
// Creates the standard child views on this sheet, potentially including
// step-specific content if any.
void InitChildViews();
AuthenticatorRequestSheetModel* model() { return model_.get(); }
protected:
// Returns the step-specific view the derived sheet wishes to provide, if any.
virtual std::unique_ptr<views::View> BuildStepSpecificContent();
......
// Copyright 2018 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/views/webauthn/sheet_view_factory.h"
#include "base/logging.h"
#include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
#include "chrome/browser/ui/webauthn/sheet_models.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
namespace {
// A placeholder sheet to show in place of unimplemented sheets.
class PlaceholderSheetModel : public AuthenticatorSheetModelBase {
public:
using AuthenticatorSheetModelBase::AuthenticatorSheetModelBase;
private:
// AuthenticatorSheetModelBase:
base::string16 GetStepTitle() const override { return base::string16(); }
base::string16 GetStepDescription() const override {
return base::string16();
}
};
} // namespace
std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf(
AuthenticatorRequestDialogModel* dialog_model) {
using Step = AuthenticatorRequestDialogModel::Step;
std::unique_ptr<AuthenticatorRequestSheetView> sheet_view;
switch (dialog_model->current_step()) {
case Step::kInitial:
sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
std::make_unique<AuthenticatorInitialSheetModel>(dialog_model));
break;
case Step::kTransportSelection:
case Step::kErrorTimedOut:
case Step::kCompleted:
case Step::kUsbInsert:
case Step::kUsbActivate:
case Step::kUsbVerifying:
case Step::kBlePowerOnAutomatic:
case Step::kBlePowerOnManual:
case Step::kBlePairingBegin:
case Step::kBleEnterPairingMode:
case Step::kBleDeviceSelection:
case Step::kBlePinEntry:
case Step::kBleActivate:
case Step::kBleVerifying:
sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
std::make_unique<PlaceholderSheetModel>(dialog_model));
break;
}
CHECK(sheet_view);
sheet_view->InitChildViews();
return sheet_view;
}
// Copyright 2018 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_VIEWS_WEBAUTHN_SHEET_VIEW_FACTORY_H_
#define CHROME_BROWSER_UI_VIEWS_WEBAUTHN_SHEET_VIEW_FACTORY_H_
#include <memory>
class AuthenticatorRequestSheetView;
class AuthenticatorRequestDialogModel;
// Creates the appropriate AuthenticatorRequestSheetView subclass instance,
// along with the appropriate AuthenticatorRequestSheetModel, for the current
// step of the |dialog_model|.
std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf(
AuthenticatorRequestDialogModel* dialog_model);
#endif // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_SHEET_VIEW_FACTORY_H_
......@@ -17,8 +17,15 @@ class AuthenticatorDialogTest : public DialogBrowserTest {
AuthenticatorDialogTest() = default;
// DialogBrowserTest:
void ShowUi(const std::string& unused_name) override {
void ShowUi(const std::string& name) override {
auto model = std::make_unique<AuthenticatorRequestDialogModel>();
// The dialog should immediately close as soon as it is displayed.
if (name == "completed") {
model->set_current_step(
AuthenticatorRequestDialogModel::Step::kCompleted);
}
ShowAuthenticatorRequestDialog(
browser()->tab_strip_model()->GetActiveWebContents(), std::move(model));
}
......@@ -33,3 +40,7 @@ class AuthenticatorDialogTest : public DialogBrowserTest {
IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_default) {
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_completed) {
ShowAndVerifyUi();
}
// Copyright 2018 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/webauthn/sheet_models.h"
#include "base/logging.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
// AuthenticatorSheetModelBase ------------------------------------------------
AuthenticatorSheetModelBase::AuthenticatorSheetModelBase(
AuthenticatorRequestDialogModel* dialog_model)
: dialog_model_(dialog_model) {
DCHECK(dialog_model);
dialog_model_->AddObserver(this);
}
AuthenticatorSheetModelBase::~AuthenticatorSheetModelBase() {
if (dialog_model_) {
dialog_model_->RemoveObserver(this);
dialog_model_ = nullptr;
}
}
bool AuthenticatorSheetModelBase::IsBackButtonVisible() const {
return true;
}
bool AuthenticatorSheetModelBase::IsCancelButtonVisible() const {
return true;
}
base::string16 AuthenticatorSheetModelBase::GetCancelButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_CANCEL);
}
bool AuthenticatorSheetModelBase::IsAcceptButtonVisible() const {
return false;
}
bool AuthenticatorSheetModelBase::IsAcceptButtonEnabled() const {
NOTREACHED();
return false;
}
base::string16 AuthenticatorSheetModelBase::GetAcceptButtonLabel() const {
NOTREACHED();
return base::string16();
}
void AuthenticatorSheetModelBase::OnBack() {
if (dialog_model())
dialog_model()->Back();
}
void AuthenticatorSheetModelBase::OnAccept() {
NOTREACHED();
}
void AuthenticatorSheetModelBase::OnCancel() {
if (dialog_model())
dialog_model()->Cancel();
}
void AuthenticatorSheetModelBase::OnModelDestroyed() {
dialog_model_ = nullptr;
}
// AuthenticatorInitialSheetModel ---------------------------------------------
base::string16 AuthenticatorInitialSheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_DIALOG_TITLE);
}
base::string16 AuthenticatorInitialSheetModel::GetStepDescription() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_DIALOG_DESCRIPTION);
}
// Copyright 2018 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_WEBAUTHN_SHEET_MODELS_H_
#define CHROME_BROWSER_UI_WEBAUTHN_SHEET_MODELS_H_
#include "base/macros.h"
#include "chrome/browser/ui/webauthn/authenticator_request_sheet_model.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
// Base class for sheets, implementing the shared behavior used on most sheets,
// as well as maintaining a weak pointer to the dialog model.
class AuthenticatorSheetModelBase
: public AuthenticatorRequestSheetModel,
public AuthenticatorRequestDialogModel::Observer {
public:
explicit AuthenticatorSheetModelBase(
AuthenticatorRequestDialogModel* dialog_model);
~AuthenticatorSheetModelBase() override;
protected:
AuthenticatorRequestDialogModel* dialog_model() const {
return dialog_model_;
}
// AuthenticatorRequestSheetModel:
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;
void OnBack() override;
void OnAccept() override;
void OnCancel() override;
// AuthenticatorRequestDialogModel::Observer:
void OnModelDestroyed() override;
private:
AuthenticatorRequestDialogModel* dialog_model_;
DISALLOW_COPY_AND_ASSIGN(AuthenticatorSheetModelBase);
};
// The initial sheet shown when the UX flow starts.
class AuthenticatorInitialSheetModel : public AuthenticatorSheetModelBase {
public:
using AuthenticatorSheetModelBase::AuthenticatorSheetModelBase;
private:
// AuthenticatorSheetModelBase:
base::string16 GetStepTitle() const override;
base::string16 GetStepDescription() const override;
};
#endif // CHROME_BROWSER_UI_WEBAUTHN_SHEET_MODELS_H_
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