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.signin.SigninManager.SignInFlowObserver;
19 import org.chromium.chrome.browser.sync.ProfileSyncService;
20 import org.chromium.sync.notifier.SyncStatusHelper;
21 import org.chromium.sync.signin.AccountManagerHelper;
22 import org.chromium.sync.signin.ChromeSigninController;
25 * A helper class for managing sync state for the ChromeShell.
27 * Builds on top of the ProfileSyncService (which manages Chrome's sync engine's state) and mimics
28 * the minimum additional functionality needed to fully enable sync for Chrome on Android.
30 public class SyncController implements ProfileSyncService.SyncStateChangedListener,
31 SyncStatusHelper.SyncSettingsChangedObserver {
32 private static final String TAG = "SyncController";
34 private static final String SESSIONS_UUID_PREF_KEY = "chromium.sync.sessions.id";
36 private static SyncController sInstance;
38 private final Context mContext;
39 private final ChromeSigninController mChromeSigninController;
40 private final SyncStatusHelper mSyncStatusHelper;
41 private final ProfileSyncService mProfileSyncService;
43 private SyncController(Context context) {
45 mChromeSigninController = ChromeSigninController.get(mContext);
46 mSyncStatusHelper = SyncStatusHelper.get(context);
47 mSyncStatusHelper.registerSyncSettingsChangedObserver(this);
48 mProfileSyncService = ProfileSyncService.get(mContext);
49 mProfileSyncService.addSyncStateChangedListener(this);
52 mChromeSigninController.ensureGcmIsInitialized();
56 * Retrieve the singleton instance of this class.
58 * @param context the current context.
59 * @return the singleton instance.
61 public static SyncController get(Context context) {
62 ThreadUtils.assertOnUiThread();
63 if (sInstance == null) {
64 sInstance = new SyncController(context.getApplicationContext());
70 * Open a dialog that gives the user the option to sign in from a list of available accounts.
72 * @param fragmentManager the FragmentManager.
74 public static void openSigninDialog(FragmentManager fragmentManager) {
75 AccountChooserFragment chooserFragment = new AccountChooserFragment();
76 chooserFragment.show(fragmentManager, null);
80 * Open a dialog that gives the user the option to sign out.
82 * @param fragmentManager the FragmentManager.
84 public static void openSignOutDialog(FragmentManager fragmentManager) {
85 SignoutFragment signoutFragment = new SignoutFragment();
86 signoutFragment.show(fragmentManager, null);
90 * Trigger Chromium sign in of the given account.
92 * This also ensure that sync setup is not in progress anymore, so sync will start after
93 * sync initialization has happened.
95 * @param activity the current activity.
96 * @param accountName the full account name.
98 public void signIn(Activity activity, String accountName) {
99 final Account account = AccountManagerHelper.createAccountFromName(accountName);
101 // The SigninManager handles most of the sign-in flow, and doFinishSignIn handles the
102 // ChromeShell specific details.
103 SigninManager signinManager = SigninManager.get(mContext);
104 signinManager.onFirstRunCheckDone();
105 final boolean passive = false;
106 signinManager.startSignIn(activity, account, passive, new SignInFlowObserver() {
108 public void onSigninComplete() {
109 SigninManager.get(mContext).logInSignedInUser();
110 mProfileSyncService.setSetupInProgress(false);
111 mProfileSyncService.syncSignIn();
116 public void onSigninCancelled() {
122 public void onStart() {
126 private void setupSessionSyncId() {
127 // Ensure that sync uses the correct UniqueIdentificationGenerator, but do not force the
128 // registration, in case a test case has already overridden it.
129 UuidBasedUniqueIdentificationGenerator generator =
130 new UuidBasedUniqueIdentificationGenerator(mContext, SESSIONS_UUID_PREF_KEY);
131 UniqueIdentificationGeneratorFactory.registerGenerator(
132 UuidBasedUniqueIdentificationGenerator.GENERATOR_ID, generator, false);
133 // Since we do not override the UniqueIdentificationGenerator, we get it from the factory,
134 // instead of using the instance we just created.
135 mProfileSyncService.setSessionsId(UniqueIdentificationGeneratorFactory
136 .getInstance(UuidBasedUniqueIdentificationGenerator.GENERATOR_ID));
139 private void refreshSyncState() {
140 if (mSyncStatusHelper.isSyncEnabled())
146 private void start() {
147 ThreadUtils.assertOnUiThread();
148 if (mSyncStatusHelper.isMasterSyncAutomaticallyEnabled()) {
149 Log.d(TAG, "Enabling sync");
150 Account account = mChromeSigninController.getSignedInUser();
151 InvalidationController.get(mContext).start();
152 mProfileSyncService.enableSync();
153 mSyncStatusHelper.enableAndroidSync(account);
158 * Stops Sync if a user is currently signed in.
161 ThreadUtils.assertOnUiThread();
162 if (mChromeSigninController.isSignedIn()) {
163 Log.d(TAG, "Disabling sync");
164 Account account = mChromeSigninController.getSignedInUser();
165 InvalidationController.get(mContext).stop();
166 mProfileSyncService.disableSync();
167 mSyncStatusHelper.disableAndroidSync(account);
172 * From {@link ProfileSyncService.SyncStateChangedListener}.
175 public void syncStateChanged() {
176 ThreadUtils.assertOnUiThread();
177 // If sync has been disabled from the dashboard, we must disable it.
178 Account account = mChromeSigninController.getSignedInUser();
179 boolean isSyncSuppressStart = mProfileSyncService.isStartSuppressed();
180 boolean isSyncEnabled = mSyncStatusHelper.isSyncEnabled(account);
181 if (account != null && isSyncSuppressStart && isSyncEnabled)
186 * From {@link SyncStatusHelper.SyncSettingsChangedObserver}.
189 public void syncSettingsChanged() {
190 ThreadUtils.runOnUiThread(new Runnable() {