blob: 3fb0248216f98db69462444cd0b7f79f27699647 [file] [log] [blame]
// 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/startup/silent_sync_enabler.h"
#include "base/functional/callback_forward.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/signin_utils.h"
#include "chrome/browser/ui/webui/signin/turn_sync_on_helper.h"
#include "components/signin/public/base/signin_metrics.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "google_apis/gaia/core_account_id.h"
namespace {
// Silently goes through the `TurnSyncOnHelper` flow, enabling Sync when given
// the opportunity.
class SilentTurnSyncOnHelperDelegate : public TurnSyncOnHelper::Delegate {
public:
~SilentTurnSyncOnHelperDelegate() override = default;
// TurnSyncOnHelper::Delegate:
void ShowEnterpriseAccountConfirmation(
const AccountInfo& account_info,
signin::SigninChoiceCallback callback) override {
// We proceed here, and we are waiting until `ShowSyncConfirmation()` for
// the Sync engine to be started to know if we can proceed or not.
// TODO(https://crbug.com/1324569): Introduce a `DEFER` status or a new
// `ShouldShowEnterpriseAccountConfirmation()` delegate method to handle
// management consent not being handled at this step.
std::move(callback).Run(signin::SIGNIN_CHOICE_CONTINUE);
}
void ShowSyncConfirmation(
base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
callback) override {
// The purpose of this delegate is specifically to enable Sync silently. If
// we get all the way here, we assume that we can proceed with it.
std::move(callback).Run(LoginUIService::SyncConfirmationUIClosedResult::
SYNC_WITH_DEFAULT_SETTINGS);
}
bool ShouldAbortBeforeShowSyncDisabledConfirmation() override { return true; }
void ShowSyncDisabledConfirmation(
bool is_managed_account,
base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
callback) override {
// If Sync is disabled, the `TurnSyncOnHelper` should quit earlier due to
// `ShouldAbortBeforeShowSyncDisabledConfirmation()`.
NOTREACHED();
}
void ShowLoginError(const SigninUIError& error) override { NOTREACHED(); }
void ShowMergeSyncDataConfirmation(const std::string&,
const std::string&,
signin::SigninChoiceCallback) override {
NOTREACHED();
}
void ShowSyncSettings() override { NOTREACHED(); }
void SwitchToProfile(Profile*) override { NOTREACHED(); }
};
} // namespace
SilentSyncEnabler::SilentSyncEnabler(Profile* profile) : profile_(profile) {
DCHECK(profile_);
}
SilentSyncEnabler::~SilentSyncEnabler() = default;
void SilentSyncEnabler::StartAttempt(base::OnceClosure callback) {
DCHECK(!callback_); // An attempt should not be ongoing
DCHECK(callback);
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile_);
DCHECK(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSignin));
DCHECK(!identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
callback_ = std::move(callback);
if (identity_manager->AreRefreshTokensLoaded()) {
TryEnableSyncSilentlyWithToken();
} else {
scoped_observation_.Observe(identity_manager);
}
}
void SilentSyncEnabler::OnRefreshTokensLoaded() {
scoped_observation_.Reset();
TryEnableSyncSilentlyWithToken();
}
void SilentSyncEnabler::TryEnableSyncSilentlyWithToken() {
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile_);
CoreAccountId account_id =
identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSignin);
if (!identity_manager->HasAccountWithRefreshToken(account_id)) {
// Still no token, just give up.
if (callback_)
std::move(callback_).Run();
return;
}
// TurnSyncOnHelper deletes itself once done.
new TurnSyncOnHelper(
profile_, signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN,
signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO,
signin_metrics::Reason::kSigninPrimaryAccount, account_id,
TurnSyncOnHelper::SigninAbortedMode::KEEP_ACCOUNT,
std::make_unique<SilentTurnSyncOnHelperDelegate>(), std::move(callback_));
}