Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / android / shell / java / src / org / chromium / chrome / shell / sync / SyncController.java
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.
4
5 package org.chromium.chrome.shell.sync;
6
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;
12
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;
23
24 /**
25  * A helper class for managing sync state for the ChromeShell.
26  *
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.
29  */
30 public class SyncController implements ProfileSyncService.SyncStateChangedListener,
31         SyncStatusHelper.SyncSettingsChangedObserver {
32     private static final String TAG = "SyncController";
33
34     private static final String SESSIONS_UUID_PREF_KEY = "chromium.sync.sessions.id";
35
36     private static SyncController sInstance;
37
38     private final Context mContext;
39     private final ChromeSigninController mChromeSigninController;
40     private final SyncStatusHelper mSyncStatusHelper;
41     private final ProfileSyncService mProfileSyncService;
42
43     private SyncController(Context context) {
44         mContext = context;
45         mChromeSigninController = ChromeSigninController.get(mContext);
46         mSyncStatusHelper = SyncStatusHelper.get(context);
47         mSyncStatusHelper.registerSyncSettingsChangedObserver(this);
48         mProfileSyncService = ProfileSyncService.get(mContext);
49         mProfileSyncService.addSyncStateChangedListener(this);
50
51         setupSessionSyncId();
52         mChromeSigninController.ensureGcmIsInitialized();
53     }
54
55     /**
56      * Retrieve the singleton instance of this class.
57      *
58      * @param context the current context.
59      * @return the singleton instance.
60      */
61     public static SyncController get(Context context) {
62         ThreadUtils.assertOnUiThread();
63         if (sInstance == null) {
64             sInstance = new SyncController(context.getApplicationContext());
65         }
66         return sInstance;
67     }
68
69     /**
70      * Open a dialog that gives the user the option to sign in from a list of available accounts.
71      *
72      * @param fragmentManager the FragmentManager.
73      */
74     public static void openSigninDialog(FragmentManager fragmentManager) {
75         AccountChooserFragment chooserFragment = new AccountChooserFragment();
76         chooserFragment.show(fragmentManager, null);
77     }
78
79     /**
80      * Open a dialog that gives the user the option to sign out.
81      *
82      * @param fragmentManager the FragmentManager.
83      */
84     public static void openSignOutDialog(FragmentManager fragmentManager) {
85         SignoutFragment signoutFragment = new SignoutFragment();
86         signoutFragment.show(fragmentManager, null);
87     }
88
89     /**
90      * Trigger Chromium sign in of the given account.
91      *
92      * This also ensure that sync setup is not in progress anymore, so sync will start after
93      * sync initialization has happened.
94      *
95      * @param activity the current activity.
96      * @param accountName the full account name.
97      */
98     public void signIn(Activity activity, String accountName) {
99         final Account account = AccountManagerHelper.createAccountFromName(accountName);
100
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() {
107             @Override
108             public void onSigninComplete() {
109                 SigninManager.get(mContext).logInSignedInUser();
110                 mProfileSyncService.setSetupInProgress(false);
111                 mProfileSyncService.syncSignIn();
112                 start();
113             }
114
115             @Override
116             public void onSigninCancelled() {
117                 stop();
118             }
119         });
120     }
121
122     public void onStart() {
123         refreshSyncState();
124     }
125
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));
137     }
138
139     private void refreshSyncState() {
140         if (mSyncStatusHelper.isSyncEnabled())
141             start();
142         else
143             stop();
144     }
145
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);
154         }
155     }
156
157     /**
158      * Stops Sync if a user is currently signed in.
159      */
160     public void stop() {
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);
168         }
169     }
170
171     /**
172      * From {@link ProfileSyncService.SyncStateChangedListener}.
173      */
174     @Override
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)
182             stop();
183     }
184
185     /**
186      * From {@link SyncStatusHelper.SyncSettingsChangedObserver}.
187      */
188     @Override
189     public void syncSettingsChanged() {
190         ThreadUtils.runOnUiThread(new Runnable() {
191             @Override
192             public void run() {
193                 refreshSyncState();
194             }
195         });
196     }
197 }