Commit 92f924a5 authored by Quan Nguyen's avatar Quan Nguyen Committed by Commit Bot

cros: Add enrollment button for external binary auth

Bug: 890912
Change-Id: Ia55a93a2d1c2c956b95797ca175c3116a8d2b255
Reviewed-on: https://chromium-review.googlesource.com/c/1279359
Commit-Queue: Quan Nguyen <qnnguyen@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarJacob Dufault <jdufault@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600837}
parent 9ab4b2cc
......@@ -4,6 +4,8 @@
#include "ash/login/login_screen_controller.h"
#include <utility>
#include "ash/focus_cycler.h"
#include "ash/login/ui/lock_screen.h"
#include "ash/login/ui/lock_window.h"
......@@ -19,6 +21,7 @@
#include "ash/system/status_area_widget_delegate.h"
#include "ash/system/toast/toast_data.h"
#include "ash/system/toast/toast_manager.h"
#include "base/bind.h"
#include "base/debug/alias.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
......@@ -149,6 +152,20 @@ void LoginScreenController::AuthenticateUserWithExternalBinary(
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void LoginScreenController::EnrollUserWithExternalBinary(
OnAuthenticateCallback callback) {
if (!login_screen_client_) {
std::move(callback).Run(base::nullopt);
return;
}
login_screen_client_->EnrollUserWithExternalBinary(base::BindOnce(
[](OnAuthenticateCallback callback, bool success) {
std::move(callback).Run(base::make_optional<bool>(success));
},
std::move(callback)));
}
void LoginScreenController::AuthenticateUserWithEasyUnlock(
const AccountId& account_id) {
// TODO(jdufault): integrate this into authenticate stage after mojom is
......@@ -537,7 +554,7 @@ void LoginScreenController::OnAuthenticateComplete(
OnAuthenticateCallback callback,
bool success) {
authentication_stage_ = AuthenticationStage::kUserCallback;
std::move(callback).Run(success);
std::move(callback).Run(base::make_optional<bool>(success));
authentication_stage_ = AuthenticationStage::kIdle;
}
......
......@@ -63,6 +63,7 @@ class ASH_EXPORT LoginScreenController : public mojom::LoginScreen {
OnAuthenticateCallback callback);
void AuthenticateUserWithExternalBinary(const AccountId& account_id,
OnAuthenticateCallback callback);
void EnrollUserWithExternalBinary(OnAuthenticateCallback callback);
void AuthenticateUserWithEasyUnlock(const AccountId& account_id);
void HardlockPod(const AccountId& account_id);
void RecordClickOnLockIcon(const AccountId& account_id);
......
......@@ -5,6 +5,7 @@
#include "ash/login/mock_login_screen_client.h"
#include <memory>
#include <utility>
#include "ash/login/login_screen_controller.h"
#include "ash/shell.h"
......@@ -48,6 +49,16 @@ void MockLoginScreenClient::AuthenticateUserWithExternalBinary(
}
}
void MockLoginScreenClient::EnrollUserWithExternalBinary(
EnrollUserWithExternalBinaryCallback callback) {
EnrollUserWithExternalBinary_(callback);
if (enroll_user_with_external_binary_callback_storage_) {
*enroll_user_with_external_binary_callback_storage_ = std::move(callback);
} else {
std::move(callback).Run(authenticate_user_callback_result_);
}
}
std::unique_ptr<MockLoginScreenClient> BindMockLoginScreenClient() {
auto client = std::make_unique<MockLoginScreenClient>();
Shell::Get()->login_screen_controller()->SetClient(
......
......@@ -28,6 +28,8 @@ class MockLoginScreenClient : public mojom::LoginScreenClient {
MOCK_METHOD2(AuthenticateUserWithExternalBinary_,
void(const AccountId& account_id,
AuthenticateUserWithExternalBinaryCallback& callback));
MOCK_METHOD1(EnrollUserWithExternalBinary_,
void(EnrollUserWithExternalBinaryCallback& callback));
// Set the result that should be passed to |callback| in
// |AuthenticateUserWithPasswordOrPin| or
......@@ -46,6 +48,10 @@ class MockLoginScreenClient : public mojom::LoginScreenClient {
AuthenticateUserWithPasswordOrPinCallback* storage) {
authenticate_user_with_external_binary_callback_storage_ = storage;
}
void set_enroll_user_with_external_binary_storage(
EnrollUserWithExternalBinaryCallback* storage) {
enroll_user_with_external_binary_callback_storage_ = storage;
}
// mojom::LoginScreenClient:
void AuthenticateUserWithPasswordOrPin(
......@@ -56,6 +62,8 @@ class MockLoginScreenClient : public mojom::LoginScreenClient {
void AuthenticateUserWithExternalBinary(
const AccountId& account_id,
AuthenticateUserWithExternalBinaryCallback callback) override;
void EnrollUserWithExternalBinary(
EnrollUserWithExternalBinaryCallback callback) override;
MOCK_METHOD1(AuthenticateUserWithEasyUnlock,
void(const AccountId& account_id));
MOCK_METHOD1(HardlockPod, void(const AccountId& account_id));
......@@ -93,6 +101,8 @@ class MockLoginScreenClient : public mojom::LoginScreenClient {
authenticate_user_with_password_or_pin_callback_storage_ = nullptr;
AuthenticateUserWithExternalBinaryCallback*
authenticate_user_with_external_binary_callback_storage_ = nullptr;
EnrollUserWithExternalBinaryCallback*
enroll_user_with_external_binary_callback_storage_ = nullptr;
mojo::Binding<mojom::LoginScreenClient> binding_;
......
......@@ -23,7 +23,9 @@
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/night_light/time_of_day.h"
#include "ash/system/toast/toast_manager.h"
#include "ash/wallpaper/wallpaper_controller.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "components/user_manager/user.h"
#include "ui/base/l10n/l10n_util.h"
......@@ -456,6 +458,8 @@ LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user,
// TODO(jdufault): Implement real UI.
external_binary_auth_button_ = views::MdTextButton::Create(
this, base::ASCIIToUTF16("Authenticate with external binary"));
external_binary_enrollment_button_ = views::MdTextButton::Create(
this, base::ASCIIToUTF16("Enroll with external binary"));
SetPaintToLayer(ui::LayerType::LAYER_NOT_DRAWN);
......@@ -479,6 +483,9 @@ LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user,
login_views_utils::WrapViewForPreferredSize(fingerprint_view_);
auto* wrapped_external_binary_view =
login_views_utils::WrapViewForPreferredSize(external_binary_auth_button_);
auto* wrapped_external_binary_enrollment_view =
login_views_utils::WrapViewForPreferredSize(
external_binary_enrollment_button_);
auto* wrapped_padding_below_password_view =
login_views_utils::WrapViewForPreferredSize(padding_below_password_view_);
......@@ -489,6 +496,7 @@ LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user,
AddChildView(wrapped_pin_view);
AddChildView(wrapped_fingerprint_view);
AddChildView(wrapped_external_binary_view);
AddChildView(wrapped_external_binary_enrollment_view);
AddChildView(wrapped_user_view);
AddChildView(wrapped_padding_below_password_view);
......@@ -519,6 +527,7 @@ LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user,
add_view(wrapped_pin_view);
add_view(wrapped_fingerprint_view);
add_view(wrapped_external_binary_view);
add_view(wrapped_external_binary_enrollment_view);
add_padding(kDistanceFromPinKeyboardToBigUserViewBottomDp);
// Update authentication UI.
......@@ -565,6 +574,7 @@ void LoginAuthUserView::SetAuthMethods(uint32_t auth_methods,
pin_view_->SetVisible(has_pin);
fingerprint_view_->SetVisible(has_fingerprint);
external_binary_auth_button_->SetVisible(has_external_binary);
external_binary_enrollment_button_->SetVisible(has_external_binary);
int padding_view_height = kDistanceBetweenPasswordFieldAndPinKeyboardDp;
if (has_fingerprint && !has_pin) {
......@@ -778,10 +788,18 @@ void LoginAuthUserView::ButtonPressed(views::Button* sender,
} else if (sender == external_binary_auth_button_) {
password_view_->SetReadOnly(true);
external_binary_auth_button_->SetEnabled(false);
external_binary_enrollment_button_->SetEnabled(false);
Shell::Get()->login_screen_controller()->AuthenticateUserWithExternalBinary(
current_user()->basic_user_info->account_id,
base::BindOnce(&LoginAuthUserView::OnAuthComplete,
weak_factory_.GetWeakPtr()));
} else if (sender == external_binary_enrollment_button_) {
password_view_->SetReadOnly(true);
external_binary_auth_button_->SetEnabled(false);
external_binary_enrollment_button_->SetEnabled(false);
Shell::Get()->login_screen_controller()->EnrollUserWithExternalBinary(
base::BindOnce(&LoginAuthUserView::OnEnrollmentComplete,
weak_factory_.GetWeakPtr()));
}
}
......@@ -803,22 +821,39 @@ void LoginAuthUserView::OnAuthSubmit(const base::string16& password) {
}
void LoginAuthUserView::OnAuthComplete(base::Optional<bool> auth_success) {
if (!auth_success.has_value())
return;
// Clear the password only if auth fails. Make sure to keep the password view
// disabled even if auth succeededs, as if the user submits a password while
// animating the next lock screen will not work as expected. See
// https://crbug.com/808486.
if (!auth_success.value()) {
if (!auth_success.has_value() || !auth_success.value()) {
password_view_->Clear();
password_view_->SetReadOnly(false);
external_binary_auth_button_->SetEnabled(true);
external_binary_enrollment_button_->SetEnabled(true);
}
on_auth_.Run(auth_success.value());
}
void LoginAuthUserView::OnEnrollmentComplete(
base::Optional<bool> enrollment_success) {
password_view_->SetReadOnly(false);
external_binary_auth_button_->SetEnabled(true);
external_binary_enrollment_button_->SetEnabled(true);
std::string result_message;
if (!enrollment_success.has_value()) {
result_message = "Enrollment attempt failed to received response.";
} else {
result_message = enrollment_success.value() ? "Enrollment successful."
: "Enrollment failed.";
}
ToastData toast_data("EnrollmentToast", base::ASCIIToUTF16(result_message),
2000, base::nullopt, true /*visible_on_lock_screen*/);
Shell::Get()->toast_manager()->Show(toast_data);
}
void LoginAuthUserView::OnUserViewTap() {
if (HasAuthMethod(AUTH_TAP)) {
Shell::Get()->login_screen_controller()->AuthenticateUserWithEasyUnlock(
......
......@@ -14,6 +14,7 @@
#include "ash/login/ui/non_accessible_view.h"
#include "ash/public/interfaces/user_info.mojom.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/scoped_observer.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/view.h"
......@@ -141,6 +142,8 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
void OnAuthSubmit(const base::string16& password);
// Called with the result of the request started in |OnAuthSubmit|.
void OnAuthComplete(base::Optional<bool> auth_success);
// Called with the result of the external binary enrollment request.
void OnEnrollmentComplete(base::Optional<bool> enrollment_success);
// Called when the user view has been tapped. This will run |on_auth_| if tap
// to unlock is enabled, or run |OnOnlineSignInMessageTap| if the online
......@@ -166,6 +169,7 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
DisabledAuthMessageView* disabled_auth_message_ = nullptr;
FingerprintView* fingerprint_view_ = nullptr;
views::LabelButton* external_binary_auth_button_ = nullptr;
views::LabelButton* external_binary_enrollment_button_ = nullptr;
// Displays padding between:
// 1. Password field and pin keyboard
......
......@@ -229,6 +229,9 @@ interface LoginScreenClient {
AuthenticateUserWithExternalBinary(signin.mojom.AccountId account_id)
=> (bool auth_success);
// Attempt to enroll a user in the external binary authentication system.
EnrollUserWithExternalBinary() => (bool enrollment_success);
// Try to authenticate |account_id| using easy unlock. This can be used on the
// login or lock screen.
// |account_id|: The account id of the user we are authenticating.
......
......@@ -44,6 +44,7 @@ namespace chromeos {
namespace {
constexpr char kLockDisplay[] = "lock";
constexpr char kExternalBinaryAuth[] = "external_binary_auth";
constexpr char kExternalBinaryEnrollment[] = "external_binary_enrollment";
constexpr char kWebCameraDeviceContext[] = "WebCamera: WebCamera";
constexpr base::TimeDelta kExternalBinaryAuthTimeout =
base::TimeDelta::FromSeconds(2);
......@@ -236,7 +237,7 @@ void ViewsScreenLocker::HandleAuthenticateUserWithExternalBinary(
const AccountId& account_id,
AuthenticateUserWithExternalBinaryCallback callback) {
authenticate_with_external_binary_callback_ = std::move(callback);
external_binary_auth_timer_.Start(
external_binary_timer_.Start(
FROM_HERE, kExternalBinaryAuthTimeout,
base::BindOnce(&ViewsScreenLocker::OnExternalBinaryAuthTimeout,
weak_factory_.GetWeakPtr()));
......@@ -244,6 +245,17 @@ void ViewsScreenLocker::HandleAuthenticateUserWithExternalBinary(
&StartGraphIfNeeded, media_analytics_client_, kExternalBinaryAuth));
}
void ViewsScreenLocker::HandleEnrollUserWithExternalBinary(
EnrollUserWithExternalBinaryCallback callback) {
enroll_user_with_external_binary_callback_ = std::move(callback);
external_binary_timer_.Start(
FROM_HERE, kExternalBinaryAuthTimeout,
base::BindOnce(&ViewsScreenLocker::OnExternalBinaryEnrollmentTimeout,
weak_factory_.GetWeakPtr()));
media_analytics_client_->GetState(base::BindOnce(
&StartGraphIfNeeded, media_analytics_client_, kExternalBinaryEnrollment));
}
void ViewsScreenLocker::HandleAuthenticateUserWithEasyUnlock(
const AccountId& account_id) {
user_selection_screen_->AttemptEasyUnlock(account_id);
......@@ -338,21 +350,29 @@ void ViewsScreenLocker::HandleLockScreenAppFocusOut(bool reverse) {
void ViewsScreenLocker::OnDetectionSignal(
const mri::MediaPerception& media_perception) {
if (!authenticate_with_external_binary_callback_)
return;
if (authenticate_with_external_binary_callback_) {
const mri::FramePerception& frame = media_perception.frame_perception(0);
if (frame.frame_id() != 1)
return;
const mri::FramePerception& frame = media_perception.frame_perception(0);
if (frame.frame_id() != 1)
return;
mri::State new_state;
new_state.set_status(mri::State::SUSPENDED);
media_analytics_client_->SetState(new_state, base::DoNothing());
mri::State new_state;
new_state.set_status(mri::State::SUSPENDED);
media_analytics_client_->SetState(new_state, base::DoNothing());
external_binary_timer_.Stop();
std::move(authenticate_with_external_binary_callback_)
.Run(true /*auth_success*/);
ScreenLocker::Hide();
} else if (enroll_user_with_external_binary_callback_) {
const mri::FramePerception& frame = media_perception.frame_perception(0);
external_binary_auth_timer_.Stop();
std::move(authenticate_with_external_binary_callback_)
.Run(true /*auth_success*/);
ScreenLocker::Hide();
external_binary_timer_.Stop();
mri::State new_state;
new_state.set_status(mri::State::SUSPENDED);
media_analytics_client_->SetState(new_state, base::DoNothing());
std::move(enroll_user_with_external_binary_callback_)
.Run(frame.frame_id() == 1 /*enrollment_success*/);
}
}
void ViewsScreenLocker::UpdatePinKeyboardState(const AccountId& account_id) {
......@@ -388,4 +408,12 @@ void ViewsScreenLocker::OnExternalBinaryAuthTimeout() {
media_analytics_client_->SetState(new_state, base::DoNothing());
}
void ViewsScreenLocker::OnExternalBinaryEnrollmentTimeout() {
std::move(enroll_user_with_external_binary_callback_)
.Run(false /*auth_success*/);
mri::State new_state;
new_state.set_status(mri::State::SUSPENDED);
media_analytics_client_->SetState(new_state, base::DoNothing());
}
} // namespace chromeos
......@@ -61,6 +61,8 @@ class ViewsScreenLocker : public LoginScreenClient::Delegate,
void HandleAuthenticateUserWithExternalBinary(
const AccountId& account_id,
AuthenticateUserWithExternalBinaryCallback callback) override;
void HandleEnrollUserWithExternalBinary(
EnrollUserWithExternalBinaryCallback) override;
void HandleAuthenticateUserWithEasyUnlock(
const AccountId& account_id) override;
void HandleHardlockPod(const AccountId& account_id) override;
......@@ -91,6 +93,7 @@ class ViewsScreenLocker : public LoginScreenClient::Delegate,
void OnAllowedInputMethodsChanged();
void OnPinCanAuthenticate(const AccountId& account_id, bool can_authenticate);
void OnExternalBinaryAuthTimeout();
void OnExternalBinaryEnrollmentTimeout();
std::unique_ptr<UserBoardViewMojo> user_board_view_mojo_;
std::unique_ptr<UserSelectionScreen> user_selection_screen_;
......@@ -114,6 +117,9 @@ class ViewsScreenLocker : public LoginScreenClient::Delegate,
AuthenticateUserWithExternalBinaryCallback
authenticate_with_external_binary_callback_;
EnrollUserWithExternalBinaryCallback
enroll_user_with_external_binary_callback_;
// Callback registered as a lock screen apps focus handler - it should be
// called to hand focus over to lock screen apps.
LockScreenAppFocusCallback lock_screen_app_focus_handler_;
......@@ -123,9 +129,9 @@ class ViewsScreenLocker : public LoginScreenClient::Delegate,
chromeos::MediaAnalyticsClient* media_analytics_client_;
// Timer for external binary auth attempt. Allows repeated auth attempts up to
// a specific timeout.
base::OneShotTimer external_binary_auth_timer_;
// Timer for external binary auth/enrollment attempt. Allows repeated attempts
// up to a specific timeout.
base::OneShotTimer external_binary_timer_;
ScopedObserver<chromeos::MediaAnalyticsClient, ViewsScreenLocker>
scoped_observer_{this};
......
......@@ -380,6 +380,12 @@ void LoginDisplayHostMojo::HandleAuthenticateUserWithExternalBinary(
std::move(callback).Run(false);
}
void LoginDisplayHostMojo::HandleEnrollUserWithExternalBinary(
EnrollUserWithExternalBinaryCallback callback) {
// Enroll in external binary auth system is not supported for login.
std::move(callback).Run(false);
}
void LoginDisplayHostMojo::HandleAuthenticateUserWithEasyUnlock(
const AccountId& account_id) {
user_selection_screen_->AttemptEasyUnlock(account_id);
......
......@@ -106,6 +106,8 @@ class LoginDisplayHostMojo : public LoginDisplayHostCommon,
void HandleAuthenticateUserWithExternalBinary(
const AccountId& account_id,
AuthenticateUserWithExternalBinaryCallback callback) override;
void HandleEnrollUserWithExternalBinary(
EnrollUserWithExternalBinaryCallback callback) override;
void HandleAuthenticateUserWithEasyUnlock(
const AccountId& account_id) override;
void HandleHardlockPod(const AccountId& account_id) override;
......
......@@ -91,15 +91,24 @@ void LoginScreenClient::AuthenticateUserWithPasswordOrPin(
void LoginScreenClient::AuthenticateUserWithExternalBinary(
const AccountId& account_id,
AuthenticateUserWithExternalBinaryCallback callback) {
if (delegate_) {
delegate_->HandleAuthenticateUserWithExternalBinary(account_id,
std::move(callback));
// TODO(jdufault): Record auth method attempt here
NOTIMPLEMENTED() << "Missing UMA recording for external binary auth";
} else {
LOG(ERROR) << "Failed AuthenticateUserWithExternalBinary; no delegate";
std::move(callback).Run(false);
}
if (!delegate_)
LOG(FATAL) << "Failed AuthenticateUserWithExternalBinary; no delegate";
delegate_->HandleAuthenticateUserWithExternalBinary(account_id,
std::move(callback));
// TODO: Record auth method attempt here
NOTIMPLEMENTED() << "Missing UMA recording for external binary auth";
}
void LoginScreenClient::EnrollUserWithExternalBinary(
EnrollUserWithExternalBinaryCallback callback) {
if (!delegate_)
LOG(FATAL) << "Failed EnrollUserWithExternalBinary; no delegate";
delegate_->HandleEnrollUserWithExternalBinary(std::move(callback));
// TODO: Record enrollment attempt here
NOTIMPLEMENTED() << "Missing UMA recording for external binary enrollment";
}
void LoginScreenClient::AuthenticateUserWithEasyUnlock(
......
......@@ -14,6 +14,8 @@ using AuthenticateUserWithPasswordOrPinCallback =
ash::mojom::LoginScreenClient::AuthenticateUserWithPasswordOrPinCallback;
using AuthenticateUserWithExternalBinaryCallback =
ash::mojom::LoginScreenClient::AuthenticateUserWithExternalBinaryCallback;
using EnrollUserWithExternalBinaryCallback =
ash::mojom::LoginScreenClient::EnrollUserWithExternalBinaryCallback;
namespace chromeos {
class LoginAuthRecorder;
......@@ -36,6 +38,8 @@ class LoginScreenClient : public ash::mojom::LoginScreenClient {
virtual void HandleAuthenticateUserWithExternalBinary(
const AccountId& account_id,
AuthenticateUserWithExternalBinaryCallback callback) = 0;
virtual void HandleEnrollUserWithExternalBinary(
EnrollUserWithExternalBinaryCallback) = 0;
virtual void HandleAuthenticateUserWithEasyUnlock(
const AccountId& account_id) = 0;
virtual void HandleHardlockPod(const AccountId& account_id) = 0;
......@@ -78,6 +82,8 @@ class LoginScreenClient : public ash::mojom::LoginScreenClient {
void AuthenticateUserWithExternalBinary(
const AccountId& account_id,
AuthenticateUserWithExternalBinaryCallback callback) override;
void EnrollUserWithExternalBinary(
EnrollUserWithExternalBinaryCallback callback) override;
void AuthenticateUserWithEasyUnlock(const AccountId& account_id) override;
void HardlockPod(const AccountId& account_id) override;
void RecordClickOnLockIcon(const AccountId& account_id) override;
......
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