Commit bdb56ef8 authored by Balazs Engedy's avatar Balazs Engedy Committed by Commit Bot

Initial version of AuthenticationDialog.

Implement an initial MVP of the modal dialog that is shown during
WebAuthn requests. See the screenshot here: crbug.com/849323#c2.

The dialog is not yet interactive, even the `x` button does not yet
cancel the WebAuthn request (it does hide the dialog).

Bug: 849323
Change-Id: I3e1d9148f0727e33fb54e9bd1b747b84caa3c827
Reviewed-on: https://chromium-review.googlesource.com/964448
Commit-Queue: Balazs Engedy <engedy@chromium.org>
Reviewed-by: default avatarTrent Apted <tapted@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565607}
parent b9c7f374
...@@ -10552,6 +10552,14 @@ Please help our engineers fix this problem. Tell us what happened right before y ...@@ -10552,6 +10552,14 @@ Please help our engineers fix this problem. Tell us what happened right before y
Got it Got it
</message> </message>
</if> </if>
<!-- Web-modal dialog shown during Web Authenticaton API requests. -->
<message name="IDS_WEBAUTHN_DIALOG_TITLE" desc="Title of the dialog shown when a web site wants to register/verify a user's security key through the Web Authentication API.">
Verify your Security Key
</message>
<message name="IDS_WEBAUTHN_DIALOG_DESCRIPTION" desc="Contents of the dialog shown when a web site wants to register/verify a user's security key through the Web Authentication API.">
The site wants to verify your Security Key for added security for your account.
</message>
</messages> </messages>
</release> </release>
</grit> </grit>
...@@ -1545,6 +1545,8 @@ jumbo_split_static_library("browser") { ...@@ -1545,6 +1545,8 @@ jumbo_split_static_library("browser") {
"vr/vr_tab_helper.h", "vr/vr_tab_helper.h",
"web_data_service_factory.cc", "web_data_service_factory.cc",
"web_data_service_factory.h", "web_data_service_factory.h",
"webauthn/authenticator_request_dialog_model.cc",
"webauthn/authenticator_request_dialog_model.h",
"webauthn/authenticator_request_scheduler.cc", "webauthn/authenticator_request_scheduler.cc",
"webauthn/authenticator_request_scheduler.h", "webauthn/authenticator_request_scheduler.h",
"webauthn/chrome_authenticator_request_delegate.cc", "webauthn/chrome_authenticator_request_delegate.cc",
......
...@@ -739,6 +739,7 @@ split_static_library("ui") { ...@@ -739,6 +739,7 @@ split_static_library("ui") {
"uninstall_browser_prompt.h", "uninstall_browser_prompt.h",
"view_ids.h", "view_ids.h",
"web_contents_sizer.h", "web_contents_sizer.h",
"webauthn/authenticator_request_dialog.h",
"webui/about_ui.cc", "webui/about_ui.cc",
"webui/about_ui.h", "webui/about_ui.h",
"webui/chrome_web_ui_controller_factory.cc", "webui/chrome_web_ui_controller_factory.cc",
...@@ -2995,6 +2996,8 @@ split_static_library("ui") { ...@@ -2995,6 +2996,8 @@ split_static_library("ui") {
"views/translate/translate_bubble_view.h", "views/translate/translate_bubble_view.h",
"views/update_recommended_message_box.cc", "views/update_recommended_message_box.cc",
"views/update_recommended_message_box.h", "views/update_recommended_message_box.h",
"views/webauthn/authenticator_request_dialog_view.cc",
"views/webauthn/authenticator_request_dialog_view.h",
] ]
deps += [ deps += [
"//chrome/browser/ui/views", "//chrome/browser/ui/views",
......
engedy@chromium.org
kpaulhamus@chromium.org
# TEAM: security-dev@chromium.org
# COMPONENT: Blink>WebAuthentication
// 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/authenticator_request_dialog_view.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
#include "chrome/browser/ui/views/harmony/chrome_typography.h"
#include "chrome/grit/generated_resources.h"
#include "components/constrained_window/constrained_window_views.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/fill_layout.h"
// static
void ShowAuthenticatorRequestDialog(
content::WebContents* web_contents,
std::unique_ptr<AuthenticatorRequestDialogModel> model) {
// The authenticator request dialog will only be shown for common user-facing
// WebContents, which have a |manager|. Most other sources without managers,
// like service workers and extension background pages, do not allow WebAuthn
// requests to be issued in the first place.
// TODO(https://crbug.com/849323): There are some niche WebContents where the
// WebAuthn API is available, but there is no |manager| available. Currently,
// we will not be able to show a dialog, so the |model| will be immediately
// destroyed. The request may be able to still run to completion if it does
// not require any user input, otherise it will be blocked and time out. We
// should audit this.
auto* manager = web_modal::WebContentsModalDialogManager::FromWebContents(
constrained_window::GetTopLevelWebContents(web_contents));
if (!manager)
return;
auto dialog =
std::make_unique<AuthenticatorRequestDialogView>(std::move(model));
constrained_window::ShowWebModalDialogViews(dialog.release(), web_contents);
}
AuthenticatorRequestDialogView::AuthenticatorRequestDialogView(
std::unique_ptr<AuthenticatorRequestDialogModel> model)
: model_(std::move(model)) {
model_->AddObserver(this);
CreateContents();
}
AuthenticatorRequestDialogView::~AuthenticatorRequestDialogView() {
model_->RemoveObserver(this);
}
void AuthenticatorRequestDialogView::CreateContents() {
SetLayoutManager(std::make_unique<views::FillLayout>());
SetBorder(views::CreateEmptyBorder(
views::LayoutProvider::Get()->GetDialogInsetsForContentType(
views::TEXT, views::CONTROL)));
auto description_label = std::make_unique<views::Label>(
l10n_util::GetStringUTF16(IDS_WEBAUTHN_DIALOG_DESCRIPTION),
CONTEXT_BODY_TEXT_SMALL, STYLE_SECONDARY);
description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
description_label->SetMultiLine(true);
description_label->SetMaximumWidth(
ChromeLayoutProvider::Get()->GetDistanceMetric(
DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH) -
margins().width());
AddChildView(description_label.release());
}
int AuthenticatorRequestDialogView::GetDialogButtons() const {
return ui::DIALOG_BUTTON_NONE;
}
ui::ModalType AuthenticatorRequestDialogView::GetModalType() const {
return ui::MODAL_TYPE_CHILD;
}
base::string16 AuthenticatorRequestDialogView::GetWindowTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_DIALOG_TITLE);
}
void AuthenticatorRequestDialogView::OnModelDestroyed() {
NOTREACHED();
}
void AuthenticatorRequestDialogView::OnRequestComplete() {
if (!GetWidget())
return;
GetWidget()->Close();
}
// 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_AUTHENTICATOR_REQUEST_DIALOG_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_VIEW_H_
#include <memory>
#include "base/macros.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
#include "ui/views/window/dialog_delegate.h"
// 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
// use to connect their security key (either USB, BLE, NFC, or internal), and
// then guides them through the flow of setting up their security key using the
// selecting transport protocol, and finally shows success/failure indications.
class AuthenticatorRequestDialogView
: public views::DialogDelegateView,
public AuthenticatorRequestDialogModel::Observer {
public:
AuthenticatorRequestDialogView(
std::unique_ptr<AuthenticatorRequestDialogModel> model);
~AuthenticatorRequestDialogView() override;
protected:
void CreateContents();
// views::DialogDelegateView:
int GetDialogButtons() const override;
ui::ModalType GetModalType() const override;
base::string16 GetWindowTitle() const override;
// AuthenticatorRequestDialogModel::Observer:
void OnModelDestroyed() override;
void OnRequestComplete() override;
private:
std::unique_ptr<AuthenticatorRequestDialogModel> model_;
DISALLOW_COPY_AND_ASSIGN(AuthenticatorRequestDialogView);
};
#endif // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_VIEW_H_
engedy@chromium.org
kpaulhamus@chromium.org
# TEAM: security-dev@chromium.org
# COMPONENT: Blink>WebAuthentication
// 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 <memory>
#include <utility>
#include "chrome/browser/ui/browser.h"
#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/webauthn/authenticator_request_dialog.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
class AuthenticatorDialogTest : public DialogBrowserTest {
public:
AuthenticatorDialogTest() = default;
// DialogBrowserTest:
void ShowUi(const std::string& unused_name) override {
auto model = std::make_unique<AuthenticatorRequestDialogModel>();
ShowAuthenticatorRequestDialog(
browser()->tab_strip_model()->GetActiveWebContents(), std::move(model));
}
private:
DISALLOW_COPY_AND_ASSIGN(AuthenticatorDialogTest);
};
// Run with:
// --gtest_filter=BrowserUiTest.Invoke --test-launcher-interactive \
// --ui=AuthenticatorDialogTest.InvokeUi_default
IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_default) {
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.
#ifndef CHROME_BROWSER_UI_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_H_
#define CHROME_BROWSER_UI_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_H_
#include <memory>
class AuthenticatorRequestDialogModel;
namespace content {
class WebContents;
}
// Creates and shows the dialog for a given WebContents.
void ShowAuthenticatorRequestDialog(
content::WebContents* web_contents,
std::unique_ptr<AuthenticatorRequestDialogModel> model);
#endif // CHROME_BROWSER_UI_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_H_
// 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/webauthn/authenticator_request_dialog_model.h"
AuthenticatorRequestDialogModel::AuthenticatorRequestDialogModel() = default;
AuthenticatorRequestDialogModel::~AuthenticatorRequestDialogModel() {
for (auto& observer : observers_)
observer.OnModelDestroyed();
}
void AuthenticatorRequestDialogModel::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void AuthenticatorRequestDialogModel::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void AuthenticatorRequestDialogModel::OnRequestComplete() {
for (auto& observer : observers_)
observer.OnRequestComplete();
}
// 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_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_MODEL_H_
#define CHROME_BROWSER_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_MODEL_H_
#include "base/observer_list.h"
// Encapsulates the model behind the Web Authentication request dialog.
//
// Ultimately, this will become an observer of the AuthenticatorRequest, and
// contain the logic to figure out which steps the user needs to take, in which
// order, to complete the authentication flow.
class AuthenticatorRequestDialogModel {
public:
// Implemented by the dialog to observe this model and show the UI panels
// appropriate for the current step.
class Observer {
public:
// Called just before the model is destructed.
virtual void OnModelDestroyed() = 0;
// Called when the authentication request completes (successfully or not).
virtual void OnRequestComplete() {}
};
AuthenticatorRequestDialogModel();
~AuthenticatorRequestDialogModel();
// The |observer| must either outlive the object, or unregister itself on its
// destruction.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// To be called when the Web Authentication request is complete.
void OnRequestComplete();
private:
base::ObserverList<Observer> observers_;
DISALLOW_COPY_AND_ASSIGN(AuthenticatorRequestDialogModel);
};
#endif // CHROME_BROWSER_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_MODEL_H_
...@@ -17,12 +17,17 @@ ...@@ -17,12 +17,17 @@
#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webauthn/authenticator_request_dialog.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
namespace { namespace {
...@@ -49,8 +54,30 @@ bool IsWebauthnRPIDListedInEnterprisePolicy( ...@@ -49,8 +54,30 @@ bool IsWebauthnRPIDListedInEnterprisePolicy(
ChromeAuthenticatorRequestDelegate::ChromeAuthenticatorRequestDelegate( ChromeAuthenticatorRequestDelegate::ChromeAuthenticatorRequestDelegate(
content::RenderFrameHost* render_frame_host) content::RenderFrameHost* render_frame_host)
: render_frame_host_(render_frame_host), weak_ptr_factory_(this) {} : render_frame_host_(render_frame_host), weak_ptr_factory_(this) {
ChromeAuthenticatorRequestDelegate::~ChromeAuthenticatorRequestDelegate() {} #if !defined(OS_ANDROID)
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kWebAuthenticationUI)) {
return;
}
auto dialog_model = std::make_unique<AuthenticatorRequestDialogModel>();
weak_dialog_model_ = dialog_model.get();
weak_dialog_model_->AddObserver(this);
ShowAuthenticatorRequestDialog(
content::WebContents::FromRenderFrameHost(render_frame_host),
std::move(dialog_model));
#endif
}
ChromeAuthenticatorRequestDelegate::~ChromeAuthenticatorRequestDelegate() {
// Currently, completion of the request is indicated by //content destroying
// this delegate.
if (weak_dialog_model_) {
// The dialog model may be destroyed after the OnRequestComplete call.
weak_dialog_model_->RemoveObserver(this);
weak_dialog_model_->OnRequestComplete();
}
}
base::WeakPtr<ChromeAuthenticatorRequestDelegate> base::WeakPtr<ChromeAuthenticatorRequestDelegate>
ChromeAuthenticatorRequestDelegate::AsWeakPtr() { ChromeAuthenticatorRequestDelegate::AsWeakPtr() {
...@@ -130,3 +157,8 @@ bool ChromeAuthenticatorRequestDelegate::IsFocused() { ...@@ -130,3 +157,8 @@ bool ChromeAuthenticatorRequestDelegate::IsFocused() {
return false; return false;
#endif #endif
} }
void ChromeAuthenticatorRequestDelegate::OnModelDestroyed() {
DCHECK(weak_dialog_model_);
weak_dialog_model_ = nullptr;
}
...@@ -6,14 +6,18 @@ ...@@ -6,14 +6,18 @@
#define CHROME_BROWSER_WEBAUTHN_CHROME_AUTHENTICATOR_REQUEST_DELEGATE_H_ #define CHROME_BROWSER_WEBAUTHN_CHROME_AUTHENTICATOR_REQUEST_DELEGATE_H_
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
#include "content/public/browser/authenticator_request_client_delegate.h" #include "content/public/browser/authenticator_request_client_delegate.h"
namespace content { namespace content {
class RenderFrameHost; class RenderFrameHost;
} }
class AuthenticatorRequestDialogModel;
class ChromeAuthenticatorRequestDelegate class ChromeAuthenticatorRequestDelegate
: public content::AuthenticatorRequestClientDelegate { : public content::AuthenticatorRequestClientDelegate,
public AuthenticatorRequestDialogModel::Observer {
public: public:
// The |render_frame_host| must outlive this instance. // The |render_frame_host| must outlive this instance.
explicit ChromeAuthenticatorRequestDelegate( explicit ChromeAuthenticatorRequestDelegate(
...@@ -35,7 +39,12 @@ class ChromeAuthenticatorRequestDelegate ...@@ -35,7 +39,12 @@ class ChromeAuthenticatorRequestDelegate
base::OnceCallback<void(bool)> callback) override; base::OnceCallback<void(bool)> callback) override;
bool IsFocused() override; bool IsFocused() override;
// AuthenticatorRequestDialogModel::Observer:
void OnModelDestroyed() override;
content::RenderFrameHost* const render_frame_host_; content::RenderFrameHost* const render_frame_host_;
AuthenticatorRequestDialogModel* weak_dialog_model_ = nullptr;
base::WeakPtrFactory<ChromeAuthenticatorRequestDelegate> weak_ptr_factory_; base::WeakPtrFactory<ChromeAuthenticatorRequestDelegate> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ChromeAuthenticatorRequestDelegate); DISALLOW_COPY_AND_ASSIGN(ChromeAuthenticatorRequestDelegate);
......
...@@ -708,6 +708,10 @@ const char kValidateCrx[] = "validate-crx"; ...@@ -708,6 +708,10 @@ const char kValidateCrx[] = "validate-crx";
// Prints version information and quits. // Prints version information and quits.
const char kVersion[] = "version"; const char kVersion[] = "version";
// Enables the work-in-progress modal dialog shown for pending WebAuthn
// requests.
const char kWebAuthenticationUI[] = "enable-web-authentication-ui";
// Allows privileged JS applications to trigger event logging for peer // Allows privileged JS applications to trigger event logging for peer
// connections, and to later upload those logs to a remote server. // connections, and to later upload those logs to a remote server.
// * If "disable" or "disabled", remote-logging will be disabled. // * If "disable" or "disabled", remote-logging will be disabled.
......
...@@ -202,6 +202,7 @@ extern const char kUserAgent[]; ...@@ -202,6 +202,7 @@ extern const char kUserAgent[];
extern const char kUserDataDir[]; extern const char kUserDataDir[];
extern const char kValidateCrx[]; extern const char kValidateCrx[];
extern const char kVersion[]; extern const char kVersion[];
extern const char kWebAuthenticationUI[];
extern const char kWebRtcRemoteEventLog[]; extern const char kWebRtcRemoteEventLog[];
extern const char kWebRtcRemoteEventLogProactivePruningDelta[]; extern const char kWebRtcRemoteEventLogProactivePruningDelta[];
extern const char kWebRtcRemoteEventLogUploadNoSuppression[]; extern const char kWebRtcRemoteEventLogUploadNoSuppression[];
......
...@@ -851,6 +851,7 @@ test("browser_tests") { ...@@ -851,6 +851,7 @@ test("browser_tests") {
"../browser/ui/views/content_setting_bubble_contents_browsertest.cc", "../browser/ui/views/content_setting_bubble_contents_browsertest.cc",
"../browser/ui/views/device_chooser_browsertest.cc", "../browser/ui/views/device_chooser_browsertest.cc",
"../browser/ui/views/try_chrome_dialog_win/try_chrome_dialog_browsertest.cc", "../browser/ui/views/try_chrome_dialog_win/try_chrome_dialog_browsertest.cc",
"../browser/ui/webauthn/authenticator_dialog_browsertest.cc",
"../browser/ui/webui/chrome_url_data_manager_browsertest.cc", "../browser/ui/webui/chrome_url_data_manager_browsertest.cc",
"../browser/ui/webui/chromeos/bluetooth_pairing_dialog_browsertest-inl.h", "../browser/ui/webui/chromeos/bluetooth_pairing_dialog_browsertest-inl.h",
"../browser/ui/webui/constrained_web_dialog_ui_browsertest.cc", "../browser/ui/webui/constrained_web_dialog_ui_browsertest.cc",
......
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