ProfileSyncService.java revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Copyright 2013 The Chromium Authors. All rights reserved.
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Use of this source code is governed by a BSD-style license that can be
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// found in the LICENSE file.
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgpackage org.chromium.chrome.browser.sync;
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgimport android.content.Context;
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgimport android.util.Log;
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgimport com.google.common.annotations.VisibleForTesting;
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgimport org.chromium.base.CalledByNative;
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgimport org.chromium.base.ThreadUtils;
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgimport org.chromium.chrome.browser.identity.UniqueIdentificationGenerator;
15281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.orgimport org.chromium.sync.internal_api.pub.SyncDecryptionPassphraseType;
16281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.orgimport org.chromium.sync.internal_api.pub.base.ModelType;
17281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgimport java.util.HashSet;
19281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.orgimport java.util.List;
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgimport java.util.Set;
21281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.orgimport java.util.concurrent.CopyOnWriteArrayList;
22281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org
23281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org/**
24281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org * Android wrapper of the ProfileSyncService which provides access from the Java layer.
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * <p/>
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * This class mostly wraps native classes, but it make a few business logic decisions, both in Java
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * and in native.
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * <p/>
29281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org * Only usable from the UI thread as the native ProfileSyncService requires its access to be in the
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * UI thread.
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * <p/>
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * See chrome/browser/sync/profile_sync_service.h for more details.
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgpublic class ProfileSyncService {
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public interface SyncStateChangedListener {
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // Invoked when the underlying sync status has changed.
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        public void syncStateChanged();
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    private static final String TAG = ProfileSyncService.class.getSimpleName();
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    @VisibleForTesting
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public static final String SESSION_TAG_PREFIX = "session_sync";
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    private static ProfileSyncService sSyncSetupManager;
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    @VisibleForTesting
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    protected final Context mContext;
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Sync state changes more often than listeners are added/removed, so using CopyOnWrite.
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    private final List<SyncStateChangedListener> mListeners =
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            new CopyOnWriteArrayList<SyncStateChangedListener>();
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Native ProfileSyncServiceAndroid object. Can not be final since we set it to 0 in destroy().
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    private final int mNativeProfileSyncServiceAndroid;
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
599d10769e109601915022fea44ec392645c3b0704wu@webrtc.org     * A helper method for retrieving the application-wide SyncSetupManager.
609d10769e109601915022fea44ec392645c3b0704wu@webrtc.org     * <p/>
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Can only be accessed on the main thread.
629d10769e109601915022fea44ec392645c3b0704wu@webrtc.org     *
63ea7b33ee032bd2d1528384e26ba079dee0d280fbwu@webrtc.org     * @param context the ApplicationContext is retrieved from the context used as an argument.
64ea7b33ee032bd2d1528384e26ba079dee0d280fbwu@webrtc.org     * @return a singleton instance of the SyncSetupManager
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public static ProfileSyncService get(Context context) {
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ThreadUtils.assertOnUiThread();
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (sSyncSetupManager == null) {
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            sSyncSetupManager = new ProfileSyncService(context);
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return sSyncSetupManager;
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
73ea7b33ee032bd2d1528384e26ba079dee0d280fbwu@webrtc.org
74ea7b33ee032bd2d1528384e26ba079dee0d280fbwu@webrtc.org    /**
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * This is called pretty early in our application. Avoid any blocking operations here.
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    private ProfileSyncService(Context context) {
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ThreadUtils.assertOnUiThread();
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // We should store the application context, as we outlive any activity which may create us.
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mContext = context.getApplicationContext();
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // This may cause us to create ProfileSyncService even if sync has not
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // been set up, but ProfileSyncService::Startup() won't be called until
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // credentials are available.
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mNativeProfileSyncServiceAndroid = nativeInit();
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    @CalledByNative
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    private static int getProfileSyncServiceAndroid(Context context) {
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return get(context).mNativeProfileSyncServiceAndroid;
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * If we are currently in the process of setting up sync, this method clears the
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * sync setup in progress flag.
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    @VisibleForTesting
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void finishSyncFirstSetupIfNeeded() {
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (isFirstSetupInProgress()) {
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            setSyncSetupCompleted();
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            setSetupInProgress(false);
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void signOut() {
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        nativeSignOutSync(mNativeProfileSyncServiceAndroid);
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
1105dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org     * Signs in to sync, using the currently signed-in account.
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void syncSignIn() {
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        nativeSignInSync(mNativeProfileSyncServiceAndroid);
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // Notify listeners right away that the sync state has changed (native side does not do
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // this)
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        syncStateChanged();
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Signs in to sync, using the existing auth token.
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    @Deprecated
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void syncSignIn(String account) {
1245dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        syncSignIn();
1255dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org    }
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Signs in to sync.
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     *
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * @param account   The username of the account that is signing in.
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * @param authToken Not used. ProfileSyncService switched to OAuth2 tokens.
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Deprecated. Use syncSignIn instead.
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    @Deprecated
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void syncSignInWithAuthToken(String account, String authToken) {
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        syncSignIn(account);
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void requestSyncFromNativeChrome(String objectId, long version, String payload) {
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ThreadUtils.assertOnUiThread();
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        nativeNudgeSyncer(mNativeProfileSyncServiceAndroid, objectId, version, payload);
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void requestSyncFromNativeChromeForAllTypes() {
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ThreadUtils.assertOnUiThread();
1465dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        nativeNudgeSyncerForAllTypes(mNativeProfileSyncServiceAndroid);
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Nudge the syncer to start a new sync cycle.
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    @VisibleForTesting
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void requestSyncCycleForTest() {
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ThreadUtils.assertOnUiThread();
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        requestSyncFromNativeChromeForAllTypes();
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public String querySyncStatus() {
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ThreadUtils.assertOnUiThread();
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeQuerySyncStatusSummary(mNativeProfileSyncServiceAndroid);
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Sets the the machine tag used by session sync to a unique value.
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void setSessionsId(UniqueIdentificationGenerator generator) {
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ThreadUtils.assertOnUiThread();
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        String uniqueTag = generator.getUniqueId(null);
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (uniqueTag.isEmpty()) {
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            Log.e(TAG, "Unable to get unique tag for sync. " +
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    "This may lead to unexpected tab sync behavior.");
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            return;
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        String sessionTag = SESSION_TAG_PREFIX + uniqueTag;
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (!nativeSetSyncSessionsId(mNativeProfileSyncServiceAndroid, sessionTag)) {
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            Log.e(TAG, "Unable to write session sync tag. " +
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    "This may lead to unexpected tab sync behavior.");
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Checks if a password or a passphrase is required for decryption of sync data.
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * <p/>
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Returns NONE if the state is unavailable, or decryption passphrase/password is not required.
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     *
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * @return the enum describing the decryption passphrase type required
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public SyncDecryptionPassphraseType getSyncDecryptionPassphraseTypeIfRequired() {
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // ProfileSyncService::IsUsingSecondaryPassphrase() requires the sync backend to be
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // initialized, and that happens just after OnPassphraseRequired(). Therefore, we need to
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // guard that call with a check of the sync backend since we can not be sure which
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // passphrase type we should tell the user we need.
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // This is tracked in:
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // http://code.google.com/p/chromium/issues/detail?id=108127
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (isSyncInitialized() && isPassphraseRequiredForDecryption()) {
1965dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org            return getSyncDecryptionPassphraseType();
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return SyncDecryptionPassphraseType.NONE;
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Returns the actual passphrase type being used for encryption. The sync backend must be
2035dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org     * running (isSyncInitialized() returns true) before calling this function.
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * <p/>
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * This method should only be used if you want to know the raw value. For checking whether we
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * should ask the user for a passphrase, you should instead use
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * getSyncDecryptionPassphraseTypeIfRequired().
2085dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org     */
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public SyncDecryptionPassphraseType getSyncDecryptionPassphraseType() {
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert isSyncInitialized();
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        int passphraseType = nativeGetPassphraseType(mNativeProfileSyncServiceAndroid);
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return SyncDecryptionPassphraseType.fromInternalValue(passphraseType);
2135dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org    }
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public boolean isSyncKeystoreMigrationDone() {
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert isSyncInitialized();
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeIsSyncKeystoreMigrationDone(mNativeProfileSyncServiceAndroid);
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2195dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Returns true if the current explicit passphrase time is defined.
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public boolean hasExplicitPassphraseTime() {
2245dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        assert isSyncInitialized();
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeHasExplicitPassphraseTime(mNativeProfileSyncServiceAndroid);
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public String getSyncEnterGooglePassphraseBodyWithDateText() {
2295dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        assert isSyncInitialized();
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeGetSyncEnterGooglePassphraseBodyWithDateText(mNativeProfileSyncServiceAndroid);
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public String getSyncEnterCustomPassphraseBodyWithDateText() {
2345dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        assert isSyncInitialized();
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeGetSyncEnterCustomPassphraseBodyWithDateText(mNativeProfileSyncServiceAndroid);
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2375dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public String getCurrentSignedInAccountText() {
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert isSyncInitialized();
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeGetCurrentSignedInAccountText(mNativeProfileSyncServiceAndroid);
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public String getSyncEnterCustomPassphraseBodyText() {
244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeGetSyncEnterCustomPassphraseBodyText(mNativeProfileSyncServiceAndroid);
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Checks if sync is currently set to use a custom passphrase. The sync backend must be running
249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * (isSyncInitialized() returns true) before calling this function.
250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     *
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * @return true if sync is using a custom passphrase.
252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public boolean isUsingSecondaryPassphrase() {
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert isSyncInitialized();
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeIsUsingSecondaryPassphrase(mNativeProfileSyncServiceAndroid);
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2575dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Checks if we need a passphrase to decrypt a currently-enabled data type. This returns false
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * if a passphrase is needed for a type that is not currently enabled.
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     *
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * @return true if we need a passphrase.
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public boolean isPassphraseRequiredForDecryption() {
265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert isSyncInitialized();
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeIsPassphraseRequiredForDecryption(mNativeProfileSyncServiceAndroid);
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Checks if we need a passphrase to decrypt any data type (including types that aren't
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * currently enabled or supported, such as passwords). This API is used to determine if we
272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * need to provide a decryption passphrase before we can re-encrypt with a custom passphrase.
273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     *
274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * @return true if we need a passphrase for some type.
275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public boolean isPassphraseRequiredForExternalType() {
277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert isSyncInitialized();
278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeIsPassphraseRequiredForExternalType(mNativeProfileSyncServiceAndroid);
279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2805dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org
281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Checks if the sync backend is running.
283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     *
284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * @return true if sync is initialized/running.
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public boolean isSyncInitialized() {
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeIsSyncInitialized(mNativeProfileSyncServiceAndroid);
288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Checks if the first sync setup is currently in progress.
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     *
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * @return true if first sync setup is in progress
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public boolean isFirstSetupInProgress() {
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeIsFirstSetupInProgress(mNativeProfileSyncServiceAndroid);
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Checks if the all the data types are encrypted.
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     *
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * @return true if all data types are encrypted, false if only passwords are encrypted.
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public boolean isEncryptEverythingEnabled() {
305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert isSyncInitialized();
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return nativeIsEncryptEverythingEnabled(mNativeProfileSyncServiceAndroid);
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /**
310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * Turns on encryption of all data types. This only takes effect after sync configuration is
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * completed and setPreferredDataTypes() is invoked.
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     */
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void enableEncryptEverything() {
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert isSyncInitialized();
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        nativeEnableEncryptEverything(mNativeProfileSyncServiceAndroid);
316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public void setEncryptionPassphrase(String passphrase, boolean isGaia) {
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert isSyncInitialized();
320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        nativeSetEncryptionPassphrase(mNativeProfileSyncServiceAndroid, passphrase, isGaia);
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    public boolean isCryptographerReady() {
324        assert isSyncInitialized();
325        return nativeIsCryptographerReady(mNativeProfileSyncServiceAndroid);
326    }
327
328    public boolean setDecryptionPassphrase(String passphrase) {
329        assert isSyncInitialized();
330        return nativeSetDecryptionPassphrase(mNativeProfileSyncServiceAndroid, passphrase);
331    }
332
333    public GoogleServiceAuthError.State getAuthError() {
334        int authErrorCode = nativeGetAuthError(mNativeProfileSyncServiceAndroid);
335        return GoogleServiceAuthError.State.fromCode(authErrorCode);
336    }
337
338    /**
339     * Gets the set of data types that are currently enabled to sync.
340     *
341     * @return Set of enabled types.
342     */
343    public Set<ModelType> getPreferredDataTypes() {
344        long modelTypeSelection =
345            nativeGetEnabledDataTypes(mNativeProfileSyncServiceAndroid);
346        Set<ModelType> syncTypes = new HashSet<ModelType>();
347        if ((modelTypeSelection & ModelTypeSelection.AUTOFILL) != 0) {
348          syncTypes.add(ModelType.AUTOFILL);
349        }
350        if ((modelTypeSelection & ModelTypeSelection.AUTOFILL_PROFILE) != 0) {
351          syncTypes.add(ModelType.AUTOFILL_PROFILE);
352        }
353        if ((modelTypeSelection & ModelTypeSelection.BOOKMARK) != 0) {
354          syncTypes.add(ModelType.BOOKMARK);
355        }
356        if ((modelTypeSelection & ModelTypeSelection.EXPERIMENTS) != 0) {
357          syncTypes.add(ModelType.EXPERIMENTS);
358        }
359        if ((modelTypeSelection & ModelTypeSelection.NIGORI) != 0) {
360          syncTypes.add(ModelType.NIGORI);
361        }
362        if ((modelTypeSelection & ModelTypeSelection.PASSWORD) != 0) {
363          syncTypes.add(ModelType.PASSWORD);
364        }
365        if ((modelTypeSelection & ModelTypeSelection.SESSION) != 0) {
366          syncTypes.add(ModelType.SESSION);
367        }
368        if ((modelTypeSelection & ModelTypeSelection.TYPED_URL) != 0) {
369          syncTypes.add(ModelType.TYPED_URL);
370        }
371        if ((modelTypeSelection & ModelTypeSelection.HISTORY_DELETE_DIRECTIVE) != 0) {
372          syncTypes.add(ModelType.HISTORY_DELETE_DIRECTIVE);
373        }
374        if ((modelTypeSelection & ModelTypeSelection.DEVICE_INFO) != 0) {
375          syncTypes.add(ModelType.DEVICE_INFO);
376        }
377        if ((modelTypeSelection & ModelTypeSelection.PROXY_TABS) != 0) {
378          syncTypes.add(ModelType.PROXY_TABS);
379        }
380        if ((modelTypeSelection & ModelTypeSelection.FAVICON_IMAGE) != 0) {
381          syncTypes.add(ModelType.FAVICON_IMAGE);
382        }
383        if ((modelTypeSelection & ModelTypeSelection.FAVICON_TRACKING) != 0) {
384          syncTypes.add(ModelType.FAVICON_TRACKING);
385        }
386        return syncTypes;
387    }
388
389    public boolean hasKeepEverythingSynced() {
390        return nativeHasKeepEverythingSynced(mNativeProfileSyncServiceAndroid);
391    }
392
393    /**
394     * Enables syncing for the passed data types.
395     *
396     * @param syncEverything Set to true if the user wants to sync all data types
397     *                       (including new data types we add in the future).
398     * @param enabledTypes   The set of types to enable. Ignored (can be null) if
399     *                       syncEverything is true.
400     */
401    public void setPreferredDataTypes(boolean syncEverything, Set<ModelType> enabledTypes) {
402        long modelTypeSelection = 0;
403        if (syncEverything || enabledTypes.contains(ModelType.AUTOFILL)) {
404            modelTypeSelection |= ModelTypeSelection.AUTOFILL;
405        }
406        if (syncEverything || enabledTypes.contains(ModelType.BOOKMARK)) {
407            modelTypeSelection |= ModelTypeSelection.BOOKMARK;
408        }
409        if (syncEverything || enabledTypes.contains(ModelType.PASSWORD)) {
410            modelTypeSelection |= ModelTypeSelection.PASSWORD;
411        }
412        if (syncEverything || enabledTypes.contains(ModelType.PROXY_TABS)) {
413            modelTypeSelection |= ModelTypeSelection.PROXY_TABS;
414        }
415        if (syncEverything || enabledTypes.contains(ModelType.TYPED_URL)) {
416            modelTypeSelection |= ModelTypeSelection.TYPED_URL;
417        }
418        nativeSetPreferredDataTypes(
419                mNativeProfileSyncServiceAndroid, syncEverything, modelTypeSelection);
420    }
421
422    public void setSyncSetupCompleted() {
423        nativeSetSyncSetupCompleted(mNativeProfileSyncServiceAndroid);
424    }
425
426    public boolean hasSyncSetupCompleted() {
427        return nativeHasSyncSetupCompleted(mNativeProfileSyncServiceAndroid);
428    }
429
430    public boolean isStartSuppressed() {
431        return nativeIsStartSuppressed(mNativeProfileSyncServiceAndroid);
432    }
433
434    /**
435     * Notifies sync whether sync setup is in progress - this tells sync whether it should start
436     * syncing data types when it starts up, or if it should just stay in "configuration mode".
437     *
438     * @param inProgress True to put sync in configuration mode, false to turn off configuration
439     *                   and allow syncing.
440     */
441    public void setSetupInProgress(boolean inProgress) {
442        nativeSetSetupInProgress(mNativeProfileSyncServiceAndroid, inProgress);
443    }
444
445    public void addSyncStateChangedListener(SyncStateChangedListener listener) {
446        ThreadUtils.assertOnUiThread();
447        mListeners.add(listener);
448    }
449
450    public void removeSyncStateChangedListener(SyncStateChangedListener listener) {
451        ThreadUtils.assertOnUiThread();
452        mListeners.remove(listener);
453    }
454
455    public boolean hasUnrecoverableError() {
456        return nativeHasUnrecoverableError(mNativeProfileSyncServiceAndroid);
457    }
458
459    /**
460     * Called when the state of the native sync engine has changed, so various
461     * UI elements can update themselves.
462     */
463    @CalledByNative
464    public void syncStateChanged() {
465        if (!mListeners.isEmpty()) {
466            for (SyncStateChangedListener listener : mListeners) {
467                listener.syncStateChanged();
468            }
469        }
470    }
471
472    @VisibleForTesting
473    public String getSyncInternalsInfoForTest() {
474        ThreadUtils.assertOnUiThread();
475        return nativeGetAboutInfoForTest(mNativeProfileSyncServiceAndroid);
476    }
477
478    /**
479     * Starts the sync engine.
480     */
481    public void enableSync() {
482        nativeEnableSync(mNativeProfileSyncServiceAndroid);
483    }
484
485    /**
486     * Stops the sync engine.
487     */
488    public void disableSync() {
489        nativeDisableSync(mNativeProfileSyncServiceAndroid);
490    }
491
492    // Native methods
493    private native void nativeNudgeSyncer(
494            int nativeProfileSyncServiceAndroid, String objectId, long version, String payload);
495    private native void nativeNudgeSyncerForAllTypes(int nativeProfileSyncServiceAndroid);
496    private native int nativeInit();
497    private native void nativeEnableSync(int nativeProfileSyncServiceAndroid);
498    private native void nativeDisableSync(int nativeProfileSyncServiceAndroid);
499    private native void nativeSignInSync(int nativeProfileSyncServiceAndroid);
500    private native void nativeSignOutSync(int nativeProfileSyncServiceAndroid);
501    private native void nativeTokenAvailable(
502            int nativeProfileSyncServiceAndroid, String username, String authToken);
503    private native boolean nativeSetSyncSessionsId(int nativeProfileSyncServiceAndroid, String tag);
504    private native String nativeQuerySyncStatusSummary(int nativeProfileSyncServiceAndroid);
505    private native int nativeGetAuthError(int nativeProfileSyncServiceAndroid);
506    private native boolean nativeIsSyncInitialized(int nativeProfileSyncServiceAndroid);
507    private native boolean nativeIsFirstSetupInProgress(int nativeProfileSyncServiceAndroid);
508    private native boolean nativeIsEncryptEverythingEnabled(int nativeProfileSyncServiceAndroid);
509    private native void nativeEnableEncryptEverything(int nativeProfileSyncServiceAndroid);
510    private native boolean nativeIsPassphraseRequiredForDecryption(
511            int nativeProfileSyncServiceAndroid);
512    private native boolean nativeIsPassphraseRequiredForExternalType(
513            int nativeProfileSyncServiceAndroid);
514    private native boolean nativeIsUsingSecondaryPassphrase(int nativeProfileSyncServiceAndroid);
515    private native boolean nativeSetDecryptionPassphrase(
516            int nativeProfileSyncServiceAndroid, String passphrase);
517    private native void nativeSetEncryptionPassphrase(
518            int nativeProfileSyncServiceAndroid, String passphrase, boolean isGaia);
519    private native boolean nativeIsCryptographerReady(int nativeProfileSyncServiceAndroid);
520    private native int nativeGetPassphraseType(int nativeProfileSyncServiceAndroid);
521    private native boolean nativeHasExplicitPassphraseTime(int nativeProfileSyncServiceAndroid);
522    private native String nativeGetSyncEnterGooglePassphraseBodyWithDateText(
523            int nativeProfileSyncServiceAndroid);
524    private native String nativeGetSyncEnterCustomPassphraseBodyWithDateText(
525            int nativeProfileSyncServiceAndroid);
526    private native String nativeGetCurrentSignedInAccountText(int nativeProfileSyncServiceAndroid);
527    private native String nativeGetSyncEnterCustomPassphraseBodyText(
528            int nativeProfileSyncServiceAndroid);
529    private native boolean nativeIsSyncKeystoreMigrationDone(int nativeProfileSyncServiceAndroid);
530    private native long nativeGetEnabledDataTypes(
531        int nativeProfileSyncServiceAndroid);
532    private native void nativeSetPreferredDataTypes(
533            int nativeProfileSyncServiceAndroid, boolean syncEverything, long modelTypeSelection);
534    private native void nativeSetSetupInProgress(
535            int nativeProfileSyncServiceAndroid, boolean inProgress);
536    private native void nativeSetSyncSetupCompleted(int nativeProfileSyncServiceAndroid);
537    private native boolean nativeHasSyncSetupCompleted(int nativeProfileSyncServiceAndroid);
538    private native boolean nativeIsStartSuppressed(int nativeProfileSyncServiceAndroid);
539    private native boolean nativeHasKeepEverythingSynced(int nativeProfileSyncServiceAndroid);
540    private native boolean nativeHasUnrecoverableError(int nativeProfileSyncServiceAndroid);
541    private native String nativeGetAboutInfoForTest(int nativeProfileSyncServiceAndroid);
542}
543