Commit a67b0478 authored by Alex Ilin's avatar Alex Ilin Committed by Commit Bot

[Profile avatar] Update the default avatar to show profile color

This CL updates ProfileAttributesEntry::GetAvatarIcon() to return
a colored person outline icon for users with placeholder (=default)
avatars.

Bug: 1100835
Change-Id: I49c19e4af24da82e48161b4b2d609ede69b3eead
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2287314
Commit-Queue: Alex Ilin <alexilin@chromium.org>
Reviewed-by: default avatarEvan Stade <estade@chromium.org>
Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Auto-Submit: Jan Krcal <jkrcal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795425}
parent 7bf12bbe
......@@ -72,6 +72,7 @@ aggregate_vector_icons("chrome_vector_icons") {
"nfc.icon",
"overflow_chevron.icon",
"paintbrush.icon",
"person_outline_padded.icon",
"photo_camera.icon",
"picture_in_picture_control_background.icon",
"picture_in_picture_alt.icon",
......
// Copyright 2020 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.
// This differs from ic_person_outline in that it has a relatively larger
// padding.
CANVAS_DIMENSIONS, 22,
MOVE_TO, 11, 22,
R_CUBIC_TO, 6.08f, 0, 11, -4.92f, 11, -11,
CUBIC_TO_SHORTHAND, 17.08f, 0, 11, 0,
CUBIC_TO_SHORTHAND, 0, 4.93f, 0, 11,
R_CUBIC_TO, 0, 6.07f, 4.93f, 11, 11, 11,
CLOSE,
MOVE_TO, 11, 22,
R_CUBIC_TO, 6.08f, 0, 11, -4.92f, 11, -11,
CUBIC_TO_SHORTHAND, 17.08f, 0, 11, 0,
CUBIC_TO_SHORTHAND, 0, 4.93f, 0, 11,
R_CUBIC_TO, 0, 6.07f, 4.93f, 11, 11, 11,
CLOSE,
MOVE_TO, 11, 5.87f,
R_ARC_TO, 2.57f, 2.57f, 0, 1, 0, 0, 5.13f,
R_ARC_TO, 2.57f, 2.57f, 0, 0, 0, 0, -5.13f,
CLOSE,
R_MOVE_TO, 1.28f, 2.57f,
R_CUBIC_TO, 0, -0.71f, -0.58f, -1.28f, -1.28f, -1.28f,
R_CUBIC_TO, -0.7f, 0, -1.28f, 0.58f, -1.28f, 1.28f,
R_CUBIC_TO, 0, 0.7f, 0.58f, 1.28f, 1.28f, 1.28f,
R_CUBIC_TO, 0.71f, 0, 1.28f, -0.58f, 1.28f, -1.28f,
CLOSE,
R_MOVE_TO, 2.57f, 5.78f,
R_CUBIC_TO, -0.13f, -0.46f, -2.12f, -1.28f, -3.85f, -1.28f,
R_CUBIC_TO, -1.73f, 0, -3.72f, 0.83f, -3.85f, 1.29f,
R_V_LINE_TO, 0.64f,
R_H_LINE_TO, 7.7f,
R_V_LINE_TO, -0.64f,
CLOSE,
R_MOVE_TO, -8.98f, 0,
R_CUBIC_TO, 0, -1.71f, 3.42f, -2.57f, 5.13f, -2.57f,
R_CUBIC_TO, 1.71f, 0, 5.13f, 0.86f, 5.13f, 2.57f,
R_V_LINE_TO, 1.93f,
H_LINE_TO, 5.87f,
R_V_LINE_TO, -1.92f,
CLOSE
CANVAS_DIMENSIONS, 20,
MOVE_TO, 10, 20,
R_CUBIC_TO, 5.52f, 0, 10, -4.48f, 10, -10,
CUBIC_TO_SHORTHAND, 15.52f, 0, 10, 0,
CUBIC_TO_SHORTHAND, 0, 4.48f, 0, 10,
R_CUBIC_TO, 0, 5.52f, 4.48f, 10, 10, 10,
CLOSE,
MOVE_TO, 10, 20,
R_CUBIC_TO, 5.52f, 0, 10, -4.48f, 10, -10,
CUBIC_TO_SHORTHAND, 15.52f, 0, 10, 0,
CUBIC_TO_SHORTHAND, 0, 4.48f, 0, 10,
R_CUBIC_TO, 0, 5.52f, 4.48f, 10, 10, 10,
CLOSE,
MOVE_TO, 10, 5.33f,
R_ARC_TO, 2.33f, 2.33f, 0, 1, 0, 0, 4.67f,
R_ARC_TO, 2.33f, 2.33f, 0, 0, 0, 0, -4.66f,
CLOSE,
R_MOVE_TO, 1.17f, 2.33f,
ARC_TO, 1.17f, 1.17f, 0, 0, 0, 10, 6.5f,
R_ARC_TO, 1.17f, 1.17f, 0, 0, 0, -1.17f, 1.17f,
ARC_TO, 1.17f, 1.17f, 0, 0, 0, 10, 8.83f,
R_ARC_TO, 1.17f, 1.17f, 0, 0, 0, 1.17f, -1.17f,
CLOSE,
R_MOVE_TO, 2.33f, 5.25f,
R_CUBIC_TO, -0.12f, -0.41f, -1.92f, -1.17f, -3.5f, -1.17f,
R_CUBIC_TO, -1.58f, 0, -3.38f, 0.75f, -3.5f, 1.17f,
R_V_LINE_TO, 0.58f,
R_H_LINE_TO, 7,
R_V_LINE_TO, -0.58f,
CLOSE,
R_MOVE_TO, -8.17f, 0,
R_CUBIC_TO, 0, -1.55f, 3.11f, -2.33f, 4.67f, -2.33f,
R_CUBIC_TO, 1.56f, 0, 4.67f, 0.78f, 4.67f, 2.33f,
R_V_LINE_TO, 1.75f,
H_LINE_TO, 5.33f,
R_V_LINE_TO, -1.75f,
CLOSE
......@@ -11,10 +11,12 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/common/pref_names.h"
......@@ -26,6 +28,10 @@
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/native_theme/native_theme.h"
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
......@@ -89,6 +95,28 @@ int GetLowEntropyHashValue(const std::string& value) {
return base::PersistentHash(value) % kNumberOfLowEntropyHashValues;
}
class ImageWithBackgroundSource : public gfx::CanvasImageSource {
public:
ImageWithBackgroundSource(const gfx::ImageSkia& image, SkColor background)
: gfx::CanvasImageSource(image.size()),
image_(image),
background_(background) {}
~ImageWithBackgroundSource() override = default;
// gfx::CanvasImageSource override.
void Draw(gfx::Canvas* canvas) override {
canvas->DrawColor(background_);
canvas->DrawImageInt(image_, 0, 0);
}
private:
const gfx::ImageSkia image_;
const SkColor background_;
DISALLOW_COPY_AND_ASSIGN(ImageWithBackgroundSource);
};
} // namespace
bool ProfileThemeColors::operator==(const ProfileThemeColors& other) const {
......@@ -284,13 +312,21 @@ base::string16 ProfileAttributesEntry::GetUserName() const {
return GetString16(kUserNameKey);
}
const gfx::Image& ProfileAttributesEntry::GetAvatarIcon() const {
gfx::Image ProfileAttributesEntry::GetAvatarIcon(
int size_for_placeholder_avatar) const {
if (IsUsingGAIAPicture()) {
const gfx::Image* image = GetGAIAPicture();
if (image)
return *image;
}
// TODO(crbug.com/1100835): After launch, remove the treatment of placeholder
// avatars from GetHighResAvatar() and from any other places.
if (base::FeatureList::IsEnabled(features::kNewProfilePicker) &&
GetAvatarIconIndex() == profiles::GetPlaceholderAvatarIndex()) {
return GetPlaceholderAvatarIcon(size_for_placeholder_avatar);
}
#if !defined(OS_ANDROID)
// Use the high resolution version of the avatar if it exists. Mobile doesn't
// need the high resolution version so no need to fetch it.
......@@ -710,6 +746,18 @@ const gfx::Image* ProfileAttributesEntry::GetHighResAvatar() const {
image_path);
}
gfx::Image ProfileAttributesEntry::GetPlaceholderAvatarIcon(int size) const {
ProfileThemeColors colors = GetProfileThemeColors();
gfx::ImageSkia icon_without_background =
gfx::CreateVectorIcon(gfx::IconDescription(
kPersonOutlinePaddedIcon, size, colors.default_avatar_stroke_color));
gfx::ImageSkia icon_with_background(
std::make_unique<ImageWithBackgroundSource>(
icon_without_background, colors.default_avatar_fill_color),
size);
return gfx::Image(icon_with_background);
}
bool ProfileAttributesEntry::HasMultipleAccountNames() const {
// If the value is not set, GetBool() returns false.
return GetBool(kHasMultipleAccountNames);
......
......@@ -19,10 +19,7 @@
#include "base/time/time.h"
#include "base/values.h"
#include "third_party/skia/include/core/SkColor.h"
namespace gfx {
class Image;
}
#include "ui/gfx/image/image.h"
class PrefRegistrySimple;
class PrefService;
......@@ -86,9 +83,13 @@ class ProfileAttributesEntry {
// address used to sign in and the empty string for profiles that aren't
// signed in to chrome.
base::string16 GetUserName() const;
// Gets the icon used as this profile's avatar. This might not be the icon
// displayed in the UI if IsUsingGAIAPicture() is true.
const gfx::Image& GetAvatarIcon() const;
// Gets the icon used as this profile's avatar.
// TODO(crbug.com/1100835): Rename |size_for_placeholder_avatar| to |size| and
// make this function resize all avatars appropriately. Remove the default
// value of |size_for_placeholder_avatar| when all callsites pass some value.
// Consider adding a |shape| parameter and get rid of
// profiles::GetSizedAvatarIcon().
gfx::Image GetAvatarIcon(int size_for_placeholder_avatar = 74) const;
std::string GetLocalAuthCredentials() const;
std::string GetPasswordChangeDetectionToken() const;
// Returns true if the profile is currently running any background apps. Note
......@@ -245,6 +246,9 @@ class ProfileAttributesEntry {
// profile avatar.
const gfx::Image* GetHighResAvatar() const;
// Generates the colored placeholder avatar icon for the given |size|.
gfx::Image GetPlaceholderAvatarIcon(int size) const;
// Returns if this profile has accounts (signed-in or signed-out) with
// different account names. This is approximate as only a short hash of an
// account name is stored so there can be false negatives.
......
......@@ -751,9 +751,12 @@ TEST_F(ProfileAttributesStorageTest, DownloadHighResAvatarTest) {
entry->GetHighResAvatar());
// Since we are not using GAIA image, |GetAvatarIcon| should return the same
// image as |GetHighResAvatar| in desktop.
EXPECT_EQ(&storage()->cached_avatar_images_[icon_filename],
&entry->GetAvatarIcon());
// image as |GetHighResAvatar| in desktop. Since it returns a copy, the
// backing object needs to get checked.
const gfx::ImageSkia* avatar_icon = entry->GetAvatarIcon().ToImageSkia();
const gfx::ImageSkia* cached_icon =
storage()->cached_avatar_images_[icon_filename].ToImageSkia();
EXPECT_TRUE(avatar_icon->BackedBySameObjectAs(*cached_icon));
// Finish the async calls that save the image to the disk.
EXPECT_CALL(observer(), OnProfileHighResAvatarLoaded(profile_path)).Times(1);
......
......@@ -464,10 +464,18 @@ bool IsModernAvatarIconIndex(size_t icon_index) {
}
int GetPlaceholderAvatarIconResourceID() {
// TODO(crbug.com/1100835): Replace with the new icon. Consider coloring the
// icon (i.e. providing the image through
// ProfileAttributesEntry::GetAvatarIcon(), instead) which would require more
// refactoring.
return IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE;
}
std::string GetPlaceholderAvatarIconUrl() {
// TODO(crbug.com/1100835): Replace with the new icon. Consider coloring the
// icon (i.e. providing the image through
// ProfileAttributesEntry::GetAvatarIcon(), instead) which would require more
// refactoring.
return "chrome://theme/IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE";
}
......
......@@ -7,6 +7,7 @@
#include <vector>
#include "base/check.h"
#include "base/compiler_specific.h"
#include "base/feature_list.h"
#include "base/notreached.h"
#include "chrome/app/chrome_command_ids.h"
......@@ -281,16 +282,19 @@ ui::ImageModel AvatarToolbarButton::GetAvatarIcon(
case State::kGuestSession:
return profiles::GetGuestAvatar(icon_size);
case State::kGenericProfile:
return ui::ImageModel::FromVectorIcon(kUserAccountAvatarIcon, icon_color,
icon_size);
if (!base::FeatureList::IsEnabled(features::kNewProfilePicker)) {
return ui::ImageModel::FromVectorIcon(kUserAccountAvatarIcon,
icon_color, icon_size);
}
FALLTHROUGH;
case State::kAnimatedUserIdentity:
case State::kPasswordsOnlySyncError:
case State::kSyncError:
case State::kSyncPaused:
case State::kNormal:
return ui::ImageModel::FromImage(profiles::GetSizedAvatarIcon(
delegate_->GetProfileAvatarImage(gaia_account_image), true, icon_size,
icon_size, profiles::SHAPE_CIRCLE));
delegate_->GetProfileAvatarImage(gaia_account_image, icon_size), true,
icon_size, icon_size, profiles::SHAPE_CIRCLE));
}
NOTREACHED();
return ui::ImageModel();
......
......@@ -17,6 +17,7 @@
#include "chrome/browser/sync/sync_ui_util.h"
#include "chrome/browser/ui/browser_list.h"
#include "components/signin/public/identity_manager/consent_level.h"
#include "ui/base/resource/resource_bundle.h"
#if defined(OS_CHROMEOS)
#include "chromeos/constants/chromeos_features.h"
......@@ -55,11 +56,16 @@ bool IsGenericProfile(const ProfileAttributesEntry& entry) {
// Returns the avatar image for the current profile. May be called only in
// "normal" states where the user is guaranteed to have an avatar image (i.e.
// not kGenericProfile, not kGuestSession and not kIncognitoProfile).
const gfx::Image& GetAvatarImage(Profile* profile,
const gfx::Image& user_identity_image) {
// not kGuestSession and not kIncognitoProfile).
gfx::Image GetAvatarImage(Profile* profile,
const gfx::Image& user_identity_image,
int preferred_size) {
ProfileAttributesEntry* entry = GetProfileAttributesEntry(profile);
DCHECK(entry);
if (!entry) { // This can happen if the user deletes the current profile.
return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
profiles::GetPlaceholderAvatarIconResourceID());
}
// TODO(crbug.com/1012179): it should suffice to call entry->GetAvatarIcon().
// For this to work well, this class needs to observe ProfileAttributesStorage
// instead of (or on top of) IdentityManager. Only then we can rely on |entry|
......@@ -80,7 +86,7 @@ const gfx::Image& GetAvatarImage(Profile* profile,
return user_identity_image;
}
return entry->GetAvatarIcon();
return entry->GetAvatarIcon(preferred_size);
}
} // namespace
......@@ -148,8 +154,9 @@ gfx::Image AvatarToolbarButtonDelegate::GetGaiaAccountImage() const {
}
gfx::Image AvatarToolbarButtonDelegate::GetProfileAvatarImage(
gfx::Image gaia_account_image) const {
return GetAvatarImage(profile_, gaia_account_image);
gfx::Image gaia_account_image,
int preferred_size) const {
return GetAvatarImage(profile_, gaia_account_image, preferred_size);
}
int AvatarToolbarButtonDelegate::GetIncognitoWindowsCount() const {
......
......@@ -37,7 +37,8 @@ class AvatarToolbarButtonDelegate : public BrowserListObserver,
base::string16 GetProfileName() const;
base::string16 GetShortProfileName() const;
gfx::Image GetGaiaAccountImage() const;
gfx::Image GetProfileAvatarImage(gfx::Image gaia_account_image) const;
gfx::Image GetProfileAvatarImage(gfx::Image gaia_account_image,
int preferred_size) const;
// Returns the count of incognito windows attached to the profile.
int GetIncognitoWindowsCount() const;
......
......@@ -470,7 +470,8 @@ void ProfileMenuView::BuildIdentity() {
} else {
SetProfileIdentityInfo(
profile_name, background_color, edit_button_params,
ui::ImageModel::FromImage(profile_attributes->GetAvatarIcon()),
ui::ImageModel::FromImage(
profile_attributes->GetAvatarIcon(kIdentityImageSize)),
/*title=*/base::string16(),
l10n_util::GetStringUTF16(IDS_PROFILES_LOCAL_PROFILE_STATE));
}
......@@ -628,7 +629,8 @@ void ProfileMenuView::BuildSelectableProfiles() {
continue;
AddSelectableProfile(
ui::ImageModel::FromImage(profile_entry->GetAvatarIcon()),
ui::ImageModel::FromImage(
profile_entry->GetAvatarIcon(kSelectableProfileImageSize)),
profile_entry->GetName(),
/*is_guest=*/false,
base::BindRepeating(&ProfileMenuView::OnOtherProfileSelected,
......
......@@ -58,8 +58,7 @@ ProfileMenuViewBase* g_profile_bubble_ = nullptr;
// Helpers --------------------------------------------------------------------
constexpr int kMenuWidth = 288;
constexpr int kIdentityImageSize = 64;
constexpr int kMaxImageSize = kIdentityImageSize;
constexpr int kMaxImageSize = ProfileMenuViewBase::kIdentityImageSize;
constexpr int kDefaultMargin = 8;
constexpr int kBadgeSize = 16;
constexpr int kCircularImageButtonSize = 28;
......@@ -260,7 +259,7 @@ class AvatarImageView : public views::ImageView {
// is no image, or in tests.
avatar_image_ = ui::ImageModel::FromVectorIcon(
kUserAccountAvatarIcon, ui::NativeTheme::kColorId_MenuIconColor,
kIdentityImageSize);
ProfileMenuViewBase::kIdentityImageSize);
}
}
......@@ -270,7 +269,8 @@ class AvatarImageView : public views::ImageView {
constexpr int kBadgePadding = 1;
DCHECK(!avatar_image_.IsEmpty());
gfx::ImageSkia sized_avatar_image =
SizeImageModel(avatar_image_, GetNativeTheme(), kIdentityImageSize);
SizeImageModel(avatar_image_, GetNativeTheme(),
ProfileMenuViewBase::kIdentityImageSize);
const SkColor background_color = GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_BubbleBackground);
......@@ -368,7 +368,9 @@ void BuildProfileBackgroundContainer(
// The bottom background edge should match the center of the identity image.
gfx::Insets background_insets(
0, 0,
/*bottom=*/kIdentityImageSize / 2 + kAvatarImageViewBottomMargin, 0);
/*bottom=*/ProfileMenuViewBase::kIdentityImageSize / 2 +
kAvatarImageViewBottomMargin,
0);
profile_background_container->SetBackground(
views::CreateBackgroundFromPainter(
views::Painter::CreateSolidRoundRectPainter(
......@@ -744,8 +746,6 @@ void ProfileMenuViewBase::AddSelectableProfile(
const base::string16& name,
bool is_guest,
base::RepeatingClosure action) {
constexpr int kImageSize = 20;
// Initialize layout if this is the first time a button is added.
if (!selectable_profiles_container_->GetLayoutManager()) {
selectable_profiles_container_->SetLayoutManager(
......@@ -754,8 +754,8 @@ void ProfileMenuViewBase::AddSelectableProfile(
}
DCHECK(!image_model.IsEmpty());
gfx::ImageSkia sized_image =
SizeImageModel(image_model, GetNativeTheme(), kImageSize);
gfx::ImageSkia sized_image = SizeImageModel(image_model, GetNativeTheme(),
kSelectableProfileImageSize);
views::Button* button = selectable_profiles_container_->AddChildView(
std::make_unique<HoverButton>(this, sized_image, name));
......
......@@ -91,6 +91,11 @@ class ProfileMenuViewBase : public content::WebContentsDelegate,
base::RepeatingClosure edit_action;
};
// Size of the large identity image in the menu.
static constexpr int kIdentityImageSize = 64;
// Size of the small identity images for other selectable profiles.
static constexpr int kSelectableProfileImageSize = 20;
// Shows the bubble if one is not already showing. This allows us to easily
// make a button toggle the bubble on and off when clicked: we unconditionally
// call this function when the button is clicked and if the bubble isn't
......
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