1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/sync/sync_startup_tracker.h"
6
7#include "chrome/browser/profiles/profile.h"
8#include "chrome/browser/sync/profile_sync_service.h"
9#include "chrome/browser/sync/profile_sync_service_factory.h"
10
11SyncStartupTracker::SyncStartupTracker(Profile* profile, Observer* observer)
12    : profile_(profile),
13      observer_(observer) {
14  ProfileSyncService* service = ProfileSyncServiceFactory::GetForProfile(
15      profile_);
16  if (service)
17    service->AddObserver(this);
18
19  CheckServiceState();
20}
21
22SyncStartupTracker::~SyncStartupTracker() {
23  ProfileSyncService* service = ProfileSyncServiceFactory::GetForProfile(
24      profile_);
25  if (service)
26    service->RemoveObserver(this);
27}
28
29void SyncStartupTracker::OnStateChanged() {
30  CheckServiceState();
31}
32
33void SyncStartupTracker::CheckServiceState() {
34  // Note: the observer may free this object so it is not allowed to access
35  // this object after invoking the observer callback below.
36  switch (GetSyncServiceState(profile_)) {
37    case SYNC_STARTUP_ERROR:
38      observer_->SyncStartupFailed();
39      break;
40    case SYNC_STARTUP_COMPLETE:
41      observer_->SyncStartupCompleted();
42      break;
43    case SYNC_STARTUP_PENDING:
44      // Do nothing - still waiting for sync to finish starting up.
45      break;
46  }
47}
48
49// static
50SyncStartupTracker::SyncServiceState SyncStartupTracker::GetSyncServiceState(
51    Profile* profile) {
52  // If sync is disabled, treat this as a startup error.
53  if (!profile->IsSyncAccessible())
54    return SYNC_STARTUP_ERROR;
55
56  ProfileSyncService* service =
57      ProfileSyncServiceFactory::GetForProfile(profile);
58
59  // If no service exists or sync is disabled, treat as a startup error.
60  if (!profile->IsSyncAccessible() || !service ||
61      !service->IsSyncEnabledAndLoggedIn()) {
62    return SYNC_STARTUP_ERROR;
63  }
64
65  // If the sync backend has started up, notify the callback.
66  if (service->sync_initialized())
67    return SYNC_STARTUP_COMPLETE;
68
69  // If the sync service has some kind of error, report to the user.
70  if (service->HasUnrecoverableError())
71    return SYNC_STARTUP_ERROR;
72
73  // If we have an auth error and sync is not still waiting for new auth tokens
74  // to be fetched, exit.
75  if (!service->waiting_for_auth() &&
76      service->GetAuthError().state() != GoogleServiceAuthError::NONE) {
77    return SYNC_STARTUP_ERROR;
78  }
79
80  // No error detected yet, but the sync backend hasn't started up yet, so
81  // we're in the pending state.
82  return SYNC_STARTUP_PENDING;
83}
84