Commit 5eaa3a19 authored by Jan Krcal's avatar Jan Krcal Committed by Commit Bot

[Identity pill] Show first name instead of email

This CL changes the way we represent user's identity in the pill: we now
show the user's first name (if available) and resort to email,
otherwise.

This CL also moves from Email specific naming of functions towards more
generic "Identity" (as it is not always Name, either).

Bug: 967317
Change-Id: Ibea8f2953687a32a54f70a8a59dbf147d4114db6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1832220
Commit-Queue: Jan Krcal <jkrcal@chromium.org>
Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Reviewed-by: default avatarThomas Tangl <tangltom@chromium.org>
Reviewed-by: default avatarPeter Boström <pbos@chromium.org>
Auto-Submit: Jan Krcal <jkrcal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#703654}
parent 592eacf9
......@@ -236,6 +236,30 @@ std::vector<AccountInfo> GetAccountsForDicePromos(Profile* profile) {
#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
base::string16 GetShortProfileIdentityToDisplay(
const ProfileAttributesEntry& profile_attributes_entry,
Profile* profile) {
DCHECK(profile);
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile);
CoreAccountInfo core_info =
identity_manager->GetUnconsentedPrimaryAccountInfo();
// If there's no unconsented primary account, simply return the name of the
// profile according to profile attributes.
if (core_info.IsEmpty())
return profile_attributes_entry.GetName();
base::Optional<AccountInfo> extended_info =
identity_manager
->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
core_info.account_id);
// If there's no given name available, return the user email.
if (!extended_info.has_value() || extended_info->given_name.empty())
return base::UTF8ToUTF16(core_info.email);
return base::UTF8ToUTF16(extended_info->given_name);
}
std::string GetAllowedDomain(std::string signin_pattern) {
std::vector<std::string> splitted_signin_pattern = base::SplitString(
signin_pattern, "@", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
......
......@@ -18,6 +18,7 @@
struct AccountInfo;
class Browser;
class Profile;
class ProfileAttributesEntry;
class ProfileAttributesStorage;
// Utility functions to gather status information from the various signed in
......@@ -64,6 +65,15 @@ std::vector<AccountInfo> GetAccountsForDicePromos(Profile* profile);
#endif
// Returns the short user identity to display for |profile|. It is based on the
// current unconsented primary account (if exists).
// TODO(crbug.com/1012179): Move this logic into ProfileAttributesEntry once
// AvatarToolbarButton becomes an observer of ProfileAttributesStorage and thus
// ProfileAttributesEntry is up-to-date when AvatarToolbarButton needs it.
base::string16 GetShortProfileIdentityToDisplay(
const ProfileAttributesEntry& profile_attributes_entry,
Profile* profile);
// Returns the domain of the policy value of RestrictSigninToPattern. Returns
// an empty string if the policy is not set or can not be parsed. The parser
// only supports the policy value that matches [^@]+@[a-zA-Z0-9\-.]+(\\E)?\$?$.
......
......@@ -42,7 +42,7 @@
namespace {
constexpr base::TimeDelta kEmailExpansionDuration =
constexpr base::TimeDelta kIdentityAnimationDuration =
base::TimeDelta::FromSeconds(3);
constexpr base::TimeDelta kAvatarHighlightAnimationDuration =
......@@ -129,7 +129,7 @@ AvatarToolbarButton::AvatarToolbarButton(Browser* browser)
if (base::FeatureList::IsEnabled(features::kAnimatedAvatarButton)) {
// For consistency with identity representation, we need to have the avatar
// on the left and the (potential) user-name / email on the right.
// on the left and the (potential) user name on the right.
SetHorizontalAlignment(gfx::ALIGN_LEFT);
}
......@@ -151,8 +151,8 @@ AvatarToolbarButton::~AvatarToolbarButton() {
void AvatarToolbarButton::UpdateIcon() {
// If widget isn't set, the button doesn't have access to the theme provider
// to set colors. Defer updating until AddedToWidget(). This may get called as
// a result of SetUserEmail() called from the constructor when the button is
// not yet added to the ToolbarView's hierarchy.
// a result of OnUserIdentityChanged() called from the constructor when the
// button is not yet added to the ToolbarView's hierarchy.
if (!GetWidget())
return;
gfx::Image gaia_image = GetGaiaImage();
......@@ -160,9 +160,9 @@ void AvatarToolbarButton::UpdateIcon() {
// TODO(crbug.com/990286): Get rid of this logic completely when we cache the
// Google account image in the profile cache and thus it is always available.
if (waiting_for_image_to_show_user_email_ && !gaia_image.IsEmpty()) {
waiting_for_image_to_show_user_email_ = false;
ExpandToShowEmail();
if (identity_animation_state_ == IdentityAnimationState::kWaitingForImage &&
!gaia_image.IsEmpty()) {
ShowIdentityAnimation();
}
}
......@@ -189,8 +189,9 @@ void AvatarToolbarButton::UpdateText() {
}
break;
}
case State::kAnimatedSignIn: {
text = base::UTF8ToUTF16(*user_email_);
case State::kAnimatedUserIdentity: {
text = signin_ui_util::GetShortProfileIdentityToDisplay(
*GetProfileAttributesEntry(profile_), profile_);
break;
}
case State::kHighlightAnimation:
......@@ -250,8 +251,10 @@ void AvatarToolbarButton::ShowAvatarHighlightAnimation() {
void AvatarToolbarButton::NotifyClick(const ui::Event& event) {
Button::NotifyClick(event);
if (should_reset_user_email_when_no_longer_hovered_or_focused_)
ResetUserEmailWhenNotHoveredOrFocused();
if (identity_animation_state_ ==
IdentityAnimationState::kShowingUntilNoLongerHoveredOrFocused) {
HideIdentityAnimationWhenNotHoveredOrFocused();
}
// TODO(bsep): Other toolbar buttons have ToolbarView as a listener and let it
// call ExecuteCommandWithDisposition on their behalf. Unfortunately, it's not
// possible to plumb IsKeyEvent through, so this has to be a special case.
......@@ -262,14 +265,18 @@ void AvatarToolbarButton::NotifyClick(const ui::Event& event) {
}
void AvatarToolbarButton::OnMouseExited(const ui::MouseEvent& event) {
if (should_reset_user_email_when_no_longer_hovered_or_focused_)
ResetUserEmailWhenNotHoveredOrFocused();
if (identity_animation_state_ ==
IdentityAnimationState::kShowingUntilNoLongerHoveredOrFocused) {
HideIdentityAnimationWhenNotHoveredOrFocused();
}
ToolbarButton::OnMouseExited(event);
}
void AvatarToolbarButton::OnBlur() {
if (should_reset_user_email_when_no_longer_hovered_or_focused_)
ResetUserEmailWhenNotHoveredOrFocused();
if (identity_animation_state_ ==
IdentityAnimationState::kShowingUntilNoLongerHoveredOrFocused) {
HideIdentityAnimationWhenNotHoveredOrFocused();
}
ToolbarButton::OnBlur();
}
......@@ -332,7 +339,7 @@ void AvatarToolbarButton::OnUnconsentedPrimaryAccountChanged(
const CoreAccountInfo& unconsented_primary_account_info) {
if (!base::FeatureList::IsEnabled(features::kAnimatedAvatarButtonOnSignIn))
return;
SetUserEmail(unconsented_primary_account_info.email);
OnUserIdentityChanged(unconsented_primary_account_info);
}
void AvatarToolbarButton::OnRefreshTokensLoaded() {
......@@ -340,9 +347,8 @@ void AvatarToolbarButton::OnRefreshTokensLoaded() {
GetProfileAttributesStorage(), profile_)) {
return;
}
SetUserEmail(IdentityManagerFactory::GetForProfile(profile_)
->GetUnconsentedPrimaryAccountInfo()
.email);
OnUserIdentityChanged(IdentityManagerFactory::GetForProfile(profile_)
->GetUnconsentedPrimaryAccountInfo());
}
void AvatarToolbarButton::OnAccountsInCookieUpdated(
......@@ -370,9 +376,10 @@ void AvatarToolbarButton::OnCreditCardSaved() {
ShowAvatarHighlightAnimation();
}
void AvatarToolbarButton::ExpandToShowEmail() {
DCHECK(user_email_.has_value());
DCHECK(!waiting_for_image_to_show_user_email_);
void AvatarToolbarButton::ShowIdentityAnimation() {
DCHECK_EQ(identity_animation_state_,
IdentityAnimationState::kWaitingForImage);
identity_animation_state_ = IdentityAnimationState::kShowing;
UpdateText();
......@@ -380,30 +387,30 @@ void AvatarToolbarButton::ExpandToShowEmail() {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(
&AvatarToolbarButton::ResetUserEmailWhenNotHoveredOrFocused,
&AvatarToolbarButton::HideIdentityAnimationWhenNotHoveredOrFocused,
weak_ptr_factory_.GetWeakPtr()),
kEmailExpansionDuration);
kIdentityAnimationDuration);
}
void AvatarToolbarButton::ResetUserEmailWhenNotHoveredOrFocused() {
void AvatarToolbarButton::HideIdentityAnimationWhenNotHoveredOrFocused() {
// No-op if it has been reset already.
if (!user_email_)
if (identity_animation_state_ == IdentityAnimationState::kNotShowing)
return;
// Keep email visible while hovering or being focused.
if (IsMouseHovered() || HasFocus()) {
// TODO(crbug.com/967317): Include also the case when some other button from
// the parent container is shown and hovered / focused.
should_reset_user_email_when_no_longer_hovered_or_focused_ = true;
identity_animation_state_ =
IdentityAnimationState::kShowingUntilNoLongerHoveredOrFocused;
return;
}
should_reset_user_email_when_no_longer_hovered_or_focused_ = false;
ResetUserEmail();
HideIdentityAnimation();
}
void AvatarToolbarButton::ResetUserEmail() {
DCHECK(user_email_.has_value());
user_email_ = base::nullopt;
void AvatarToolbarButton::HideIdentityAnimation() {
DCHECK_NE(identity_animation_state_, IdentityAnimationState::kNotShowing);
identity_animation_state_ = IdentityAnimationState::kNotShowing;
// Update the text to the pre-shown state. This also makes sure that we now
// reflect changes that happened while the identity pill was shown.
......@@ -418,8 +425,9 @@ base::string16 AvatarToolbarButton::GetAvatarTooltipText() const {
return l10n_util::GetStringUTF16(IDS_GUEST_PROFILE_NAME);
case State::kGenericProfile:
return l10n_util::GetStringUTF16(IDS_GENERIC_USER_AVATAR_LABEL);
case State::kAnimatedSignIn:
return base::UTF8ToUTF16(*user_email_);
case State::kAnimatedUserIdentity:
return signin_ui_util::GetShortProfileIdentityToDisplay(
*GetProfileAttributesEntry(profile_), profile_);
case State::kSyncError:
return l10n_util::GetStringFUTF16(IDS_AVATAR_BUTTON_SYNC_ERROR_TOOLTIP,
GetProfileName());
......@@ -459,7 +467,7 @@ gfx::ImageSkia AvatarToolbarButton::GetAvatarIcon(
case State::kGenericProfile:
return gfx::CreateVectorIcon(kUserAccountAvatarIcon, icon_size,
icon_color);
case State::kAnimatedSignIn:
case State::kAnimatedUserIdentity:
case State::kHighlightAnimation:
case State::kSyncError:
case State::kSyncPaused:
......@@ -534,8 +542,11 @@ AvatarToolbarButton::State AvatarToolbarButton::GetState() const {
return State::kGenericProfile;
}
if (user_email_.has_value() && !waiting_for_image_to_show_user_email_)
return State::kAnimatedSignIn;
if (identity_animation_state_ == IdentityAnimationState::kShowing ||
identity_animation_state_ ==
IdentityAnimationState::kShowingUntilNoLongerHoveredOrFocused) {
return State::kAnimatedUserIdentity;
}
if (highlight_animation_visible_)
return State::kHighlightAnimation;
......@@ -567,16 +578,16 @@ void AvatarToolbarButton::SetInsets() {
SetLayoutInsetDelta(layout_insets);
}
void AvatarToolbarButton::SetUserEmail(const std::string& user_email) {
void AvatarToolbarButton::OnUserIdentityChanged(
const CoreAccountInfo& user_identity) {
if (!base::FeatureList::IsEnabled(features::kAnimatedAvatarButton) ||
user_email.empty()) {
user_identity.IsEmpty()) {
return;
}
user_email_ = user_email;
// If we already have a gaia image, the pill will be immediately
// displayed by UpdateIcon().
waiting_for_image_to_show_user_email_ = true;
identity_animation_state_ = IdentityAnimationState::kWaitingForImage;
UpdateIcon();
}
......
......@@ -49,12 +49,19 @@ class AvatarToolbarButton : public ToolbarButton,
kGuestSession,
kGenericProfile,
kHighlightAnimation,
kAnimatedSignIn,
kAnimatedUserIdentity,
kSyncPaused,
kSyncError,
kNormal
};
enum class IdentityAnimationState {
kNotShowing,
kWaitingForImage,
kShowing,
kShowingUntilNoLongerHoveredOrFocused
};
// ToolbarButton:
void NotifyClick(const ui::Event& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
......@@ -96,9 +103,9 @@ class AvatarToolbarButton : public ToolbarButton,
// autofill::PersonalDataManagerObserver:
void OnCreditCardSaved() override;
void ExpandToShowEmail();
void ResetUserEmailWhenNotHoveredOrFocused();
void ResetUserEmail();
void ShowIdentityAnimation();
void HideIdentityAnimationWhenNotHoveredOrFocused();
void HideIdentityAnimation();
base::string16 GetAvatarTooltipText() const;
base::string16 GetProfileName() const;
......@@ -108,8 +115,8 @@ class AvatarToolbarButton : public ToolbarButton,
void SetInsets();
// Sets |user_email_| and initiates showing the email (if non-empty).
void SetUserEmail(const std::string& user_email);
// Initiates showing the identity |user_identity| (if non-empty).
void OnUserIdentityChanged(const CoreAccountInfo& user_identity);
void ShowHighlightAnimation();
void HideHighlightAnimation();
......@@ -130,13 +137,8 @@ class AvatarToolbarButton : public ToolbarButton,
// paused/error state.
bool autofill_icon_visible_ = false;
// The user email that we're currently showing in an animation or empty if no
// animation is in progress.
base::Optional<std::string> user_email_;
// We cannot show the animation before we fetch the new avatar.
bool waiting_for_image_to_show_user_email_ = false;
// We cannot hide the animation when the button is hovered or focused.
bool should_reset_user_email_when_no_longer_hovered_or_focused_ = false;
IdentityAnimationState identity_animation_state_ =
IdentityAnimationState::kNotShowing;
ScopedObserver<ProfileAttributesStorage, ProfileAttributesStorage::Observer>
profile_observer_{this};
......
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