blob: 8e5783d86624c632ba9e88feb20de23cd45a5590 [file] [log] [blame]
// Copyright (c) 2013 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/sync/sync_startup_tracker.h"
#include "base/bind.h"
#include "components/sync/driver/sync_service.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace {
constexpr base::TimeDelta kDefaultWaitTimeout = base::Seconds(10);
absl::optional<base::TimeDelta> g_wait_timeout = kDefaultWaitTimeout;
} // namespace
SyncStartupTracker::SyncStartupTracker(syncer::SyncService* sync_service,
SyncStartupStateChangedCallback callback)
: sync_service_(sync_service),
sync_startup_status_changed_callback_(std::move(callback)) {
DCHECK(sync_service_);
sync_service_observation_.Observe(sync_service_);
if (g_wait_timeout.has_value()) {
timeout_waiter_.Start(FROM_HERE, g_wait_timeout.value(),
base::BindOnce(&SyncStartupTracker::OnStartupTimeout,
weak_factory_.GetWeakPtr()));
}
CheckServiceState();
}
SyncStartupTracker::~SyncStartupTracker() = default;
void SyncStartupTracker::OnStateChanged(syncer::SyncService* sync) {
CheckServiceState();
}
void SyncStartupTracker::OnStartupTimeout() {
is_timed_out_ = true;
CheckServiceState();
}
void SyncStartupTracker::CheckServiceState() {
ServiceStartupState state = GetServiceStartupState(sync_service_);
if (state == ServiceStartupState::kPending) {
if (is_timed_out_) {
state = ServiceStartupState::kTimeout;
} else {
// Do nothing - still waiting for sync to finish starting up.
return;
}
}
timeout_waiter_.Stop();
sync_service_observation_.Reset();
DCHECK(sync_startup_status_changed_callback_);
std::move(sync_startup_status_changed_callback_).Run(state);
}
// static
SyncStartupTracker::ServiceStartupState
SyncStartupTracker::GetServiceStartupState(syncer::SyncService* sync_service) {
// If no service exists or it can't be started, treat as a startup error.
if (!sync_service || !sync_service->CanSyncFeatureStart()) {
return ServiceStartupState::kError;
}
// If the sync engine has started up, notify the callback.
if (sync_service->IsEngineInitialized()) {
return ServiceStartupState::kComplete;
}
// If the sync service has some kind of error, report to the user.
if (sync_service->HasUnrecoverableError()) {
return ServiceStartupState::kError;
}
// If we have an auth error, exit.
if (sync_service->GetAuthError().state() != GoogleServiceAuthError::NONE) {
return ServiceStartupState::kError;
}
// No error detected yet, but the sync engine hasn't started up yet, so
// we're in the pending state.
return ServiceStartupState::kPending;
}
namespace testing {
ScopedSyncStartupTimeoutOverride::ScopedSyncStartupTimeoutOverride(
absl::optional<base::TimeDelta> wait_timeout) {
old_wait_timeout_ = g_wait_timeout;
g_wait_timeout = wait_timeout;
}
ScopedSyncStartupTimeoutOverride::~ScopedSyncStartupTimeoutOverride() {
g_wait_timeout = old_wait_timeout_;
}
} // namespace testing