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