Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java

Issue 12313075: [sync] Upstream the Android ProfileSyncService (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.accounts.Account;
8 import android.content.Context;
9 import android.os.AsyncTask;
10 import android.util.Log;
11
12 import com.google.common.annotations.VisibleForTesting;
13
14 import org.chromium.base.CalledByNative;
15 import org.chromium.base.ThreadUtils;
16 import org.chromium.chrome.browser.identity.UniqueIdentificationGenerator;
17 import org.chromium.sync.internal_api.pub.SyncDecryptionPassphraseType;
18 import org.chromium.sync.internal_api.pub.base.ModelType;
19 import org.chromium.sync.notifier.SyncStatusHelper;
20 import org.chromium.sync.signin.AccountManagerHelper;
21
22 import java.util.ArrayList;
23 import java.util.HashSet;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.Set;
27
28 /**
29 * Android wrapper of the ProfileSyncService which provides access from the Java layer.
30 * <p/>
31 * This class mostly wraps native classes, but it make a few business logic deci sions, both in Java
32 * and in native.
33 * <p/>
34 * Only usable from the UI thread as the native ProfileSyncService requires its access to be in the
35 * UI thread.
36 * <p/>
37 * See chrome/browser/sync/profile_sync_service.h for more details.
38 */
39 public class ProfileSyncService {
40
41 public interface SyncStateChangedListener {
42 // Invoked when the underlying sync status has changed.
43 public void syncStateChanged();
44 }
45
46 private static final String TAG = ProfileSyncService.class.getSimpleName();
47
48 @VisibleForTesting
49 public static final String SESSION_TAG_PREFIX = "session_sync";
50
51 private static ProfileSyncService sSyncSetupManager;
52
53 @VisibleForTesting
54 protected final Context mContext;
55
56 private final List<SyncStateChangedListener> mListeners =
57 new LinkedList<SyncStateChangedListener>();
58
59 // Native ProfileSyncServiceAndroid object. Can not be final since we set it to 0 in destroy().
Yaron 2013/02/23 01:38:49 Since destroy isn't called let's just delete that
nyquist 2013/02/27 05:19:16 Done.
60 private int mNativeProfileSyncServiceAndroid;
61
62 /**
63 * A helper method for retrieving the application-wide SyncSetupManager.
64 * <p/>
65 * Can only be accessed on the main thread.
66 *
67 * @param context the ApplicationContext is retrieved from the context used as an argument.
68 * @return a singleton instance of the SyncSetupManager
69 */
70 public static ProfileSyncService get(Context context) {
71 ThreadUtils.assertOnUiThread();
72 if (sSyncSetupManager == null) {
73 sSyncSetupManager = new ProfileSyncService(context);
74 }
75 return sSyncSetupManager;
76 }
77
78 /**
79 * This is called pretty early in our application. Avoid any blocking operat ions here.
80 */
81 private ProfileSyncService(Context context) {
82 ThreadUtils.assertOnUiThread();
83 // We should store the application context, as we outlive any activity w hich may create us.
84 mContext = context.getApplicationContext();
85
86 // This may cause us to create ProfileSyncService even if sync has not
87 // been set up, but ProfileSyncService::Startup() wont be called until
Yaron 2013/02/23 01:38:49 s/wont/won't/
nyquist 2013/02/27 05:19:16 Done.
88 // credentials are available.
89 mNativeProfileSyncServiceAndroid = nativeInit();
90 }
91
92 /**
93 * Currently, destroy is never called as we are never destroyed.
94 */
95 public void destroy() {
96 nativeDestroy(mNativeProfileSyncServiceAndroid);
97 mNativeProfileSyncServiceAndroid = 0;
98 }
99
100 /**
101 * If we are currently in the process of setting up sync, this method clears the
102 * sync setup in progress flag.
103 */
104 @VisibleForTesting
105 public void finishSyncFirstSetupIfNeeded() {
106 if (isFirstSetupInProgress()) {
107 setSyncSetupCompleted();
108 setSetupInProgress(false);
109 }
110 }
111
112 public void signOut() {
113 nativeSignOutSync(mNativeProfileSyncServiceAndroid);
114 }
115
116 /**
117 * Signs in to sync, using the existing auth token.
118 */
119 public void syncSignIn(String account) {
120 syncSignInWithAuthToken(account, "");
121 }
122
123 /**
124 * Signs in to sync.
125 *
126 * @param account The username of the account that is signing in.
127 * @param authToken A chromiumsync auth token for sync to use, or empty if
128 * sync should use its existing auth token if available.
129 */
130 public void syncSignInWithAuthToken(String account, String authToken) {
131 nativeSignInSync(mNativeProfileSyncServiceAndroid, account, authToken);
132 // Notify listeners right away that the sync state has changed (native s ide does not do
133 // this)
134 syncStateChanged();
135 }
136
137 public void requestSyncFromNativeChrome(String objectId, long version, Strin g payload) {
138 assert mNativeProfileSyncServiceAndroid != 0;
Yaron 2013/02/23 01:38:49 I believe these asserts are spurious. It's set in
nyquist 2013/02/27 05:19:16 Done.
139 nativeNudgeSyncer(mNativeProfileSyncServiceAndroid, objectId, version, p ayload);
140 }
141
142 /**
143 * Nudge the syncer to start a new sync cycle.
144 */
145 @VisibleForTesting
146 public void requestSyncCycleForTest() {
147 ThreadUtils.assertOnUiThread();
148 requestSyncFromNativeChrome("", 0, "");
149 }
150
151 /**
152 * Must be run on the main thread since it is contacting the sync engine dir ectly
Yaron 2013/02/23 01:38:49 Comment is redundant (it's assumed everywhere)
nyquist 2013/02/27 05:19:16 Done.
153 *
154 * @return the current sync status
155 */
156 public String querySyncStatus() {
157 ThreadUtils.assertOnUiThread();
158 assert mNativeProfileSyncServiceAndroid != 0;
159 return nativeQuerySyncStatusSummary(mNativeProfileSyncServiceAndroid);
160 }
161
162 /**
163 * Sets the the machine tag used by session sync to a unique value.
164 */
165 public void setSessionsId(UniqueIdentificationGenerator generator) {
166 ThreadUtils.assertOnUiThread();
167 assert mNativeProfileSyncServiceAndroid != 0;
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, sessionTa g)) {
176 Log.e(TAG, "Unable to write session sync tag. " +
177 "This may lead to unexpected tab sync behavior.");
178 }
179 }
180
181 /**
182 * Requests a new auth token from the AccountManager. Invalidates the old to ken
183 * if |invalidAuthToken| is not empty.
184 */
185 @CalledByNative
186 public void getNewAuthToken(final String username, final String invalidAuthT oken) {
187 Log.d(TAG, "Handling request for auth token from sync engine");
Yaron 2013/02/23 01:38:49 Log Necessary?
nyquist 2013/02/27 05:19:16 Done.
188 if (username == null) {
189 Log.e(TAG, "username is null");
190 return;
191 }
192
193 final AccountManagerHelper accountManagerHelper = AccountManagerHelper.g et(mContext);
194 final Account account = accountManagerHelper.getAccountFromName(username );
195 if (account == null) {
196 Log.e(TAG, "Account not found for provided username.");
197 return;
198 }
199
200 // Since this is blocking, do it in the background.
201 new AsyncTask<Void, Void, String>() {
202
203 @Override
204 public String doInBackground(Void... params) {
205 // Invalidate our old auth token and fetch a new one.
206 return accountManagerHelper.getNewAuthToken(
207 account, invalidAuthToken, SyncStatusHelper.AUTH_TOKEN_T YPE_SYNC);
208 }
209
210 @Override
211 public void onPostExecute(String authToken) {
212 if (authToken == null) {
213 // TODO(sync): Need to hook LOGIN_ACCOUNTS_CHANGED_ACTION (h ttp://b/5354713).
214 Log.d(TAG, "Auth token for sync was null.");
215 } else {
216 if (mNativeProfileSyncServiceAndroid != 0) {
Yaron 2013/02/23 01:38:49 If destroy can go away, i think this check can too
nyquist 2013/02/27 05:19:16 Done.
217 Log.d(TAG, "Successfully retrieved sync auth token.");
218 nativeTokenAvailable(mNativeProfileSyncServiceAndroid, u sername, authToken);
219 } else {
220 Log.e(TAG, "Native sync setup manager not valid.");
221 }
222 }
223 }
224 }.execute();
225 }
226
227 /**
228 * Checks if a password or a passphrase is required for decryption of sync d ata.
229 * <p/>
230 * Returns NONE if the state is unavailable, or decryption passphrase/passwo rd is not required.
231 *
232 * @return the enum describing the decryption passphrase type required
233 */
234 public SyncDecryptionPassphraseType getSyncDecryptionPassphraseTypeIfRequire d() {
235 // ProfileSyncService::IsUsingSecondaryPassphrase() requires the sync ba ckend to be
236 // initialized, and that happens just after OnPassphraseRequired(). Ther efore, we need to
237 // guard that call with a check of the sync backend since we can not be sure which
238 // passphrase type we should tell the user we need.
239 // This is tracked in:
240 // http://code.google.com/p/chromium/issues/detail?id=108127
241 if (isSyncInitialized() && isPassphraseRequiredForDecryption()) {
242 return getSyncDecryptionPassphraseType();
243 }
244 return SyncDecryptionPassphraseType.NONE;
245 }
246
247 /**
248 * Returns the actual passphrase type being used for encryption. The sync ba ckend must be
249 * running (isSyncInitialized() returns true) before calling this function.
250 * <p/>
251 * This method should only be used if you want to know the raw value. For ch ecking whether we
252 * should ask the user for a passphrase, you should instead use
253 * getSyncDecryptionPassphraseTypeIfRequired().
254 */
255 public SyncDecryptionPassphraseType getSyncDecryptionPassphraseType() {
256 assert isSyncInitialized();
257 int passphraseType = nativeGetPassphraseType(mNativeProfileSyncServiceAn droid);
258 return SyncDecryptionPassphraseType.fromInternalValue(passphraseType);
259 }
260
261 /**
262 * Returns true if sync has been migrated.
Yaron 2013/02/23 01:38:49 This is helpful..
nyquist 2013/02/27 05:19:16 Done.
263 */
264 public boolean isSyncMigrated() {
265 assert isSyncInitialized();
266 return nativeIsMigrated(mNativeProfileSyncServiceAndroid);
267 }
268
269 /**
270 * Returns true if the current explicit passphrase time is defined.
271 */
272 public boolean hasExplicitPassphraseTime() {
273 assert isSyncInitialized();
274 return nativeHasExplicitPassphraseTime(mNativeProfileSyncServiceAndroid) ;
275 }
276
277 public String getSyncEnterGooglePassphraseBodyWithDateText() {
278 assert isSyncInitialized();
279 return nativeGetSyncEnterGooglePassphraseBodyWithDateText(mNativeProfile SyncServiceAndroid);
280 }
281
282 public String getSyncEnterCustomPassphraseBodyWithDateText() {
283 assert isSyncInitialized();
284 return nativeGetSyncEnterCustomPassphraseBodyWithDateText(mNativeProfile SyncServiceAndroid);
285 }
286
287 public static String getSyncEnterCustomPassphraseBodyText() {
288 return nativeGetSyncEnterCustomPassphraseBodyText();
289 }
290
291 /**
292 * Checks if sync is currently set to use a custom passphrase. The sync back end must be running
293 * (isSyncInitialized() returns true) before calling this function.
294 *
295 * @return true if sync is using a custom passphrase.
296 */
297 public boolean isUsingSecondaryPassphrase() {
298 assert isSyncInitialized();
299 return nativeIsUsingSecondaryPassphrase(mNativeProfileSyncServiceAndroid );
300 }
301
302 /**
303 * Checks if we need a passphrase to decrypt a currently-enabled data type. This returns false
304 * if a passphrase is needed for a type that is not currently enabled.
305 *
306 * @return true if we need a passphrase.
307 */
308 public boolean isPassphraseRequiredForDecryption() {
309 assert isSyncInitialized();
310 return nativeIsPassphraseRequiredForDecryption(mNativeProfileSyncService Android);
311 }
312
313 /**
314 * Checks if we need a passphrase to decrypt any data type (including types that aren't
315 * currently enabled or supported, such as passwords). This API is used to d etermine if we
316 * need to provide a decryption passphrase before we can re-encrypt with a c ustom passphrase.
317 *
318 * @return true if we need a passphrase for some type.
319 */
320 public boolean isPassphraseRequiredForExternalType() {
321 assert isSyncInitialized();
322 return nativeIsPassphraseRequiredForExternalType(mNativeProfileSyncServi ceAndroid);
323 }
324
325 /**
326 * Checks if the sync backend is running.
327 *
328 * @return true if sync is initialized/running.
329 */
330 public boolean isSyncInitialized() {
331 return nativeIsSyncInitialized(mNativeProfileSyncServiceAndroid);
332 }
333
334 /**
335 * Checks if the first sync setup is currently in progress.
336 *
337 * @return true if first sync setup is in progress
338 */
339 public boolean isFirstSetupInProgress() {
340 return nativeIsFirstSetupInProgress(mNativeProfileSyncServiceAndroid);
341 }
342
343 /**
344 * Checks if the all the data types are encrypted.
345 *
346 * @return true if all data types are encrypted, false if only passwords are encrypted.
347 */
348 public boolean isEncryptEverythingEnabled() {
349 assert isSyncInitialized();
350 return nativeIsEncryptEverythingEnabled(mNativeProfileSyncServiceAndroid );
351 }
352
353 /**
354 * Turns on encryption of all data types. This only takes effect after sync configuration is
355 * completed and setPreferredDataTypes() is invoked.
356 */
357 public void enableEncryptEverything() {
358 assert isSyncInitialized();
359 nativeEnableEncryptEverything(mNativeProfileSyncServiceAndroid);
360 }
361
362 public void setEncryptionPassphrase(String passphrase, boolean isGaia) {
363 assert isSyncInitialized();
364 nativeSetEncryptionPassphrase(mNativeProfileSyncServiceAndroid, passphra se, isGaia);
365 }
366
367 public boolean isCryptographerReady() {
368 assert isSyncInitialized();
369 return nativeIsCryptographerReady(mNativeProfileSyncServiceAndroid);
370 }
371
372 public boolean setDecryptionPassphrase(String passphrase) {
373 assert isSyncInitialized();
374 return nativeSetDecryptionPassphrase(mNativeProfileSyncServiceAndroid, p assphrase);
375 }
376
377 public GoogleServiceAuthError.State getAuthError() {
378 int authErrorCode = nativeGetAuthError(mNativeProfileSyncServiceAndroid) ;
379 return GoogleServiceAuthError.State.fromCode(authErrorCode);
380 }
381
382 /**
383 * Gets the set of data types that are currently enabled to sync.
384 *
385 * @return Set of enabled types.
386 */
387 public Set<ModelType> getPreferredDataTypes() {
388 Set<ModelType> syncTypes = new HashSet<ModelType>();
389
390 if (nativeIsAutofillSyncEnabled(mNativeProfileSyncServiceAndroid)) {
391 syncTypes.add(ModelType.AUTOFILL);
392 }
393 if (nativeIsBookmarkSyncEnabled(mNativeProfileSyncServiceAndroid)) {
394 syncTypes.add(ModelType.BOOKMARK);
395 }
396 if (nativeIsPasswordSyncEnabled(mNativeProfileSyncServiceAndroid)) {
397 syncTypes.add(ModelType.PASSWORD);
398 }
399 if (nativeIsTypedUrlSyncEnabled(mNativeProfileSyncServiceAndroid)) {
400 syncTypes.add(ModelType.TYPED_URL);
401 }
402 if (nativeIsSessionSyncEnabled(mNativeProfileSyncServiceAndroid)) {
403 syncTypes.add(ModelType.SESSION);
404 }
405 return syncTypes;
406 }
407
408 public boolean hasKeepEverythingSynced() {
409 return nativeHasKeepEverythingSynced(mNativeProfileSyncServiceAndroid);
410 }
411
412 /**
413 * Enables syncing for the passed data types.
414 *
415 * @param syncEverything Set to true if the user wants to sync all data type s
416 * (including new data types we add in the future).
417 * @param enabledTypes The set of types to enable. Ignored (can be null) i f
418 * syncEverything is true.
419 */
420 public void setPreferredDataTypes(boolean syncEverything, Set<ModelType> ena bledTypes) {
421 nativeSetPreferredDataTypes(
422 mNativeProfileSyncServiceAndroid,
423 syncEverything,
424 syncEverything || enabledTypes.contains(ModelType.AUTOFILL),
425 syncEverything || enabledTypes.contains(ModelType.BOOKMARK),
426 syncEverything || enabledTypes.contains(ModelType.PASSWORD),
427 syncEverything || enabledTypes.contains(ModelType.SESSION),
428 syncEverything || enabledTypes.contains(ModelType.TYPED_URL));
429 }
430
431 public void setSyncSetupCompleted() {
432 nativeSetSyncSetupCompleted(mNativeProfileSyncServiceAndroid);
433 }
434
435 public boolean hasSyncSetupCompleted() {
436 return nativeHasSyncSetupCompleted(mNativeProfileSyncServiceAndroid);
437 }
438
439 /**
440 * Notifies sync whether sync setup is in progress - this tells sync whether it should start
441 * syncing data types when it starts up, or if it should just stay in "confi guration mode".
442 *
443 * @param inProgress True to put sync in configuration mode, false to turn o ff configuration
444 * and allow syncing.
445 */
446 public void setSetupInProgress(boolean inProgress) {
447 Log.d(TAG, "Setting sync setup_in_progress = " + inProgress);
Yaron 2013/02/23 01:38:49 remove
nyquist 2013/02/27 05:19:16 Done.
448 nativeSetSetupInProgress(mNativeProfileSyncServiceAndroid, inProgress);
449 }
450
451 public void addSyncStateChangedListener(SyncStateChangedListener listener) {
452 mListeners.add(listener);
Yaron 2013/02/23 01:38:49 Assert UIThread so it's clear that callback will c
nyquist 2013/02/27 05:19:16 Done.
453 }
454
455 public void removeSyncStateChangedListener(SyncStateChangedListener listener ) {
456 mListeners.remove(listener);
457 }
458
459 public boolean hasUnrecoverableError() {
460 return nativeHasUnrecoverableError(mNativeProfileSyncServiceAndroid);
461 }
462
463 /**
464 * Called when the state of the native sync engine has changed, so various
465 * UI elements can update themselves.
466 */
467 @CalledByNative
468 public void syncStateChanged() {
469 if (!mListeners.isEmpty()) {
470 // Copy our list of listeners so they can remove themselves in their callbacks.
471 List<SyncStateChangedListener> listeners =
472 new ArrayList<SyncStateChangedListener>(mListeners);
Yaron 2013/02/23 01:38:49 Hmm. What if mListeners is a CopyOnWriteArrayList?
473 for (SyncStateChangedListener listener : listeners) {
474 listener.syncStateChanged();
475 }
476 }
477 }
478
479 @VisibleForTesting
480 public String getSyncInternalsInfoForTest() {
481 ThreadUtils.assertOnUiThread();
482 assert mNativeProfileSyncServiceAndroid != 0;
483 return nativeGetAboutInfoForTest(mNativeProfileSyncServiceAndroid);
484 }
485
486 /**
487 * Starts the sync engine.
488 */
489 public void enableSync() {
490 nativeEnableSync(mNativeProfileSyncServiceAndroid);
491 }
492
493 /**
494 * Stops the sync engine.
495 */
496 public void disableSync() {
497 nativeDisableSync(mNativeProfileSyncServiceAndroid);
498 }
499
500 // Native methods
501 private native void nativeNudgeSyncer(
502 int nativeProfileSyncServiceAndroid, String objectId, long version, String payload);
503
Yaron 2013/02/23 01:38:49 Are whitespaces helpful here?
nyquist 2013/02/27 05:19:16 Done.
504 private native int nativeInit();
505
506 private native void nativeDestroy(int nativeProfileSyncServiceAndroid);
507
508 private native void nativeEnableSync(int nativeProfileSyncServiceAndroid);
509
510 private native void nativeDisableSync(int nativeProfileSyncServiceAndroid);
511
512 private native void nativeSignInSync(
513 int nativeProfileSyncServiceAndroid, String username, String authTok en);
514
515 private native void nativeSignOutSync(int nativeProfileSyncServiceAndroid);
516
517 private native void nativeTokenAvailable(
518 int nativeProfileSyncServiceAndroid, String username, String authTok en);
519
520 private native boolean nativeSetSyncSessionsId(int nativeProfileSyncServiceA ndroid, String tag);
521
522 private native String nativeQuerySyncStatusSummary(int nativeProfileSyncServ iceAndroid);
523
524 private native int nativeGetAuthError(int nativeProfileSyncServiceAndroid);
525
526 private native boolean nativeIsSyncInitialized(int nativeProfileSyncServiceA ndroid);
527
528 private native boolean nativeIsFirstSetupInProgress(int nativeProfileSyncSer viceAndroid);
529
530 private native boolean nativeIsEncryptEverythingEnabled(int nativeProfileSyn cServiceAndroid);
531
532 private native void nativeEnableEncryptEverything(int nativeProfileSyncServi ceAndroid);
533
534 private native boolean nativeIsPassphraseRequiredForDecryption(
535 int nativeProfileSyncServiceAndroid);
536
537 private native boolean nativeIsPassphraseRequiredForExternalType(
538 int nativeProfileSyncServiceAndroid);
539
540 private native boolean nativeIsUsingSecondaryPassphrase(int nativeProfileSyn cServiceAndroid);
541
542 private native boolean nativeSetDecryptionPassphrase(
543 int nativeProfileSyncServiceAndroid, String passphrase);
544
545 private native void nativeSetEncryptionPassphrase(
546 int nativeProfileSyncServiceAndroid, String passphrase, boolean isGa ia);
547
548 private native boolean nativeIsCryptographerReady(int nativeProfileSyncServi ceAndroid);
549
550 private native int nativeGetPassphraseType(int nativeProfileSyncServiceAndro id);
551
552 private native boolean nativeHasExplicitPassphraseTime(int nativeProfileSync ServiceAndroid);
553
554 private native String nativeGetSyncEnterGooglePassphraseBodyWithDateText(
555 int nativeProfileSyncServiceAndroid);
556
557 private native String nativeGetSyncEnterCustomPassphraseBodyWithDateText(
558 int nativeProfileSyncServiceAndroid);
559
560 private static native String nativeGetSyncEnterCustomPassphraseBodyText();
561
562 private native boolean nativeIsMigrated(int nativeProfileSyncServiceAndroid) ;
563
564 private native void nativeSetPreferredDataTypes(
565 int nativeProfileSyncServiceAndroid,
566 boolean syncEverything, boolean syncAutofill, boolean syncBookmarks,
567 boolean syncPasswords, boolean syncSessions, boolean syncTypedUrls);
568
569 private native void nativeSetSetupInProgress(
570 int nativeProfileSyncServiceAndroid, boolean inProgress);
571
572 private native void nativeSetSyncSetupCompleted(int nativeProfileSyncService Android);
573
574 private native boolean nativeHasSyncSetupCompleted(int nativeProfileSyncServ iceAndroid);
575
576 private native boolean nativeHasKeepEverythingSynced(int nativeProfileSyncSe rviceAndroid);
577
578 private native boolean nativeIsAutofillSyncEnabled(int nativeProfileSyncServ iceAndroid);
579
580 private native boolean nativeIsBookmarkSyncEnabled(int nativeProfileSyncServ iceAndroid);
581
582 private native boolean nativeIsPasswordSyncEnabled(int nativeProfileSyncServ iceAndroid);
583
584 private native boolean nativeIsTypedUrlSyncEnabled(int nativeProfileSyncServ iceAndroid);
585
586 private native boolean nativeIsSessionSyncEnabled(int nativeProfileSyncServi ceAndroid);
587
588 private native boolean nativeHasUnrecoverableError(int nativeProfileSyncServ iceAndroid);
589
590 private native String nativeGetAboutInfoForTest(int nativeProfileSyncService Android);
591 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698