| // Copyright 2014 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/profiles/profile_menu_view.h" |
| |
| #include <algorithm> |
| #include <string> |
| #include <utility> |
| |
| #include "base/feature_list.h" |
| #include "base/macros.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/metrics/user_metrics.h" |
| #include "build/branding_buildflags.h" |
| #include "build/build_config.h" |
| #include "build/chromeos_buildflags.h" |
| #include "chrome/app/vector_icons/vector_icons.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/lifetime/application_lifetime.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profile_avatar_icon_util.h" |
| #include "chrome/browser/profiles/profile_metrics.h" |
| #include "chrome/browser/profiles/profiles_state.h" |
| #include "chrome/browser/signin/account_consistency_mode_manager.h" |
| #include "chrome/browser/signin/chrome_signin_client_factory.h" |
| #include "chrome/browser/signin/identity_manager_factory.h" |
| #include "chrome/browser/signin/signin_error_controller_factory.h" |
| #include "chrome/browser/signin/signin_ui_util.h" |
| #include "chrome/browser/sync/profile_sync_service_factory.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_commands.h" |
| #include "chrome/browser/ui/browser_dialogs.h" |
| #include "chrome/browser/ui/browser_finder.h" |
| #include "chrome/browser/ui/browser_list.h" |
| #include "chrome/browser/ui/browser_navigator_params.h" |
| #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" |
| #include "chrome/browser/ui/signin/profile_colors_util.h" |
| #include "chrome/browser/ui/sync/sync_promo_ui.h" |
| #include "chrome/browser/ui/ui_features.h" |
| #include "chrome/browser/ui/views/accessibility/non_accessible_image_view.h" |
| #include "chrome/browser/ui/views/chrome_layout_provider.h" |
| #include "chrome/browser/ui/views/chrome_typography.h" |
| #include "chrome/browser/ui/views/hover_button.h" |
| #include "chrome/browser/ui/views/profiles/badged_profile_photo.h" |
| #include "chrome/browser/ui/views/profiles/user_manager_view.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/grit/chromium_strings.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "chrome/grit/theme_resources.h" |
| #include "components/signin/core/browser/signin_error_controller.h" |
| #include "components/signin/public/base/signin_pref_names.h" |
| #include "components/signin/public/identity_manager/consent_level.h" |
| #include "components/signin/public/identity_manager/primary_account_mutator.h" |
| #include "components/strings/grit/components_strings.h" |
| #include "components/vector_icons/vector_icons.h" |
| #include "net/base/url_util.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/gfx/image/canvas_image_source.h" |
| #include "ui/gfx/image/image_skia_operations.h" |
| #include "ui/native_theme/native_theme.h" |
| #include "ui/strings/grit/ui_strings.h" |
| #include "ui/views/accessibility/view_accessibility.h" |
| |
| namespace { |
| |
| // Helpers -------------------------------------------------------------------- |
| |
| // Most error cases get displayed the same way, only the button string changes. |
| ProfileMenuViewBase::SyncInfo GetStandardSyncErrorInfo(int button_string_id) { |
| return {IDS_SYNC_ERROR_USER_MENU_TITLE, button_string_id, |
| ProfileMenuViewBase::SyncInfoContainerBackgroundState::kError}; |
| } |
| |
| ProfileMenuViewBase::SyncInfo GetSyncInfoForAvatarErrorType( |
| sync_ui_util::AvatarSyncErrorType error) { |
| switch (error) { |
| case sync_ui_util::NO_SYNC_ERROR: |
| return {IDS_SETTINGS_EMPTY_STRING, IDS_PROFILES_OPEN_SYNC_SETTINGS_BUTTON, |
| ProfileMenuViewBase::SyncInfoContainerBackgroundState::kNoError}; |
| case sync_ui_util::AUTH_ERROR: |
| // Sync paused. The user can reauth to resolve the signin error. |
| return {IDS_PROFILES_DICE_SYNC_PAUSED_TITLE, |
| IDS_SYNC_ERROR_USER_MENU_SIGNIN_BUTTON, |
| ProfileMenuViewBase::SyncInfoContainerBackgroundState::kPaused}; |
| case sync_ui_util::MANAGED_USER_UNRECOVERABLE_ERROR: |
| // For a managed user, the user is directed to the signout confirmation |
| // dialogue in the settings page. |
| return GetStandardSyncErrorInfo(IDS_SYNC_ERROR_USER_MENU_SIGNOUT_BUTTON); |
| case sync_ui_util::UNRECOVERABLE_ERROR: |
| // For a non-managed user, we sign out on the user's behalf and prompt the |
| // user to sign in again. |
| return GetStandardSyncErrorInfo( |
| IDS_SYNC_ERROR_USER_MENU_SIGNIN_AGAIN_BUTTON); |
| case sync_ui_util::UPGRADE_CLIENT_ERROR: |
| return GetStandardSyncErrorInfo(IDS_SYNC_ERROR_USER_MENU_UPGRADE_BUTTON); |
| case sync_ui_util::PASSPHRASE_ERROR: |
| return GetStandardSyncErrorInfo( |
| IDS_SYNC_ERROR_USER_MENU_PASSPHRASE_BUTTON); |
| case sync_ui_util::TRUSTED_VAULT_KEY_MISSING_FOR_EVERYTHING_ERROR: |
| return GetStandardSyncErrorInfo( |
| IDS_SYNC_ERROR_USER_MENU_RETRIEVE_KEYS_BUTTON); |
| case sync_ui_util::TRUSTED_VAULT_KEY_MISSING_FOR_PASSWORDS_ERROR: |
| return {IDS_SYNC_ERROR_PASSWORDS_USER_MENU_TITLE, |
| IDS_SYNC_ERROR_USER_MENU_RETRIEVE_KEYS_BUTTON, |
| ProfileMenuViewBase::SyncInfoContainerBackgroundState::kError}; |
| case sync_ui_util:: |
| TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING_ERROR: |
| return { |
| IDS_SYNC_ERROR_RECOVERABILITY_DEGRADED_FOR_EVERYTHING_USER_MENU_TITLE, |
| IDS_SYNC_ERROR_USER_MENU_RECOVERABILITY_BUTTON, |
| ProfileMenuViewBase::SyncInfoContainerBackgroundState::kError}; |
| case sync_ui_util:: |
| TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS_ERROR: |
| return { |
| IDS_SYNC_ERROR_RECOVERABILITY_DEGRADED_FOR_PASSWORDS_USER_MENU_TITLE, |
| IDS_SYNC_ERROR_USER_MENU_RECOVERABILITY_BUTTON, |
| ProfileMenuViewBase::SyncInfoContainerBackgroundState::kError}; |
| case sync_ui_util::SETTINGS_UNCONFIRMED_ERROR: |
| return GetStandardSyncErrorInfo( |
| IDS_SYNC_ERROR_USER_MENU_CONFIRM_SYNC_SETTINGS_BUTTON); |
| } |
| |
| NOTREACHED(); |
| return {IDS_SETTINGS_EMPTY_STRING, IDS_SETTINGS_EMPTY_STRING, |
| ProfileMenuViewBase::SyncInfoContainerBackgroundState::kNoError}; |
| } |
| |
| ProfileAttributesEntry* GetProfileAttributesEntry(Profile* profile) { |
| ProfileAttributesEntry* entry; |
| CHECK(g_browser_process->profile_manager() |
| ->GetProfileAttributesStorage() |
| .GetProfileAttributesWithPath(profile->GetPath(), &entry)); |
| return entry; |
| } |
| |
| void NavigateToGoogleAccountPage(Profile* profile, const std::string& email) { |
| // Create a URL so that the account chooser is shown if the account with |
| // |email| is not signed into the web. Include a UTM parameter to signal the |
| // source of the navigation. |
| GURL google_account = net::AppendQueryParameter( |
| GURL(chrome::kGoogleAccountURL), "utm_source", "chrome-profile-chooser"); |
| |
| GURL url(chrome::kGoogleAccountChooserURL); |
| url = net::AppendQueryParameter(url, "Email", email); |
| url = net::AppendQueryParameter(url, "continue", google_account.spec()); |
| |
| NavigateParams params(profile, url, ui::PAGE_TRANSITION_LINK); |
| params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; |
| Navigate(¶ms); |
| } |
| |
| // Returns the number of browsers associated with |profile|. |
| // Note: For regular profiles this includes incognito sessions. |
| int CountBrowsersFor(Profile* profile) { |
| int browser_count = chrome::GetBrowserCount(profile); |
| if (!profile->IsOffTheRecord() && profile->HasPrimaryOTRProfile()) |
| browser_count += chrome::GetBrowserCount(profile->GetPrimaryOTRProfile()); |
| return browser_count; |
| } |
| |
| bool IsSyncPaused(Profile* profile) { |
| return sync_ui_util::GetAvatarSyncErrorType(profile) == |
| sync_ui_util::AUTH_ERROR; |
| } |
| |
| // TODO(crbug.com/1125474): Replace IsGuest(profile) calls with |
| // Profile::IsGuestProfile() after IsEphemeralGuestProfile is fully migrated. |
| bool IsGuest(Profile* profile) { |
| return profile->IsGuestSession() || profile->IsEphemeralGuestProfile(); |
| } |
| |
| bool UseNewPicker() { |
| return base::FeatureList::IsEnabled(features::kNewProfilePicker); |
| } |
| |
| } // namespace |
| |
| // ProfileMenuView --------------------------------------------------------- |
| |
| // static |
| bool ProfileMenuView::close_on_deactivate_for_testing_ = true; |
| |
| ProfileMenuView::ProfileMenuView(views::Button* anchor_button, Browser* browser) |
| : ProfileMenuViewBase(anchor_button, browser) { |
| chrome::RecordDialogCreation(chrome::DialogIdentifier::PROFILE_CHOOSER); |
| set_close_on_deactivate(close_on_deactivate_for_testing_); |
| } |
| |
| ProfileMenuView::~ProfileMenuView() = default; |
| |
| void ProfileMenuView::BuildMenu() { |
| Profile* profile = browser()->profile(); |
| if (IsGuest(profile)) { |
| BuildGuestIdentity(); |
| } else if (profile->IsRegularProfile()) { |
| BuildIdentity(); |
| BuildSyncInfo(); |
| BuildAutofillButtons(); |
| } else { |
| NOTREACHED(); |
| } |
| |
| BuildFeatureButtons(); |
| |
| // ChromeOS doesn't support multi-profile. |
| #if !BUILDFLAG(IS_CHROMEOS_ASH) |
| if (!(IsGuest(profile) && |
| base::FeatureList::IsEnabled(features::kNewProfilePicker))) { |
| BuildProfileManagementHeading(); |
| BuildSelectableProfiles(); |
| BuildProfileManagementFeatureButtons(); |
| } |
| #endif |
| } |
| |
| gfx::ImageSkia ProfileMenuView::GetSyncIcon() const { |
| Profile* profile = browser()->profile(); |
| |
| if (!profile->IsRegularProfile()) |
| return gfx::ImageSkia(); |
| |
| if (!IdentityManagerFactory::GetForProfile(profile)->HasPrimaryAccount()) |
| return ColoredImageForMenu(kSyncPausedCircleIcon, gfx::kGoogleGrey500); |
| |
| const gfx::VectorIcon* icon = nullptr; |
| ui::NativeTheme::ColorId color_id; |
| switch (sync_ui_util::GetAvatarSyncErrorType(profile)) { |
| case sync_ui_util::NO_SYNC_ERROR: |
| icon = &kSyncCircleIcon; |
| color_id = ui::NativeTheme::kColorId_AlertSeverityLow; |
| break; |
| case sync_ui_util::AUTH_ERROR: |
| icon = &kSyncPausedCircleIcon; |
| color_id = ui::NativeTheme::kColorId_ProminentButtonColor; |
| break; |
| case sync_ui_util::MANAGED_USER_UNRECOVERABLE_ERROR: |
| case sync_ui_util::UNRECOVERABLE_ERROR: |
| case sync_ui_util::UPGRADE_CLIENT_ERROR: |
| case sync_ui_util::PASSPHRASE_ERROR: |
| case sync_ui_util::TRUSTED_VAULT_KEY_MISSING_FOR_EVERYTHING_ERROR: |
| case sync_ui_util::TRUSTED_VAULT_KEY_MISSING_FOR_PASSWORDS_ERROR: |
| case sync_ui_util:: |
| TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING_ERROR: |
| case sync_ui_util:: |
| TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS_ERROR: |
| case sync_ui_util::SETTINGS_UNCONFIRMED_ERROR: |
| icon = &kSyncPausedCircleIcon; |
| color_id = ui::NativeTheme::kColorId_AlertSeverityHigh; |
| break; |
| } |
| const SkColor image_color = GetNativeTheme()->GetSystemColor(color_id); |
| return ColoredImageForMenu(*icon, image_color); |
| } |
| |
| base::string16 ProfileMenuView::GetAccessibleWindowTitle() const { |
| base::string16 title = |
| l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_BUBBLE_ACCESSIBLE_TITLE); |
| |
| if (!menu_title_.empty()) { |
| title = l10n_util::GetStringFUTF16(IDS_CONCAT_TWO_STRINGS_WITH_COMMA, title, |
| menu_title_); |
| } |
| if (!menu_subtitle_.empty()) { |
| title = l10n_util::GetStringFUTF16(IDS_CONCAT_TWO_STRINGS_WITH_COMMA, title, |
| menu_subtitle_); |
| } |
| return title; |
| } |
| |
| void ProfileMenuView::OnManageGoogleAccountButtonClicked() { |
| RecordClick(ActionableItem::kManageGoogleAccountButton); |
| if (!perform_menu_actions()) |
| return; |
| |
| Profile* profile = browser()->profile(); |
| signin::IdentityManager* identity_manager = |
| IdentityManagerFactory::GetForProfile(profile); |
| DCHECK( |
| identity_manager->HasPrimaryAccount(signin::ConsentLevel::kNotRequired)); |
| NavigateToGoogleAccountPage( |
| profile, identity_manager |
| ->GetPrimaryAccountInfo(signin::ConsentLevel::kNotRequired) |
| .email); |
| } |
| |
| void ProfileMenuView::OnPasswordsButtonClicked() { |
| RecordClick(ActionableItem::kPasswordsButton); |
| if (!perform_menu_actions()) |
| return; |
| NavigateToManagePasswordsPage( |
| browser(), password_manager::ManagePasswordsReferrer::kProfileChooser); |
| } |
| |
| void ProfileMenuView::OnCreditCardsButtonClicked() { |
| RecordClick(ActionableItem::kCreditCardsButton); |
| if (!perform_menu_actions()) |
| return; |
| chrome::ShowSettingsSubPage(browser(), chrome::kPaymentsSubPage); |
| } |
| |
| void ProfileMenuView::OnAddressesButtonClicked() { |
| RecordClick(ActionableItem::kAddressesButton); |
| if (!perform_menu_actions()) |
| return; |
| chrome::ShowSettingsSubPage(browser(), chrome::kAddressesSubPage); |
| } |
| |
| void ProfileMenuView::OnGuestProfileButtonClicked() { |
| RecordClick(ActionableItem::kGuestProfileButton); |
| if (!perform_menu_actions()) |
| return; |
| PrefService* service = g_browser_process->local_state(); |
| DCHECK(service); |
| DCHECK(service->GetBoolean(prefs::kBrowserGuestModeEnabled)); |
| profiles::SwitchToGuestProfile(ProfileManager::CreateCallback()); |
| } |
| |
| void ProfileMenuView::OnExitProfileButtonClicked() { |
| RecordClick(ActionableItem::kExitProfileButton); |
| if (!perform_menu_actions()) |
| return; |
| profiles::CloseProfileWindows(browser()->profile()); |
| } |
| |
| void ProfileMenuView::OnSyncSettingsButtonClicked() { |
| RecordClick(ActionableItem::kSyncSettingsButton); |
| if (!perform_menu_actions()) |
| return; |
| chrome::ShowSettingsSubPage(browser(), chrome::kSyncSetupSubPage); |
| } |
| |
| void ProfileMenuView::OnSyncErrorButtonClicked( |
| sync_ui_util::AvatarSyncErrorType error) { |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| // On ChromeOS, sync errors are fixed by re-signing into the OS. |
| chrome::AttemptUserExit(); |
| #else |
| RecordClick(ActionableItem::kSyncErrorButton); |
| if (!perform_menu_actions()) |
| return; |
| |
| // The logic below must be consistent with GetSyncInfoForAvatarErrorType(). |
| switch (error) { |
| case sync_ui_util::MANAGED_USER_UNRECOVERABLE_ERROR: |
| chrome::ShowSettingsSubPage(browser(), chrome::kSignOutSubPage); |
| break; |
| case sync_ui_util::UNRECOVERABLE_ERROR: |
| // GetPrimaryAccountMutator() might return nullptr on some platforms. |
| if (auto* account_mutator = |
| IdentityManagerFactory::GetForProfile(browser()->profile()) |
| ->GetPrimaryAccountMutator()) { |
| account_mutator->RevokeSyncConsent( |
| signin_metrics::USER_CLICKED_SIGNOUT_SETTINGS, |
| signin_metrics::SignoutDelete::IGNORE_METRIC); |
| Hide(); |
| browser()->signin_view_controller()->ShowSignin( |
| profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN, |
| signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN); |
| } |
| break; |
| case sync_ui_util::AUTH_ERROR: |
| Hide(); |
| browser()->signin_view_controller()->ShowSignin( |
| profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH, |
| signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN); |
| break; |
| case sync_ui_util::UPGRADE_CLIENT_ERROR: |
| chrome::OpenUpdateChromeDialog(browser()); |
| break; |
| case sync_ui_util::TRUSTED_VAULT_KEY_MISSING_FOR_EVERYTHING_ERROR: |
| case sync_ui_util::TRUSTED_VAULT_KEY_MISSING_FOR_PASSWORDS_ERROR: |
| sync_ui_util::OpenTabForSyncKeyRetrieval( |
| browser(), syncer::KeyRetrievalTriggerForUMA::kProfileMenu); |
| break; |
| case sync_ui_util:: |
| TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING_ERROR: |
| case sync_ui_util:: |
| TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS_ERROR: |
| // TODO(crbug.com/1081649): This should use a dedicated function. |
| sync_ui_util::OpenTabForSyncKeyRetrieval( |
| browser(), syncer::KeyRetrievalTriggerForUMA::kProfileMenu); |
| break; |
| case sync_ui_util::PASSPHRASE_ERROR: |
| case sync_ui_util::SETTINGS_UNCONFIRMED_ERROR: |
| chrome::ShowSettingsSubPage(browser(), chrome::kSyncSetupSubPage); |
| break; |
| case sync_ui_util::NO_SYNC_ERROR: |
| NOTREACHED(); |
| break; |
| } |
| #endif |
| } |
| |
| void ProfileMenuView::OnSigninAccountButtonClicked(AccountInfo account) { |
| RecordClick(ActionableItem::kSigninAccountButton); |
| if (!perform_menu_actions()) |
| return; |
| Hide(); |
| signin_ui_util::EnableSyncFromSingleAccountPromo( |
| browser(), account, |
| signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN); |
| } |
| |
| #if !BUILDFLAG(IS_CHROMEOS_ASH) |
| void ProfileMenuView::OnSignoutButtonClicked() { |
| RecordClick(ActionableItem::kSignoutButton); |
| if (!perform_menu_actions()) |
| return; |
| Hide(); |
| // Sign out from all accounts. |
| browser()->signin_view_controller()->ShowGaiaLogoutTab( |
| signin_metrics::SourceForRefreshTokenOperation:: |
| kUserMenu_SignOutAllAccounts); |
| } |
| |
| void ProfileMenuView::OnSigninButtonClicked() { |
| RecordClick(ActionableItem::kSigninButton); |
| if (!perform_menu_actions()) |
| return; |
| Hide(); |
| browser()->signin_view_controller()->ShowSignin( |
| profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN, |
| signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN); |
| } |
| |
| void ProfileMenuView::OnOtherProfileSelected( |
| const base::FilePath& profile_path) { |
| RecordClick(ActionableItem::kOtherProfileButton); |
| if (!perform_menu_actions()) |
| return; |
| Hide(); |
| profiles::SwitchToProfile(profile_path, /*always_create=*/false, |
| ProfileManager::CreateCallback()); |
| } |
| |
| void ProfileMenuView::OnAddNewProfileButtonClicked() { |
| RecordClick(ActionableItem::kAddNewProfileButton); |
| if (!perform_menu_actions()) |
| return; |
| UserManager::Show(/*profile_path_to_focus=*/base::FilePath(), |
| profiles::USER_MANAGER_OPEN_CREATE_USER_PAGE); |
| } |
| |
| void ProfileMenuView::OnManageProfilesButtonClicked() { |
| RecordClick(ActionableItem::kManageProfilesButton); |
| if (!perform_menu_actions()) |
| return; |
| UserManager::Show(base::FilePath(), |
| profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION); |
| } |
| |
| void ProfileMenuView::OnEditProfileButtonClicked() { |
| RecordClick(ActionableItem::kEditProfileButton); |
| if (!perform_menu_actions()) |
| return; |
| chrome::ShowSettingsSubPage(browser(), chrome::kManageProfileSubPage); |
| } |
| #endif // BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| void ProfileMenuView::OnCookiesClearedOnExitLinkClicked() { |
| RecordClick(ActionableItem::kCookiesClearedOnExitLink); |
| if (!perform_menu_actions()) |
| return; |
| chrome::ShowSettingsSubPage(browser(), chrome::kContentSettingsSubPage + |
| std::string("/") + |
| chrome::kCookieSettingsSubPage); |
| } |
| |
| void ProfileMenuView::BuildIdentity() { |
| Profile* profile = browser()->profile(); |
| signin::IdentityManager* identity_manager = |
| IdentityManagerFactory::GetForProfile(profile); |
| CoreAccountInfo account = identity_manager->GetPrimaryAccountInfo( |
| signin::ConsentLevel::kNotRequired); |
| base::Optional<AccountInfo> account_info = |
| identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken( |
| account); |
| ProfileAttributesEntry* profile_attributes = |
| GetProfileAttributesEntry(profile); |
| |
| base::string16 profile_name; |
| base::Optional<EditButtonParams> edit_button_params; |
| // Profile names are not supported on ChromeOS. |
| #if !BUILDFLAG(IS_CHROMEOS_ASH) |
| size_t num_of_profiles = |
| g_browser_process->profile_manager()->GetNumberOfProfiles(); |
| if (num_of_profiles > 1 || !profile_attributes->IsUsingDefaultName() || |
| base::FeatureList::IsEnabled(features::kNewProfilePicker)) { |
| profile_name = profile_attributes->GetLocalProfileName(); |
| edit_button_params = EditButtonParams( |
| &vector_icons::kEditIcon, |
| UseNewPicker() ? l10n_util::GetStringUTF16( |
| IDS_PROFILES_CUSTOMIZE_PROFILE_BUTTON_TOOLTIP) |
| : l10n_util::GetStringUTF16(IDS_SETTINGS_EDIT_PERSON), |
| base::BindRepeating(&ProfileMenuView::OnEditProfileButtonClicked, |
| base::Unretained(this))); |
| } |
| #endif |
| |
| SkColor background_color = |
| profile_attributes->GetProfileThemeColors().profile_highlight_color; |
| if (account_info.has_value()) { |
| menu_title_ = base::UTF8ToUTF16(account_info.value().full_name); |
| menu_subtitle_ = |
| IsSyncPaused(profile) |
| ? l10n_util::GetStringUTF16(IDS_PROFILES_LOCAL_PROFILE_STATE) |
| : base::UTF8ToUTF16(account_info.value().email); |
| SetProfileIdentityInfo( |
| profile_name, background_color, edit_button_params, |
| ui::ImageModel::FromImage(account_info.value().account_image), |
| menu_title_, menu_subtitle_); |
| } else { |
| menu_title_ = base::string16(); |
| menu_subtitle_ = |
| l10n_util::GetStringUTF16(IDS_PROFILES_LOCAL_PROFILE_STATE); |
| SetProfileIdentityInfo( |
| profile_name, background_color, edit_button_params, |
| ui::ImageModel::FromImage( |
| profile_attributes->GetAvatarIcon(kIdentityImageSize)), |
| menu_title_, menu_subtitle_); |
| } |
| } |
| |
| void ProfileMenuView::BuildGuestIdentity() { |
| int guest_window_count = BrowserList::GetGuestBrowserCount(); |
| |
| menu_title_ = l10n_util::GetStringUTF16(IDS_GUEST_PROFILE_NAME); |
| menu_subtitle_ = base::string16(); |
| if (guest_window_count > 1 && |
| base::FeatureList::IsEnabled(features::kNewProfilePicker)) { |
| menu_subtitle_ = l10n_util::GetPluralStringFUTF16( |
| IDS_GUEST_WINDOW_COUNT_MESSAGE, guest_window_count); |
| } |
| |
| ui::ThemedVectorIcon header_art_icon( |
| &kGuestMenuArtIcon, ui::NativeTheme::kColorId_AvatarHeaderArt); |
| SetProfileIdentityInfo( |
| /*profile_name=*/base::string16(), |
| /*background_color=*/SK_ColorTRANSPARENT, |
| /*edit_button=*/base::nullopt, profiles::GetGuestAvatar(), menu_title_, |
| menu_subtitle_, header_art_icon); |
| } |
| |
| void ProfileMenuView::BuildAutofillButtons() { |
| AddShortcutFeatureButton( |
| kKeyIcon, l10n_util::GetStringUTF16(IDS_PROFILES_PASSWORDS_LINK), |
| base::BindRepeating(&ProfileMenuView::OnPasswordsButtonClicked, |
| base::Unretained(this))); |
| |
| AddShortcutFeatureButton( |
| kCreditCardIcon, |
| l10n_util::GetStringUTF16(IDS_PROFILES_CREDIT_CARDS_LINK), |
| base::BindRepeating(&ProfileMenuView::OnCreditCardsButtonClicked, |
| base::Unretained(this))); |
| |
| AddShortcutFeatureButton( |
| vector_icons::kLocationOnIcon, |
| l10n_util::GetStringUTF16(IDS_PROFILES_ADDRESSES_LINK), |
| base::BindRepeating(&ProfileMenuView::OnAddressesButtonClicked, |
| base::Unretained(this))); |
| } |
| |
| void ProfileMenuView::BuildSyncInfo() { |
| Profile* profile = browser()->profile(); |
| // Only show the sync info if signin and sync are allowed. |
| if (!profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed) || |
| !ProfileSyncServiceFactory::IsSyncAllowed(profile)) { |
| return; |
| } |
| |
| signin::IdentityManager* identity_manager = |
| IdentityManagerFactory::GetForProfile(profile); |
| |
| if (identity_manager->HasPrimaryAccount()) { |
| // Show sync state. |
| const sync_ui_util::AvatarSyncErrorType error = |
| sync_ui_util::GetAvatarSyncErrorType(browser()->profile()); |
| |
| const base::RepeatingClosure action = |
| error == sync_ui_util::NO_SYNC_ERROR |
| ? base::BindRepeating(&ProfileMenuView::OnSyncSettingsButtonClicked, |
| base::Unretained(this)) |
| : base::BindRepeating(&ProfileMenuView::OnSyncErrorButtonClicked, |
| base::Unretained(this), error); |
| SetSyncInfo(GetSyncInfoForAvatarErrorType(error), action, |
| /*show_badge=*/true); |
| |
| return; |
| } |
| |
| // Show sync promos. |
| CoreAccountInfo unconsented_account = identity_manager->GetPrimaryAccountInfo( |
| signin::ConsentLevel::kNotRequired); |
| base::Optional<AccountInfo> account_info = |
| identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken( |
| unconsented_account); |
| |
| if (account_info.has_value()) { |
| SetSyncInfo( |
| {IDS_PROFILES_DICE_NOT_SYNCING_TITLE, IDS_PROFILES_DICE_SIGNIN_BUTTON, |
| SyncInfoContainerBackgroundState::kNoPrimaryAccount}, |
| base::BindRepeating(&ProfileMenuView::OnSigninAccountButtonClicked, |
| base::Unretained(this), account_info.value()), |
| /*show_badge=*/true); |
| } else { |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| // There is always an account on ChromeOS. |
| NOTREACHED(); |
| #else |
| SetSyncInfo({IDS_PROFILES_DICE_SYNC_PROMO, IDS_PROFILES_DICE_SIGNIN_BUTTON, |
| SyncInfoContainerBackgroundState::kNoPrimaryAccount}, |
| base::BindRepeating(&ProfileMenuView::OnSigninButtonClicked, |
| base::Unretained(this)), |
| /*show_badge=*/false); |
| #endif |
| } |
| } |
| |
| void ProfileMenuView::BuildFeatureButtons() { |
| Profile* profile = browser()->profile(); |
| signin::IdentityManager* identity_manager = |
| IdentityManagerFactory::GetForProfile(profile); |
| const bool has_unconsented_account = |
| !IsGuest(profile) && |
| identity_manager->HasPrimaryAccount(signin::ConsentLevel::kNotRequired); |
| |
| if (has_unconsented_account && !IsSyncPaused(profile)) { |
| #if BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| // The Google G icon needs to be shrunk, so it won't look too big compared |
| // to the other icons. |
| AddFeatureButton( |
| l10n_util::GetStringUTF16(IDS_SETTINGS_MANAGE_GOOGLE_ACCOUNT), |
| base::BindRepeating( |
| &ProfileMenuView::OnManageGoogleAccountButtonClicked, |
| base::Unretained(this)), |
| kGoogleGLogoIcon, |
| /*icon_to_image_ratio=*/0.75f); |
| #else |
| AddFeatureButton( |
| l10n_util::GetStringUTF16(IDS_SETTINGS_MANAGE_GOOGLE_ACCOUNT), |
| base::BindRepeating( |
| &ProfileMenuView::OnManageGoogleAccountButtonClicked, |
| base::Unretained(this))); |
| #endif |
| } |
| |
| int window_count = CountBrowsersFor(profile); |
| if (base::FeatureList::IsEnabled(features::kNewProfilePicker) && |
| IsGuest(profile)) { |
| AddFeatureButton( |
| l10n_util::GetPluralStringFUTF16(IDS_GUEST_PROFILE_MENU_CLOSE_BUTTON, |
| window_count), |
| base::BindRepeating(&ProfileMenuView::OnExitProfileButtonClicked, |
| base::Unretained(this)), |
| vector_icons::kCloseIcon); |
| } else { |
| if (window_count > 1) { |
| AddFeatureButton( |
| l10n_util::GetPluralStringFUTF16(IDS_PROFILES_CLOSE_X_WINDOWS_BUTTON, |
| window_count), |
| base::BindRepeating(&ProfileMenuView::OnExitProfileButtonClicked, |
| base::Unretained(this)), |
| vector_icons::kCloseIcon); |
| } |
| } |
| |
| #if !BUILDFLAG(IS_CHROMEOS_ASH) |
| const bool has_primary_account = |
| !IsGuest(profile) && identity_manager->HasPrimaryAccount(); |
| // The sign-out button is always at the bottom. |
| if (has_unconsented_account && !has_primary_account) { |
| AddFeatureButton( |
| l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_SIGN_OUT), |
| base::BindRepeating(&ProfileMenuView::OnSignoutButtonClicked, |
| base::Unretained(this)), |
| kSignOutIcon); |
| } |
| #endif |
| } |
| |
| #if !BUILDFLAG(IS_CHROMEOS_ASH) |
| void ProfileMenuView::BuildProfileManagementHeading() { |
| SetProfileManagementHeading( |
| UseNewPicker() |
| ? l10n_util::GetStringUTF16(IDS_PROFILES_LIST_PROFILES_TITLE) |
| : l10n_util::GetStringUTF16(IDS_PROFILES_OTHER_PROFILES_TITLE)); |
| } |
| |
| void ProfileMenuView::BuildSelectableProfiles() { |
| auto profile_entries = g_browser_process->profile_manager() |
| ->GetProfileAttributesStorage() |
| .GetAllProfilesAttributesSortedByName(); |
| for (ProfileAttributesEntry* profile_entry : profile_entries) { |
| // Guest profile and the current profile are excluded. |
| if (profile_entry->IsGuest() || |
| profile_entry->GetPath() == browser()->profile()->GetPath()) { |
| continue; |
| } |
| |
| AddSelectableProfile( |
| ui::ImageModel::FromImage( |
| profile_entry->GetAvatarIcon(profiles::kMenuAvatarIconSize)), |
| profile_entry->GetName(), |
| /*is_guest=*/false, |
| base::BindRepeating(&ProfileMenuView::OnOtherProfileSelected, |
| base::Unretained(this), profile_entry->GetPath())); |
| } |
| UMA_HISTOGRAM_BOOLEAN("ProfileChooser.HasProfilesShown", |
| profile_entries.size() > 1); |
| |
| PrefService* service = g_browser_process->local_state(); |
| DCHECK(service); |
| if (!IsGuest(browser()->profile()) && |
| service->GetBoolean(prefs::kBrowserGuestModeEnabled)) { |
| AddSelectableProfile( |
| profiles::GetGuestAvatar(), |
| l10n_util::GetStringUTF16(IDS_GUEST_PROFILE_NAME), |
| /*is_guest=*/true, |
| base::BindRepeating(&ProfileMenuView::OnGuestProfileButtonClicked, |
| base::Unretained(this))); |
| } |
| } |
| |
| void ProfileMenuView::BuildProfileManagementFeatureButtons() { |
| AddProfileManagementShortcutFeatureButton( |
| vector_icons::kSettingsIcon, |
| UseNewPicker() |
| ? l10n_util::GetStringUTF16( |
| IDS_PROFILES_MANAGE_PROFILES_BUTTON_TOOLTIP) |
| : l10n_util::GetStringUTF16(IDS_PROFILES_MANAGE_USERS_BUTTON), |
| base::BindRepeating(&ProfileMenuView::OnManageProfilesButtonClicked, |
| base::Unretained(this))); |
| |
| PrefService* service = g_browser_process->local_state(); |
| DCHECK(service); |
| if (service->GetBoolean(prefs::kBrowserAddPersonEnabled)) { |
| AddProfileManagementFeatureButton( |
| kAddIcon, l10n_util::GetStringUTF16(IDS_ADD), |
| base::BindRepeating(&ProfileMenuView::OnAddNewProfileButtonClicked, |
| base::Unretained(this))); |
| } |
| } |
| #endif // BUILDFLAG(IS_CHROMEOS_ASH) |