1 // Copyright 2014 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.
5 package org.chromium.chrome.shell.sync;
7 import android.accounts.Account;
8 import android.app.Activity;
9 import android.app.FragmentManager;
10 import android.content.Context;
11 import android.util.Log;
13 import org.chromium.base.ThreadUtils;
14 import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory;
15 import org.chromium.chrome.browser.identity.UuidBasedUniqueIdentificationGenerator;
16 import org.chromium.chrome.browser.invalidation.InvalidationController;
17 import org.chromium.chrome.browser.signin.SigninManager;
18 import org.chromium.chrome.browser.sync.ProfileSyncService;
19 import org.chromium.sync.notifier.SyncStatusHelper;
20 import org.chromium.sync.signin.AccountManagerHelper;
21 import org.chromium.sync.signin.ChromeSigninController;
24 * A helper class for managing sync state for the ChromeShell.
26 * Builds on top of the ProfileSyncService (which manages Chrome's sync engine's state) and mimics
27 * the minimum additional functionality needed to fully enable sync for Chrome on Android.
29 public class SyncController implements ProfileSyncService.SyncStateChangedListener,
30 SyncStatusHelper.SyncSettingsChangedObserver {
31 private static final String TAG = "SyncController";
33 private static final String SESSIONS_UUID_PREF_KEY = "chromium.sync.sessions.id";
35 private static SyncController sInstance;
37 private final Context mContext;
38 private final ChromeSigninController mChromeSigninController;
39 private final SyncStatusHelper mSyncStatusHelper;
40 private final ProfileSyncService mProfileSyncService;
42 private SyncController(Context context) {
44 mChromeSigninController = ChromeSigninController.get(mContext);
45 mSyncStatusHelper = SyncStatusHelper.get(context);
46 mSyncStatusHelper.registerSyncSettingsChangedObserver(this);
47 mProfileSyncService = ProfileSyncService.get(mContext);
48 mProfileSyncService.addSyncStateChangedListener(this);
51 mChromeSigninController.ensureGcmIsInitialized();
55 * Retrieve the singleton instance of this class.
57 * @param context the current context.
58 * @return the singleton instance.
60 public static SyncController get(Context context) {
61 ThreadUtils.assertOnUiThread();
62 if (sInstance == null) {
63 sInstance = new SyncController(context.getApplicationContext());
69 * Open a dialog that gives the user the option to sign in from a list of available accounts.
71 * @param fragmentManager the FragmentManager.
73 public static void openSigninDialog(FragmentManager fragmentManager) {
74 AccountChooserFragment chooserFragment = new AccountChooserFragment();
75 chooserFragment.show(fragmentManager, null);
79 * Open a dialog that gives the user the option to sign out.
81 * @param fragmentManager the FragmentManager.
83 public static void openSignOutDialog(FragmentManager fragmentManager) {
84 SignoutFragment signoutFragment = new SignoutFragment();
85 signoutFragment.show(fragmentManager, null);
89 * Trigger Chromium sign in of the given account.
91 * This also ensure that sync setup is not in progress anymore, so sync will start after
92 * sync initialization has happened.
94 * @param activity the current activity.
95 * @param accountName the full account name.
97 public void signIn(Activity activity, String accountName) {
98 final Account account = AccountManagerHelper.createAccountFromName(accountName);
100 // The SigninManager handles most of the sign-in flow, and doFinishSignIn handles the
101 // ChromeShell specific details.
102 SigninManager signinManager = SigninManager.get(mContext);
103 signinManager.onFirstRunCheckDone();
104 final boolean passive = false;
105 signinManager.startSignIn(activity, account, passive, new SigninManager.Observer() {
107 public void onSigninComplete() {
108 SigninManager.get(mContext).logInSignedInUser();
109 mProfileSyncService.setSetupInProgress(false);
110 mProfileSyncService.syncSignIn();
115 public void onSigninCancelled() {
121 public void onStart() {
125 private void setupSessionSyncId() {
126 // Ensure that sync uses the correct UniqueIdentificationGenerator, but do not force the
127 // registration, in case a test case has already overridden it.
128 UuidBasedUniqueIdentificationGenerator generator =
129 new UuidBasedUniqueIdentificationGenerator(mContext, SESSIONS_UUID_PREF_KEY);
130 UniqueIdentificationGeneratorFactory.registerGenerator(
131 UuidBasedUniqueIdentificationGenerator.GENERATOR_ID, generator, false);
132 // Since we do not override the UniqueIdentificationGenerator, we get it from the factory,
133 // instead of using the instance we just created.
134 mProfileSyncService.setSessionsId(UniqueIdentificationGeneratorFactory
135 .getInstance(UuidBasedUniqueIdentificationGenerator.GENERATOR_ID));
138 private void refreshSyncState() {
139 if (mSyncStatusHelper.isSyncEnabled())
145 private void start() {
146 ThreadUtils.assertOnUiThread();
147 if (mSyncStatusHelper.isMasterSyncAutomaticallyEnabled()) {
148 Log.d(TAG, "Enabling sync");
149 Account account = mChromeSigninController.getSignedInUser();
150 InvalidationController.get(mContext).start();
151 mProfileSyncService.enableSync();
152 mSyncStatusHelper.enableAndroidSync(account);
157 * Stops Sync if a user is currently signed in.
160 ThreadUtils.assertOnUiThread();
161 if (mChromeSigninController.isSignedIn()) {
162 Log.d(TAG, "Disabling sync");
163 Account account = mChromeSigninController.getSignedInUser();
164 InvalidationController.get(mContext).stop();
165 mProfileSyncService.disableSync();
166 mSyncStatusHelper.disableAndroidSync(account);
171 * From {@link ProfileSyncService.SyncStateChangedListener}.
174 public void syncStateChanged() {
175 ThreadUtils.assertOnUiThread();
176 // If sync has been disabled from the dashboard, we must disable it.
177 Account account = mChromeSigninController.getSignedInUser();
178 boolean isSyncSuppressStart = mProfileSyncService.isStartSuppressed();
179 boolean isSyncEnabled = mSyncStatusHelper.isSyncEnabled(account);
180 if (account != null && isSyncSuppressStart && isSyncEnabled)
185 * From {@link SyncStatusHelper.SyncSettingsChangedObserver}.
188 public void syncSettingsChanged() {
189 ThreadUtils.runOnUiThread(new Runnable() {