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 | |
5 | package org.chromium.chrome.browser.sync; |
6 | |
7 | import android.content.Context; |
8 | import android.util.Log; |
9 | |
10 | import com.google.common.annotations.VisibleForTesting; |
11 | |
12 | import org.chromium.base.CalledByNative; |
13 | import org.chromium.base.ThreadUtils; |
14 | import org.chromium.chrome.browser.identity.UniqueIdentificationGenerator; |
15 | import org.chromium.sync.internal_api.pub.SyncDecryptionPassphraseType; |
16 | import org.chromium.sync.internal_api.pub.base.ModelType; |
17 | |
18 | import java.util.HashSet; |
19 | import java.util.List; |
20 | import java.util.Set; |
21 | import java.util.concurrent.CopyOnWriteArrayList; |
22 | |
23 | /** |
24 | * Android wrapper of the ProfileSyncService which provides access from the Java layer. |
25 | * <p/> |
26 | * This class mostly wraps native classes, but it make a few business logic decisions, both in Java |
27 | * and in native. |
28 | * <p/> |
29 | * Only usable from the UI thread as the native ProfileSyncService requires its access to be in the |
30 | * UI thread. |
31 | * <p/> |
32 | * See chrome/browser/sync/profile_sync_service.h for more details. |
33 | */ |
34 | public class ProfileSyncService { |
35 | |
36 | public interface SyncStateChangedListener { |
37 | // Invoked when the underlying sync status has changed. |
38 | public void syncStateChanged(); |
39 | } |
40 | |
41 | private static final String TAG = "ProfileSyncService"; |
42 | |
43 | @VisibleForTesting |
44 | public static final String SESSION_TAG_PREFIX = "session_sync"; |
45 | |
46 | private static ProfileSyncService sSyncSetupManager; |
47 | |
48 | @VisibleForTesting |
49 | protected final Context mContext; |
50 | |
51 | // Sync state changes more often than listeners are added/removed, so using CopyOnWrite. |
52 | private final List<SyncStateChangedListener> mListeners = |
53 | new CopyOnWriteArrayList<SyncStateChangedListener>(); |
54 | |
55 | // Native ProfileSyncServiceAndroid object. Can not be final since we set it to 0 in destroy(). |
56 | private final int mNativeProfileSyncServiceAndroid; |
57 | |
58 | /** |
59 | * A helper method for retrieving the application-wide SyncSetupManager. |
60 | * <p/> |
61 | * Can only be accessed on the main thread. |
62 | * |
63 | * @param context the ApplicationContext is retrieved from the context used as an argument. |
64 | * @return a singleton instance of the SyncSetupManager |
65 | */ |
66 | public static ProfileSyncService get(Context context) { |
67 | ThreadUtils.assertOnUiThread(); |
68 | if (sSyncSetupManager == null) { |
69 | sSyncSetupManager = new ProfileSyncService(context); |
70 | } |
71 | return sSyncSetupManager; |
72 | } |
73 | |
74 | /** |
75 | * This is called pretty early in our application. Avoid any blocking operations here. |
76 | */ |
77 | private ProfileSyncService(Context context) { |
78 | ThreadUtils.assertOnUiThread(); |
79 | // We should store the application context, as we outlive any activity which may create us. |
80 | mContext = context.getApplicationContext(); |
81 | |
82 | // This may cause us to create ProfileSyncService even if sync has not |
83 | // been set up, but ProfileSyncService::Startup() won't be called until |
84 | // credentials are available. |
85 | mNativeProfileSyncServiceAndroid = nativeInit(); |
86 | } |
87 | |
88 | @CalledByNative |
89 | private static int getProfileSyncServiceAndroid(Context context) { |
90 | return get(context).mNativeProfileSyncServiceAndroid; |
91 | } |
92 | |
93 | /** |
94 | * If we are currently in the process of setting up sync, this method clears the |
95 | * sync setup in progress flag. |
96 | */ |
97 | @VisibleForTesting |
98 | public void finishSyncFirstSetupIfNeeded() { |
99 | if (isFirstSetupInProgress()) { |
100 | setSyncSetupCompleted(); |
101 | setSetupInProgress(false); |
102 | } |
103 | } |
104 | |
105 | public void signOut() { |
106 | nativeSignOutSync(mNativeProfileSyncServiceAndroid); |
107 | } |
108 | |
109 | /** |
110 | * Signs in to sync, using the currently signed-in account. |
111 | */ |
112 | public void syncSignIn() { |
113 | nativeSignInSync(mNativeProfileSyncServiceAndroid); |
114 | // Notify listeners right away that the sync state has changed (native side does not do |
115 | // this) |
116 | syncStateChanged(); |
117 | } |
118 | |
119 | /** |
120 | * Signs in to sync, using the existing auth token. |
121 | */ |
122 | @Deprecated |
123 | public void syncSignIn(String account) { |
124 | syncSignIn(); |
125 | } |
126 | |
127 | /** |
128 | * Signs in to sync. |
129 | * |
130 | * @param account The username of the account that is signing in. |
131 | * @param authToken Not used. ProfileSyncService switched to OAuth2 tokens. |
132 | * Deprecated. Use syncSignIn instead. |
133 | */ |
134 | @Deprecated |
135 | public void syncSignInWithAuthToken(String account, String authToken) { |
136 | syncSignIn(account); |
137 | } |
138 | |
139 | public void requestSyncFromNativeChrome(String objectId, long version, String payload) { |
140 | ThreadUtils.assertOnUiThread(); |
141 | nativeNudgeSyncer(mNativeProfileSyncServiceAndroid, objectId, version, payload); |
142 | } |
143 | |
144 | public void requestSyncFromNativeChromeForAllTypes() { |
145 | ThreadUtils.assertOnUiThread(); |
146 | nativeNudgeSyncerForAllTypes(mNativeProfileSyncServiceAndroid); |
147 | } |
148 | |
149 | /** |
150 | * Nudge the syncer to start a new sync cycle. |
151 | */ |
152 | @VisibleForTesting |
153 | public void requestSyncCycleForTest() { |
154 | ThreadUtils.assertOnUiThread(); |
155 | requestSyncFromNativeChromeForAllTypes(); |
156 | } |
157 | |
158 | public String querySyncStatus() { |
159 | ThreadUtils.assertOnUiThread(); |
160 | return nativeQuerySyncStatusSummary(mNativeProfileSyncServiceAndroid); |
161 | } |
162 | |
163 | /** |
164 | * Sets the the machine tag used by session sync to a unique value. |
165 | */ |
166 | public void setSessionsId(UniqueIdentificationGenerator generator) { |
167 | ThreadUtils.assertOnUiThread(); |
168 | String uniqueTag = generator.getUniqueId(null); |
169 | if (uniqueTag.isEmpty()) { |
170 | Log.e(TAG, "Unable to get unique tag for sync. " + |
171 | "This may lead to unexpected tab sync behavior."); |
172 | return; |
173 | } |
174 | String sessionTag = SESSION_TAG_PREFIX + uniqueTag; |
175 | if (!nativeSetSyncSessionsId(mNativeProfileSyncServiceAndroid, sessionTag)) { |
176 | Log.e(TAG, "Unable to write session sync tag. " + |
177 | "This may lead to unexpected tab sync behavior."); |
178 | } |
179 | } |
180 | |
181 | /** |
182 | * Checks if a password or a passphrase is required for decryption of sync data. |
183 | * <p/> |
184 | * Returns NONE if the state is unavailable, or decryption passphrase/password is not required. |
185 | * |
186 | * @return the enum describing the decryption passphrase type required |
187 | */ |
188 | public SyncDecryptionPassphraseType getSyncDecryptionPassphraseTypeIfRequired() { |
189 | // ProfileSyncService::IsUsingSecondaryPassphrase() requires the sync backend to be |
190 | // initialized, and that happens just after OnPassphraseRequired(). Therefore, we need to |
191 | // guard that call with a check of the sync backend since we can not be sure which |
192 | // passphrase type we should tell the user we need. |
193 | // This is tracked in: |
194 | // http://code.google.com/p/chromium/issues/detail?id=108127 |
195 | if (isSyncInitialized() && isPassphraseRequiredForDecryption()) { |
196 | return getSyncDecryptionPassphraseType(); |
197 | } |
198 | return SyncDecryptionPassphraseType.NONE; |
199 | } |
200 | |
201 | /** |
202 | * Returns the actual passphrase type being used for encryption. The sync backend must be |
203 | * running (isSyncInitialized() returns true) before calling this function. |
204 | * <p/> |
205 | * This method should only be used if you want to know the raw value. For checking whether we |
206 | * should ask the user for a passphrase, you should instead use |
207 | * getSyncDecryptionPassphraseTypeIfRequired(). |
208 | */ |
209 | public SyncDecryptionPassphraseType getSyncDecryptionPassphraseType() { |
210 | assert isSyncInitialized(); |
211 | int passphraseType = nativeGetPassphraseType(mNativeProfileSyncServiceAndroid); |
212 | return SyncDecryptionPassphraseType.fromInternalValue(passphraseType); |
213 | } |
214 | |
215 | public boolean isSyncKeystoreMigrationDone() { |
216 | assert isSyncInitialized(); |
217 | return nativeIsSyncKeystoreMigrationDone(mNativeProfileSyncServiceAndroid); |
218 | } |
219 | |
220 | /** |
221 | * Returns true if the current explicit passphrase time is defined. |
222 | */ |
223 | public boolean hasExplicitPassphraseTime() { |
224 | assert isSyncInitialized(); |
225 | return nativeHasExplicitPassphraseTime(mNativeProfileSyncServiceAndroid); |
226 | } |
227 | |
228 | public String getSyncEnterGooglePassphraseBodyWithDateText() { |
229 | assert isSyncInitialized(); |
230 | return nativeGetSyncEnterGooglePassphraseBodyWithDateText(mNativeProfileSyncServiceAndroid); |
231 | } |
232 | |
233 | public String getSyncEnterCustomPassphraseBodyWithDateText() { |
234 | assert isSyncInitialized(); |
235 | return nativeGetSyncEnterCustomPassphraseBodyWithDateText(mNativeProfileSyncServiceAndroid); |
236 | } |
237 | |
238 | public String getCurrentSignedInAccountText() { |
239 | assert isSyncInitialized(); |
240 | return nativeGetCurrentSignedInAccountText(mNativeProfileSyncServiceAndroid); |
241 | } |
242 | |
243 | public String getSyncEnterCustomPassphraseBodyText() { |
244 | return nativeGetSyncEnterCustomPassphraseBodyText(mNativeProfileSyncServiceAndroid); |
245 | } |
246 | |
247 | /** |
248 | * Checks if sync is currently set to use a custom passphrase. The sync backend must be running |
249 | * (isSyncInitialized() returns true) before calling this function. |
250 | * |
251 | * @return true if sync is using a custom passphrase. |
252 | */ |
253 | public boolean isUsingSecondaryPassphrase() { |
254 | assert isSyncInitialized(); |
255 | return nativeIsUsingSecondaryPassphrase(mNativeProfileSyncServiceAndroid); |
256 | } |
257 | |
258 | /** |
259 | * Checks if we need a passphrase to decrypt a currently-enabled data type. This returns false |
260 | * if a passphrase is needed for a type that is not currently enabled. |
261 | * |
262 | * @return true if we need a passphrase. |
263 | */ |
264 | public boolean isPassphraseRequiredForDecryption() { |
265 | assert isSyncInitialized(); |
266 | return nativeIsPassphraseRequiredForDecryption(mNativeProfileSyncServiceAndroid); |
267 | } |
268 | |
269 | /** |
270 | * Checks if we need a passphrase to decrypt any data type (including types that aren't |
271 | * currently enabled or supported, such as passwords). This API is used to determine if we |
272 | * need to provide a decryption passphrase before we can re-encrypt with a custom passphrase. |
273 | * |
274 | * @return true if we need a passphrase for some type. |
275 | */ |
276 | public boolean isPassphraseRequiredForExternalType() { |
277 | assert isSyncInitialized(); |
278 | return nativeIsPassphraseRequiredForExternalType(mNativeProfileSyncServiceAndroid); |
279 | } |
280 | |
281 | /** |
282 | * Checks if the sync backend is running. |
283 | * |
284 | * @return true if sync is initialized/running. |
285 | */ |
286 | public boolean isSyncInitialized() { |
287 | return nativeIsSyncInitialized(mNativeProfileSyncServiceAndroid); |
288 | } |
289 | |
290 | /** |
291 | * Checks if the first sync setup is currently in progress. |
292 | * |
293 | * @return true if first sync setup is in progress |
294 | */ |
295 | public boolean isFirstSetupInProgress() { |
296 | return nativeIsFirstSetupInProgress(mNativeProfileSyncServiceAndroid); |
297 | } |
298 | |
299 | /** |
300 | * Checks if the all the data types are encrypted. |
301 | * |
302 | * @return true if all data types are encrypted, false if only passwords are encrypted. |
303 | */ |
304 | public boolean isEncryptEverythingEnabled() { |
305 | assert isSyncInitialized(); |
306 | return nativeIsEncryptEverythingEnabled(mNativeProfileSyncServiceAndroid); |
307 | } |
308 | |
309 | /** |
310 | * Turns on encryption of all data types. This only takes effect after sync configuration is |
311 | * completed and setPreferredDataTypes() is invoked. |
312 | */ |
313 | public void enableEncryptEverything() { |
314 | assert isSyncInitialized(); |
315 | nativeEnableEncryptEverything(mNativeProfileSyncServiceAndroid); |
316 | } |
317 | |
318 | public void setEncryptionPassphrase(String passphrase, boolean isGaia) { |
319 | assert isSyncInitialized(); |
320 | nativeSetEncryptionPassphrase(mNativeProfileSyncServiceAndroid, passphrase, isGaia); |
321 | } |
322 | |
323 | 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 | } |