| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/profiles/profile_customization_util.h" |
| |
| #include "base/auto_reset.h" |
| #include "base/feature_list.h" |
| #include "base/functional/bind.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/profiles/profile_attributes_entry.h" |
| #include "chrome/browser/profiles/profile_attributes_storage.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/profiles/profiles_state.h" |
| #include "chrome/browser/signin/identity_manager_factory.h" |
| #include "chrome/browser/signin/signin_util.h" |
| #include "chrome/common/pref_names.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/signin/public/identity_manager/account_info.h" |
| #include "components/signin/public/identity_manager/identity_manager.h" |
| #include "components/sync/base/features.h" |
| |
| namespace { |
| |
| constexpr base::TimeDelta kDefaultExtendedAccountInfoTimeout = |
| base::Seconds(10); |
| |
| std::optional<base::TimeDelta> g_extended_account_info_timeout_for_testing = |
| std::nullopt; |
| |
| } // namespace |
| |
| // -- Helper functions --------------------------------------------------------- |
| |
| void FinalizeNewProfileSetup(Profile* profile, |
| const std::u16string& profile_name, |
| bool is_default_name) { |
| ProfileAttributesEntry* entry = |
| g_browser_process->profile_manager() |
| ->GetProfileAttributesStorage() |
| .GetProfileAttributesWithPath(profile->GetPath()); |
| CHECK(entry); |
| CHECK(!profile_name.empty()); |
| |
| // We don't expect this to be run for profiles where the user already had a |
| // chance to set a custom profile name. |
| DCHECK(entry->IsUsingDefaultName()); |
| |
| entry->SetLocalProfileName(profile_name, is_default_name); |
| |
| if (signin_util::IsForceSigninEnabled()) { |
| if (!base::FeatureList::IsEnabled( |
| syncer::kReplaceSyncPromosWithSignInPromos)) { |
| // Managed accounts do not need to have Sync consent set. |
| if (!entry->CanBeManaged()) { |
| signin::IdentityManager* identity_manager = |
| IdentityManagerFactory::GetForProfile(profile); |
| CHECK(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)) |
| << "A non syncing account should not be able to finalize the " |
| "profile."; |
| } |
| } |
| entry->LockForceSigninProfile(/*is_lock=*/false); |
| } |
| |
| if (!entry->IsOmitted()) { |
| // The profile has already been created outside of the classic "profile |
| // creation" flow and did not start as omitted. The rest of the finalization |
| // is not necessary. |
| // TODO(crbug.com/40264199): Improve the API to clarify this inconsistency. |
| return; |
| } |
| |
| entry->SetIsOmitted(false); |
| |
| if (!profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) { |
| // Unmark this profile ephemeral so that it isn't deleted upon next |
| // startup. Profiles should never be made non-ephemeral if ephemeral mode |
| // is forced by policy. |
| entry->SetIsEphemeral(false); |
| } |
| } |
| |
| // -- ProfileNameResolver ------------------------------------------------------ |
| |
| // static |
| ProfileNameResolver::ScopedInfoFetchTimeoutOverride |
| ProfileNameResolver::CreateScopedInfoFetchTimeoutOverrideForTesting( |
| base::TimeDelta timeout) { |
| return base::AutoReset<std::optional<base::TimeDelta>>( |
| &g_extended_account_info_timeout_for_testing, timeout); |
| } |
| |
| ProfileNameResolver::ProfileNameResolver( |
| signin::IdentityManager* identity_manager, |
| const CoreAccountInfo& core_account_info) |
| : core_account_info_(core_account_info) { |
| CHECK(!core_account_info_.IsEmpty()); |
| |
| auto extended_account_info = |
| identity_manager->FindExtendedAccountInfo(core_account_info_); |
| if (extended_account_info.IsValid()) { |
| OnExtendedAccountInfoUpdated(extended_account_info); |
| return; |
| } |
| |
| // Listen for extended account info getting fetched. |
| identity_manager_observation_.Observe(identity_manager); |
| |
| // Set up a timeout for extended account info. |
| std::u16string fallback_profile_name = |
| profiles::GetDefaultNameForNewSignedInProfileWithIncompleteInfo( |
| core_account_info_); |
| CHECK(!fallback_profile_name.empty()); |
| extended_account_info_timeout_closure_.Reset( |
| base::BindOnce(&ProfileNameResolver::OnProfileNameResolved, |
| weak_ptr_factory_.GetWeakPtr(), fallback_profile_name)); |
| base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( |
| FROM_HERE, extended_account_info_timeout_closure_.callback(), |
| g_extended_account_info_timeout_for_testing.value_or( |
| kDefaultExtendedAccountInfoTimeout)); |
| } |
| |
| ProfileNameResolver::~ProfileNameResolver() = default; |
| |
| void ProfileNameResolver::RunWithProfileName(NameResolvedCallback callback) { |
| CHECK(!on_profile_name_resolved_callback_); // Multiple pending callbacks |
| // not supported yet. |
| if (resolved_profile_name_.empty()) { |
| on_profile_name_resolved_callback_ = std::move(callback); |
| return; |
| } |
| |
| std::move(callback).Run(resolved_profile_name_); |
| } |
| |
| void ProfileNameResolver::OnExtendedAccountInfoUpdated( |
| const AccountInfo& account_info) { |
| if (!account_info.IsValid() || |
| core_account_info_.account_id != account_info.account_id) { |
| return; |
| } |
| |
| std::u16string profile_name = |
| profiles::GetDefaultNameForNewSignedInProfile(account_info); |
| CHECK(!profile_name.empty()); |
| OnProfileNameResolved(profile_name); |
| } |
| |
| void ProfileNameResolver::OnProfileNameResolved( |
| const std::u16string& profile_name) { |
| CHECK(!profile_name.empty()); |
| DCHECK(resolved_profile_name_.empty()); // Should be resolved only once. |
| |
| // Cancel timeout and stop listening to further changes. |
| extended_account_info_timeout_closure_.Cancel(); |
| identity_manager_observation_.Reset(); |
| |
| resolved_profile_name_ = profile_name; |
| if (on_profile_name_resolved_callback_) { |
| std::move(on_profile_name_resolved_callback_).Run(resolved_profile_name_); |
| } |
| } |