blob: bdce67cfe93757740a1a3c122795b98581788459 [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/profiles/profile_customization_synced_theme_waiter.h"
#include "base/functional/callback.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "chrome/browser/themes/theme_service.h"
#include "components/sync/base/user_selectable_type.h"
#include "components/sync/service/sync_service.h"
#include "components/sync/service/sync_service_utils.h"
#include "components/sync/service/sync_user_settings.h"
ProfileCustomizationSyncedThemeWaiter::ProfileCustomizationSyncedThemeWaiter(
syncer::SyncService* sync_service,
ThemeService* theme_service,
base::OnceCallback<void(Outcome)> callback)
: sync_service_(sync_service),
theme_service_(theme_service),
callback_(std::move(callback)) {
DCHECK(sync_service_);
DCHECK(theme_service_);
DCHECK(callback_);
}
ProfileCustomizationSyncedThemeWaiter::
~ProfileCustomizationSyncedThemeWaiter() = default;
// static
bool ProfileCustomizationSyncedThemeWaiter::CanThemeSyncStart(
syncer::SyncService* sync_service) {
return syncer::GetUploadToGoogleState(sync_service,
syncer::DataType::THEMES) !=
syncer::UploadState::NOT_ACTIVE;
}
void ProfileCustomizationSyncedThemeWaiter::Run() {
#if DCHECK_IS_ON()
DCHECK(!is_running_);
is_running_ = true;
#endif // DCHECK_IS_ON()
if (!CheckThemeSyncPreconditions()) {
return;
}
std::optional<ThemeSyncableService::ThemeSyncState> theme_state =
theme_service_->GetThemeSyncableService()->GetThemeSyncStartState();
if (theme_state) {
OnThemeSyncStarted(*theme_state);
return;
}
constexpr base::TimeDelta kSyncedThemeTimeout = base::Seconds(3);
base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&ProfileCustomizationSyncedThemeWaiter::OnTimeout,
weak_ptr_factory_.GetWeakPtr()),
kSyncedThemeTimeout);
sync_observation_.Observe(sync_service_);
theme_sync_observation_.Observe(theme_service_->GetThemeSyncableService());
}
void ProfileCustomizationSyncedThemeWaiter::OnStateChanged(
syncer::SyncService* sync) {
CheckThemeSyncPreconditions();
}
void ProfileCustomizationSyncedThemeWaiter::OnSyncShutdown(
syncer::SyncService* sync) {
// Unreachable: This object must be destroyed before SyncService shutdown.
NOTREACHED();
}
void ProfileCustomizationSyncedThemeWaiter::OnThemeSyncStarted(
ThemeSyncableService::ThemeSyncState state) {
switch (state) {
case ThemeSyncableService::ThemeSyncState::kWaitingForExtensionInstallation:
// Wait for the extension theme to be installed to avoid flicker in the
// profile customization dialog.
theme_observation_.Observe(theme_service_);
return;
case ThemeSyncableService::ThemeSyncState::kFailed:
case ThemeSyncableService::ThemeSyncState::kApplied:
InvokeCallback(Outcome::kSyncSuccess);
return;
}
}
void ProfileCustomizationSyncedThemeWaiter::OnThemeChanged() {
InvokeCallback(Outcome::kSyncSuccess);
}
void ProfileCustomizationSyncedThemeWaiter::OnTimeout() {
if (!callback_) {
return;
}
InvokeCallback(Outcome::kTimeout);
}
void ProfileCustomizationSyncedThemeWaiter::InvokeCallback(Outcome outcome) {
sync_observation_.Reset();
theme_sync_observation_.Reset();
theme_observation_.Reset();
std::move(callback_).Run(outcome);
// `this` may be deleted.
}
bool ProfileCustomizationSyncedThemeWaiter::CheckThemeSyncPreconditions() {
if (!CanThemeSyncStart(sync_service_)) {
InvokeCallback(Outcome::kSyncCannotStart);
return false;
}
if (sync_service_->GetUserSettings()->IsPassphraseRequired()) {
InvokeCallback(Outcome::kSyncPassphraseRequired);
return false;
}
return true;
}