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