Commit 09b4a197 authored by Renato Silva's avatar Renato Silva Committed by Commit Bot

Reland: CrOS - Login Screen - Minor cleanup

Reverted due to a merge conflict with another CL.

Original change's description:
> CrOS - Login Screen - Minor cleanup
>
> Rename AnimationState to UiState and use it to determine the
> visibility of elements. Remove multiple variables in favor of
> UiState.
>
> Bug: 1075994
> Change-Id: I0d7413fb173dadbff22cde0eb3af6f43586bdee2
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2352883
> Commit-Queue: Renato Silva <rrsilva@google.com>
> Reviewed-by: Denis Kuznetsov [CET] <antrim@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#798780}

Bug: 1075994
Change-Id: I0e2c05b692ddb807930455fca6b5a2216c0a16e1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2362183Reviewed-by: default avatarDenis Kuznetsov [CET] <antrim@chromium.org>
Reviewed-by: default avatarRoman Aleksandrov <raleksandrov@google.com>
Commit-Queue: Renato Silva <rrsilva@google.com>
Cr-Commit-Position: refs/heads/master@{#799680}
parent 0ad9a3ec
......@@ -1763,7 +1763,7 @@ void LockContentsView::LayoutAuth(LoginBigUserView* to_update,
DCHECK(to_update);
auto capture_animation_state_pre_layout = [&](LoginBigUserView* view) {
if (!animate || !view)
if (!view)
return;
if (view->auth_user())
view->auth_user()->CaptureStateForAnimationPreLayout();
......@@ -1818,10 +1818,10 @@ void LockContentsView::LayoutAuth(LoginBigUserView* to_update,
};
auto apply_animation_post_layout = [&](LoginBigUserView* view) {
if (!animate || !view)
if (!view)
return;
if (view->auth_user())
view->auth_user()->ApplyAnimationPostLayout();
view->auth_user()->ApplyAnimationPostLayout(animate);
};
// The high-level layout flow:
......
......@@ -69,13 +69,12 @@ constexpr const char kLoginAuthUserViewClassName[] = "LoginAuthUserView";
// Distance between the user view (ie, the icon and name) and the password
// textfield.
const int kDistanceBetweenUserViewAndPasswordDp = 24;
const int kDistanceBetweenUserViewAndOnlineSigninDp = 24;
const int kDistanceBetweenUserViewAndChallengeResponseDp = 32;
// Distance between the password textfield and the the pin keyboard.
const int kDistanceBetweenPasswordFieldAndPinKeyboardDp = 16;
// The height of the password field.
const int kPasswordFieldHeight = 37;
// Distance from the end of pin keyboard to the bottom of the big user view.
const int kDistanceFromPinKeyboardToBigUserViewBottomDp = 50;
......@@ -111,7 +110,7 @@ constexpr int kChallengeResponseArrowSizeDp = 48;
constexpr int kSpacingBetweenChallengeResponseArrowAndIconDp = 100;
constexpr int kSpacingBetweenChallengeResponseIconAndLabelDp = 15;
constexpr int kChallengeResponseIconSizeDp = 28;
constexpr int kDistanceBetweenPasswordFieldAndChallengeResponseViewDp = 0;
constexpr int kDistanceBetweenPwdFieldAndChallengeResponseViewDp = 0;
constexpr int kDisabledAuthMessageVerticalBorderDp = 16;
constexpr int kDisabledAuthMessageHorizontalBorderDp = 16;
......@@ -124,6 +123,9 @@ constexpr int kDisabledAuthMessageContentsFontSizeDeltaDp = -1;
constexpr int kDisabledAuthMessageRoundedCornerRadiusDp = 8;
constexpr int kNonEmptyWidthDp = 1;
gfx::Size SizeFromHeight(int height) {
return gfx::Size(kNonEmptyWidthDp, height);
}
// Returns an observer that will hide |view| when it fires. The observer will
// delete itself after firing (by returning true). Make sure to call
......@@ -744,24 +746,30 @@ class LoginAuthUserView::DisabledAuthMessageView : public views::View {
DISALLOW_COPY_AND_ASSIGN(DisabledAuthMessageView);
};
struct LoginAuthUserView::AnimationState {
explicit AnimationState(LoginAuthUserView* view) {
struct LoginAuthUserView::UiState {
explicit UiState(const LoginAuthUserView* view) {
has_password = view->ShouldShowPasswordField();
has_pinpad = view->ShouldShowPinPad();
has_fingerprint = view->HasAuthMethod(LoginAuthUserView::AUTH_FINGERPRINT);
has_challenge_response =
view->HasAuthMethod(LoginAuthUserView::AUTH_CHALLENGE_RESPONSE);
auth_disabled = view->HasAuthMethod(LoginAuthUserView::AUTH_DISABLED);
force_online_sign_in =
view->HasAuthMethod(LoginAuthUserView::AUTH_ONLINE_SIGN_IN);
non_pin_y_start_in_screen = view->GetBoundsInScreen().y();
pin_start_in_screen = view->pin_view_->GetBoundsInScreen().origin();
had_pinpad = view->ShouldShowPinPad();
had_password = view->ShouldShowPasswordField();
had_fingerprint = view->HasAuthMethod(LoginAuthUserView::AUTH_FINGERPRINT);
had_challenge_response =
view->HasAuthMethod(LoginAuthUserView::AUTH_CHALLENGE_RESPONSE);
}
bool has_password = false;
bool has_pinpad = false;
bool has_fingerprint = false;
bool has_challenge_response = false;
bool auth_disabled = false;
bool force_online_sign_in = false;
// Used for this view's animation in `ApplyAnimationPostLayout`.
int non_pin_y_start_in_screen = 0;
gfx::Point pin_start_in_screen;
bool had_pinpad = false;
bool had_password = false;
bool had_fingerprint = false;
bool had_challenge_response = false;
};
LoginAuthUserView::TestApi::TestApi(LoginAuthUserView* view) : view_(view) {}
......@@ -970,52 +978,42 @@ LoginAuthUserView::LoginAuthUserView(const LoginUserInfo& user,
add_padding(kDistanceFromPinKeyboardToBigUserViewBottomDp);
// Update authentication UI.
CaptureStateForAnimationPreLayout();
SetAuthMethods(auth_methods_);
user_view_->UpdateForUser(user, false /*animate*/);
ApplyAnimationPostLayout(/*animate*/ false);
user_view_->UpdateForUser(user, /*animate*/ false);
}
LoginAuthUserView::~LoginAuthUserView() = default;
void LoginAuthUserView::SetAuthMethods(uint32_t auth_methods,
AuthMethodsMetadata auth_metadata) {
bool had_password = ShouldShowPasswordField();
// It is an error to call this method without storing the previous state.
DCHECK(previous_state_);
// Apply changes and determine the new state of input fields.
auth_methods_ = static_cast<AuthMethods>(auth_methods);
auth_metadata_ = auth_metadata;
UpdateInputFieldMode();
const UiState current_state{this};
bool has_password = ShouldShowPasswordField();
bool has_pinpad = ShouldShowPinPad();
bool force_online_sign_in = HasAuthMethod(AUTH_ONLINE_SIGN_IN);
bool has_fingerprint = HasAuthMethod(AUTH_FINGERPRINT);
bool has_challenge_response = HasAuthMethod(AUTH_CHALLENGE_RESPONSE);
bool auth_disabled = HasAuthMethod(AUTH_DISABLED);
bool hide_auth = auth_disabled || force_online_sign_in;
online_sign_in_message_->SetVisible(force_online_sign_in);
disabled_auth_message_->SetVisible(auth_disabled);
if (auth_disabled)
disabled_auth_message_->RequestFocus();
online_sign_in_message_->SetVisible(current_state.force_online_sign_in);
disabled_auth_message_->SetVisible(current_state.auth_disabled);
// Adjust the PIN keyboard visibility before the password textfield's one, so
// that when both are about to be hidden the focus doesn't jump to the "1"
// keyboard button, causing unexpected accessibility effects.
pin_view_->SetVisible(has_pinpad);
pin_view_->SetVisible(current_state.has_pinpad);
password_view_->SetEnabled(has_password);
password_view_->SetEnabled(current_state.has_password);
password_view_->SetEnabledOnEmptyPassword(HasAuthMethod(AUTH_TAP));
password_view_->SetFocusEnabledForChildViews(has_password);
password_view_->SetVisible(!hide_auth && has_password);
password_view_->layer()->SetOpacity(has_password ? 1 : 0);
if (!had_password && has_password)
password_view_->RequestFocus();
password_view_->SetFocusEnabledForChildViews(current_state.has_password);
password_view_->SetVisible(current_state.has_password);
password_view_->layer()->SetOpacity(current_state.has_password ? 1 : 0);
fingerprint_view_->SetVisible(has_fingerprint);
fingerprint_view_->SetVisible(current_state.has_fingerprint);
fingerprint_view_->SetCanUsePin(HasAuthMethod(AUTH_PIN));
challenge_response_view_->SetVisible(has_challenge_response);
challenge_response_view_->SetVisible(current_state.has_challenge_response);
padding_below_user_view_->SetPreferredSize(GetPaddingBelowUserView());
padding_below_password_view_->SetPreferredSize(GetPaddingBelowPasswordView());
......@@ -1027,19 +1025,13 @@ void LoginAuthUserView::SetAuthMethods(uint32_t auth_methods,
IDS_ASH_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME,
base::UTF8ToUTF16(user_display_email)));
// Only the active auth user view has a password displayed. If that is the
// Only the active auth user view has authentication methods. If that is the
// case, then render the user view as if it was always focused, since clicking
// on it will not do anything (such as swapping users).
user_view_->SetForceOpaque(auth_methods_ != AUTH_NONE);
user_view_->SetTapEnabled(!HasAuthMethod(AUTH_PASSWORD));
// Tapping the user view will trigger the online sign-in flow when
// |force_online_sign_in| is true.
if (force_online_sign_in)
user_view_->RequestFocus();
if (has_challenge_response)
challenge_response_view_->RequestFocus();
user_view_->SetTapEnabled(auth_methods_ == AUTH_NONE);
UpdateFocus();
PreferredSizeChanged();
}
......@@ -1074,18 +1066,19 @@ void LoginAuthUserView::CaptureStateForAnimationPreLayout() {
stop_animation(fingerprint_view_);
stop_animation(challenge_response_view_);
DCHECK(!cached_animation_state_);
cached_animation_state_ = std::make_unique<AnimationState>(this);
DCHECK(!previous_state_);
previous_state_ = std::make_unique<UiState>(this);
}
void LoginAuthUserView::ApplyAnimationPostLayout() {
DCHECK(cached_animation_state_);
void LoginAuthUserView::ApplyAnimationPostLayout(bool animate) {
DCHECK(previous_state_);
// Release the previous state if no animation should be performed.
if (!animate) {
previous_state_.reset();
return;
}
bool has_password = ShouldShowPasswordField();
bool had_password = cached_animation_state_->had_password;
bool has_pinpad = ShouldShowPinPad();
bool has_fingerprint = HasAuthMethod(AUTH_FINGERPRINT);
bool has_challenge_response = HasAuthMethod(AUTH_CHALLENGE_RESPONSE);
const UiState current_state{this};
////////
// Animate the user info (ie, icon, name) up or down the screen.
......@@ -1098,7 +1091,7 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
// but it seems that the timing gets slightly out of sync with the PIN
// animation.
auto move_to_center = std::make_unique<ui::InterpolatedTranslation>(
gfx::PointF(0, cached_animation_state_->non_pin_y_start_in_screen -
gfx::PointF(0, previous_state_->non_pin_y_start_in_screen -
non_pin_y_end_in_screen),
gfx::PointF());
auto transition =
......@@ -1117,9 +1110,9 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
////////
// Fade the password view if it is being hidden or shown.
if (had_password != has_password) {
if (current_state.has_password != previous_state_->has_password) {
float opacity_start = 0, opacity_end = 1;
if (!has_password)
if (!current_state.has_password)
std::swap(opacity_start, opacity_end);
password_view_->layer()->SetOpacity(opacity_start);
......@@ -1130,7 +1123,7 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
login_constants::kChangeUserAnimationDurationMs));
settings.SetTweenType(gfx::Tween::Type::FAST_OUT_SLOW_IN);
if (had_password && !has_password) {
if (previous_state_->has_password && !current_state.has_password) {
settings.AddObserver(
new ClearPasswordAndHideAnimationObserver(password_view_));
}
......@@ -1142,13 +1135,13 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
////////
// Grow/shrink the PIN keyboard if it is being hidden or shown.
if (cached_animation_state_->had_pinpad != has_pinpad) {
if (!has_pinpad) {
if (previous_state_->has_pinpad != current_state.has_pinpad) {
if (!current_state.has_pinpad) {
gfx::Point pin_end_in_screen = pin_view_->GetBoundsInScreen().origin();
gfx::Rect pin_bounds = pin_view_->bounds();
pin_bounds.set_x(cached_animation_state_->pin_start_in_screen.x() -
pin_bounds.set_x(previous_state_->pin_start_in_screen.x() -
pin_end_in_screen.x());
pin_bounds.set_y(cached_animation_state_->pin_start_in_screen.y() -
pin_bounds.set_y(previous_state_->pin_start_in_screen.y() -
pin_end_in_screen.y());
// Since PIN is disabled, the previous Layout() hid the PIN keyboard.
......@@ -1158,7 +1151,7 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
}
auto transition = std::make_unique<PinKeyboardAnimation>(
has_pinpad /*grow*/, pin_view_->height(),
current_state.has_pinpad /*grow*/, pin_view_->height(),
// TODO(https://crbug.com/955119): Implement proper animation.
base::TimeDelta::FromMilliseconds(
login_constants::kChangeUserAnimationDurationMs / 2.0f),
......@@ -1166,7 +1159,7 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
auto* sequence = new ui::LayerAnimationSequence(std::move(transition));
// Hide the PIN keyboard after animation if needed.
if (!has_pinpad) {
if (!current_state.has_pinpad) {
auto* observer = BuildObserverToHideView(pin_view_);
sequence->AddObserver(observer);
observer->SetActive();
......@@ -1180,9 +1173,9 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
////////
// Fade the fingerprint view if it is being hidden or shown.
if (cached_animation_state_->had_fingerprint != has_fingerprint) {
if (previous_state_->has_fingerprint != current_state.has_fingerprint) {
float opacity_start = 0, opacity_end = 1;
if (!has_fingerprint)
if (!current_state.has_fingerprint)
std::swap(opacity_start, opacity_end);
fingerprint_view_->layer()->SetOpacity(opacity_start);
......@@ -1199,10 +1192,10 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
////////
// Fade the challenge response (Smart Card) if it is being hidden or shown.
if (cached_animation_state_->had_challenge_response !=
has_challenge_response) {
if (previous_state_->has_challenge_response !=
current_state.has_challenge_response) {
float opacity_start = 0, opacity_end = 1;
if (!has_challenge_response)
if (!current_state.has_challenge_response)
std::swap(opacity_start, opacity_end);
challenge_response_view_->layer()->SetOpacity(opacity_start);
......@@ -1217,7 +1210,7 @@ void LoginAuthUserView::ApplyAnimationPostLayout() {
}
}
cached_animation_state_.reset();
previous_state_.reset();
}
void LoginAuthUserView::UpdateForUser(const LoginUserInfo& user) {
......@@ -1370,13 +1363,37 @@ void LoginAuthUserView::AttemptAuthenticateWithChallengeResponse() {
weak_factory_.GetWeakPtr()));
}
void LoginAuthUserView::UpdateFocus() {
DCHECK(previous_state_);
const UiState current_state{this};
// All states are exclusive.
if (current_state.auth_disabled)
disabled_auth_message_->RequestFocus();
if (current_state.has_challenge_response)
challenge_response_view_->RequestFocus();
if (current_state.has_password && !previous_state_->has_password)
password_view_->RequestFocus();
// Tapping the user view will trigger the online sign-in flow when
// |force_online_sign_in| is true.
if (current_state.force_online_sign_in)
user_view_->RequestFocus();
}
void LoginAuthUserView::UpdateInputFieldMode() {
// Currently the challenge-response authentication can't be combined
// with the password or PIN based one.
if (!HasAuthMethod(AUTH_PASSWORD) || HasAuthMethod(AUTH_CHALLENGE_RESPONSE)) {
input_field_mode_ = InputFieldMode::DISABLED;
// There isn't an input field when any of the following is true:
// - Challenge response is active (Smart Card)
// - Online sign in message shown
// - Disabled message shown
// - No password auth available
if (HasAuthMethod(AUTH_CHALLENGE_RESPONSE) ||
HasAuthMethod(AUTH_ONLINE_SIGN_IN) ||
HasAuthMethod(AUTH_DISABLED) ||
!HasAuthMethod(AUTH_PASSWORD)) {
input_field_mode_ = InputFieldMode::NONE;
return;
}
if (!HasAuthMethod(AUTH_PIN)) {
input_field_mode_ = InputFieldMode::PASSWORD_ONLY;
return;
......@@ -1390,7 +1407,7 @@ bool LoginAuthUserView::ShouldShowPinPad() const {
if (auth_metadata_.virtual_keyboard_visible)
return false;
switch (input_field_mode_) {
case InputFieldMode::DISABLED:
case InputFieldMode::NONE:
return false;
case InputFieldMode::PASSWORD_ONLY:
return auth_metadata_.show_pinpad_for_pw;
......@@ -1405,25 +1422,29 @@ bool LoginAuthUserView::ShouldShowPasswordField() const {
}
gfx::Size LoginAuthUserView::GetPaddingBelowUserView() const {
int height = kDistanceBetweenUserViewAndPasswordDp;
const UiState state{this};
// Compensate with the height of the password field if there isn't
// an input field or smart card login (challenge response).
if (!ShouldShowPasswordField() && !HasAuthMethod(AUTH_CHALLENGE_RESPONSE))
height += kPasswordFieldHeight;
if (state.has_password)
return SizeFromHeight(kDistanceBetweenUserViewAndPasswordDp);
if (state.force_online_sign_in)
return SizeFromHeight(kDistanceBetweenUserViewAndOnlineSigninDp);
if (state.has_challenge_response)
return SizeFromHeight(kDistanceBetweenUserViewAndChallengeResponseDp);
return gfx::Size(kNonEmptyWidthDp, height);
return SizeFromHeight(0);
}
gfx::Size LoginAuthUserView::GetPaddingBelowPasswordView() const {
int padding_view_height = kDistanceBetweenPasswordFieldAndPinKeyboardDp;
if (HasAuthMethod(AUTH_FINGERPRINT) && !ShouldShowPinPad()) {
padding_view_height = kDistanceBetweenPasswordFieldAndFingerprintViewDp;
} else if (HasAuthMethod(AUTH_CHALLENGE_RESPONSE) && !ShouldShowPinPad()) {
padding_view_height =
kDistanceBetweenPasswordFieldAndChallengeResponseViewDp;
}
return gfx::Size(kNonEmptyWidthDp, padding_view_height);
const UiState state{this};
if (state.has_pinpad)
return SizeFromHeight(kDistanceBetweenPasswordFieldAndPinKeyboardDp);
if (state.has_fingerprint)
return SizeFromHeight(kDistanceBetweenPasswordFieldAndFingerprintViewDp);
if (state.has_challenge_response)
return SizeFromHeight(kDistanceBetweenPwdFieldAndChallengeResponseViewDp);
return SizeFromHeight(0);
}
base::string16 LoginAuthUserView::GetPasswordViewPlaceholder() const {
......
......@@ -68,7 +68,7 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
// This is determined by the current authentication methods
// that a user has.
enum class InputFieldMode {
DISABLED, // Not showing any input field.
NONE, // Not showing any input field.
PASSWORD_ONLY, // No PIN set. Password only field.
PIN_AND_PASSWORD, // PIN set.
};
......@@ -125,7 +125,8 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
// Set the displayed set of auth methods. |auth_methods| contains or-ed
// together AuthMethod values. |auth_metadata| provides additional control
// parameters for the view.
// parameters for the view. Must always be called in conjunction with
// `CaptureStateForAnimationPreLayout` and `ApplyAnimationPostLayout`.
void SetAuthMethods(
uint32_t auth_methods,
AuthMethodsMetadata auth_metadata = AuthMethodsMetadata());
......@@ -140,8 +141,9 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
// animation.
void CaptureStateForAnimationPreLayout();
// Applies animation based on current layout state compared to the most
// recently captured state.
void ApplyAnimationPostLayout();
// recently captured state. If `animate` is false, the previous UI state
// is released and no animation is performed.
void ApplyAnimationPostLayout(bool animate);
// Update the displayed name, icon, etc to that of |user|.
void UpdateForUser(const LoginUserInfo& user);
......@@ -172,7 +174,7 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
private:
struct AnimationState;
struct UiState;
class FingerprintView;
class ChallengeResponseView;
class DisabledAuthMessageView;
......@@ -210,6 +212,9 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
// starts the asynchronous authentication process against a security token.
void AttemptAuthenticateWithChallengeResponse();
// Updates the element in focus. Used in `ApplyAnimationPostLayout`.
void UpdateFocus();
// Determines the mode of the input field based on the available
// authentication methods.
void UpdateInputFieldMode();
......@@ -230,7 +235,7 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
AuthMethodsMetadata auth_metadata_ = AuthMethodsMetadata();
// Controls which input field is currently being shown.
InputFieldMode input_field_mode_ = InputFieldMode::DISABLED;
InputFieldMode input_field_mode_ = InputFieldMode::NONE;
LoginUserView* user_view_ = nullptr;
LoginPasswordView* password_view_ = nullptr;
......@@ -252,10 +257,10 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
const OnAuthCallback on_auth_;
const LoginUserView::OnTap on_tap_;
// Animation state that was cached from before a layout. Generated by
// |CaptureStateForAnimationPreLayout| and consumed by
// |ApplyAnimationPostLayout|.
std::unique_ptr<AnimationState> cached_animation_state_;
// UI state that was stored before setting new authentication methods.
// Generated by `CaptureStateForAnimationPreLayout` and consumed by
// `ApplyAnimationPostLayout`.
std::unique_ptr<UiState> previous_state_;
base::WeakPtrFactory<LoginAuthUserView> weak_factory_{this};
......
......@@ -65,7 +65,9 @@ class LoginAuthUserViewUnittest : public LoginTestBase {
auth_metadata.show_pinpad_for_pw = show_pinpad_for_pw;
auth_metadata.virtual_keyboard_visible = virtual_keyboard_visible;
auth_metadata.autosubmit_pin_length = autosubmit_pin_length;
view_->CaptureStateForAnimationPreLayout();
view_->SetAuthMethods(auth_methods, auth_metadata);
view_->ApplyAnimationPostLayout(true);
}
LoginUserInfo user_;
......@@ -183,18 +185,14 @@ TEST_F(LoginAuthUserViewUnittest,
password_test.textfield()->SetText(base::ASCIIToUTF16("Hello"));
// Enable some other auth method (PIN), password is not cleared.
view_->CaptureStateForAnimationPreLayout();
EXPECT_TRUE(has_password());
SetAuthMethods(LoginAuthUserView::AUTH_PASSWORD |
LoginAuthUserView::AUTH_PIN);
EXPECT_TRUE(has_password());
view_->ApplyAnimationPostLayout();
EXPECT_TRUE(has_password());
// Disable password, password is cleared.
view_->CaptureStateForAnimationPreLayout();
SetAuthMethods(LoginAuthUserView::AUTH_NONE);
EXPECT_TRUE(has_password());
view_->ApplyAnimationPostLayout();
SetAuthMethods(LoginAuthUserView::AUTH_NONE);
EXPECT_FALSE(has_password());
}
......
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