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 androidx.annotation.Nullable; 8 import androidx.annotation.VisibleForTesting; 9 10 import org.json.JSONArray; 11 import org.json.JSONException; 12 13 import org.chromium.base.ThreadUtils; 14 import org.chromium.base.annotations.CalledByNative; 15 import org.chromium.base.annotations.NativeMethods; 16 import org.chromium.components.signin.base.GoogleServiceAuthError; 17 import org.chromium.components.sync.KeyRetrievalTriggerForUMA; 18 import org.chromium.components.sync.ModelType; 19 import org.chromium.components.sync.PassphraseType; 20 21 import java.util.HashSet; 22 import java.util.List; 23 import java.util.Set; 24 import java.util.concurrent.CopyOnWriteArrayList; 25 26 /** 27 * JNI wrapper for the native ProfileSyncService. 28 * 29 * This class mostly makes calls to native and contains a minimum of business logic. It is only 30 * usable from the UI thread as the native ProfileSyncService requires its access to be on the 31 * UI thread. See components/sync/driver/profile_sync_service.h for more details. 32 */ 33 public class ProfileSyncService { 34 35 /** 36 * Listener for the underlying sync status. 37 */ 38 public interface SyncStateChangedListener { 39 // Invoked when the status has changed. syncStateChanged()40 public void syncStateChanged(); 41 } 42 43 private static final int[] ALL_SELECTABLE_TYPES = new int[] { 44 ModelType.AUTOFILL, 45 ModelType.BOOKMARKS, 46 ModelType.PASSWORDS, 47 ModelType.PREFERENCES, 48 ModelType.PROXY_TABS, 49 ModelType.TYPED_URLS 50 }; 51 52 private static ProfileSyncService sProfileSyncService; 53 private static boolean sInitialized; 54 55 // Sync state changes more often than listeners are added/removed, so using CopyOnWrite. 56 private final List<SyncStateChangedListener> mListeners = 57 new CopyOnWriteArrayList<SyncStateChangedListener>(); 58 59 /** 60 * Native ProfileSyncServiceAndroid object. Cannot be final because it is initialized in 61 * {@link init()}. 62 */ 63 private long mNativeProfileSyncServiceAndroid; 64 65 private int mSetupInProgressCounter; 66 67 /** 68 * Retrieves or creates the ProfileSyncService singleton instance. Returns null if sync is 69 * disabled (via flag or variation). 70 * 71 * Can only be accessed on the main thread. 72 */ 73 @Nullable get()74 public static ProfileSyncService get() { 75 ThreadUtils.assertOnUiThread(); 76 if (!sInitialized) { 77 sProfileSyncService = new ProfileSyncService(); 78 if (sProfileSyncService.mNativeProfileSyncServiceAndroid == 0) { 79 sProfileSyncService = null; 80 } 81 sInitialized = true; 82 } 83 return sProfileSyncService; 84 } 85 86 /** 87 * Overrides the initialization for tests. The tests should call resetForTests() at shutdown. 88 */ 89 @VisibleForTesting overrideForTests(ProfileSyncService profileSyncService)90 public static void overrideForTests(ProfileSyncService profileSyncService) { 91 ThreadUtils.assertOnUiThread(); 92 sProfileSyncService = profileSyncService; 93 sInitialized = true; 94 } 95 96 /** 97 * Resets the ProfileSyncService instance. Calling get() next time will initialize with a new 98 * instance. 99 */ 100 @VisibleForTesting resetForTests()101 public static void resetForTests() { 102 sInitialized = false; 103 sProfileSyncService = null; 104 } 105 ProfileSyncService()106 protected ProfileSyncService() { 107 init(); 108 } 109 110 /** 111 * This is called pretty early in our application. Avoid any blocking operations here. init() 112 * is a separate function to enable a test subclass of ProfileSyncService to completely stub out 113 * ProfileSyncService. 114 */ init()115 protected void init() { 116 ThreadUtils.assertOnUiThread(); 117 118 // This may cause us to create ProfileSyncService even if sync has not 119 // been set up, but ProfileSyncService won't actually start until 120 // credentials are available. 121 mNativeProfileSyncServiceAndroid = 122 ProfileSyncServiceJni.get().init(ProfileSyncService.this); 123 } 124 125 /** 126 * Checks if the sync engine is initialized. 127 * 128 * @return true if the sync engine is initialized. 129 */ isEngineInitialized()130 public boolean isEngineInitialized() { 131 return ProfileSyncServiceJni.get().isEngineInitialized( 132 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 133 } 134 135 /** 136 * Checks whether sync machinery is active. 137 * 138 * @return true if the transport state is active. 139 */ 140 @VisibleForTesting isTransportStateActive()141 public boolean isTransportStateActive() { 142 return ProfileSyncServiceJni.get().isTransportStateActive( 143 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 144 } 145 146 /** 147 * Checks whether Sync-the-feature can (attempt to) start. This means that there is a primary 148 * account and no disable reasons. Note that the Sync machinery may start up in transport-only 149 * mode even if this is false. 150 * 151 * @return true if Sync can start, false otherwise. 152 */ canSyncFeatureStart()153 public boolean canSyncFeatureStart() { 154 return ProfileSyncServiceJni.get().canSyncFeatureStart( 155 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 156 } 157 158 /** 159 * Checks whether Sync-the-feature is currently active. Note that Sync-the-transport may be 160 * active even if this is false. 161 * 162 * @return true if Sync is active, false otherwise. 163 */ isSyncActive()164 public boolean isSyncActive() { 165 return ProfileSyncServiceJni.get().isSyncActive( 166 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 167 } 168 getAuthError()169 public @GoogleServiceAuthError.State int getAuthError() { 170 int authErrorCode = ProfileSyncServiceJni.get().getAuthError( 171 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 172 if (authErrorCode < 0 || authErrorCode >= GoogleServiceAuthError.State.NUM_ENTRIES) { 173 throw new IllegalArgumentException("No state for code: " + authErrorCode); 174 } 175 return authErrorCode; 176 } 177 178 /** 179 * Checks whether Sync is disabled by enterprise policy (through prefs) or account policy 180 * received from the sync server. 181 * 182 * @return true if Sync is disabled, false otherwise. 183 */ isSyncDisabledByEnterprisePolicy()184 public boolean isSyncDisabledByEnterprisePolicy() { 185 return ProfileSyncServiceJni.get().isSyncDisabledByEnterprisePolicy( 186 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 187 } 188 hasUnrecoverableError()189 public boolean hasUnrecoverableError() { 190 return ProfileSyncServiceJni.get().hasUnrecoverableError( 191 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 192 } 193 requiresClientUpgrade()194 public boolean requiresClientUpgrade() { 195 return ProfileSyncServiceJni.get().requiresClientUpgrade( 196 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 197 } 198 setDecoupledFromAndroidMasterSync()199 public void setDecoupledFromAndroidMasterSync() { 200 ProfileSyncServiceJni.get().setDecoupledFromAndroidMasterSync( 201 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 202 } 203 getDecoupledFromAndroidMasterSync()204 public boolean getDecoupledFromAndroidMasterSync() { 205 return ProfileSyncServiceJni.get().getDecoupledFromAndroidMasterSync( 206 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 207 } 208 isAuthenticatedAccountPrimary()209 public boolean isAuthenticatedAccountPrimary() { 210 return ProfileSyncServiceJni.get().isAuthenticatedAccountPrimary( 211 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 212 } 213 214 /** 215 * Gets the set of data types that are "preferred" in sync. Those are the 216 * chosen ones (see getChosenDataTypes), plus any that are implied by them. 217 * 218 * This is unaffected by whether sync is on. 219 * 220 * @return Set of preferred data types. 221 */ getPreferredDataTypes()222 public Set<Integer> getPreferredDataTypes() { 223 int[] modelTypeArray = ProfileSyncServiceJni.get().getPreferredDataTypes( 224 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 225 return modelTypeArrayToSet(modelTypeArray); 226 } 227 228 /** 229 * Gets the set of data types that are currently syncing. 230 * 231 * This is affected by whether sync is on. 232 * 233 * @return Set of active data types. 234 */ getActiveDataTypes()235 public Set<Integer> getActiveDataTypes() { 236 int[] activeDataTypes = ProfileSyncServiceJni.get().getActiveDataTypes( 237 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 238 return modelTypeArrayToSet(activeDataTypes); 239 } 240 241 /** 242 * Gets the set of data types that are enabled in sync. This will always 243 * return a subset of syncer::UserSelectableTypes(). 244 * 245 * This is unaffected by whether sync is on. 246 * 247 * @return Set of chosen types. 248 */ getChosenDataTypes()249 public Set<Integer> getChosenDataTypes() { 250 int[] modelTypeArray = ProfileSyncServiceJni.get().getChosenDataTypes( 251 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 252 return modelTypeArrayToSet(modelTypeArray); 253 } 254 hasKeepEverythingSynced()255 public boolean hasKeepEverythingSynced() { 256 return ProfileSyncServiceJni.get().hasKeepEverythingSynced( 257 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 258 } 259 260 /** 261 * Enables syncing for the passed data types. 262 * 263 * @param syncEverything Set to true if the user wants to sync all data types 264 * (including new data types we add in the future). 265 * @param enabledTypes The set of types to enable. Ignored (can be null) if 266 * syncEverything is true. 267 */ setChosenDataTypes(boolean syncEverything, Set<Integer> enabledTypes)268 public void setChosenDataTypes(boolean syncEverything, Set<Integer> enabledTypes) { 269 ProfileSyncServiceJni.get().setChosenDataTypes(mNativeProfileSyncServiceAndroid, 270 ProfileSyncService.this, syncEverything, 271 syncEverything ? ALL_SELECTABLE_TYPES : modelTypeSetToArray(enabledTypes)); 272 } 273 setFirstSetupComplete(int syncFirstSetupCompleteSource)274 public void setFirstSetupComplete(int syncFirstSetupCompleteSource) { 275 ProfileSyncServiceJni.get().setFirstSetupComplete(mNativeProfileSyncServiceAndroid, 276 ProfileSyncService.this, syncFirstSetupCompleteSource); 277 } 278 isFirstSetupComplete()279 public boolean isFirstSetupComplete() { 280 return ProfileSyncServiceJni.get().isFirstSetupComplete( 281 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 282 } 283 requestStart()284 public void requestStart() { 285 ProfileSyncServiceJni.get().requestStart( 286 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 287 } 288 requestStop()289 public void requestStop() { 290 ProfileSyncServiceJni.get().requestStop( 291 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 292 } 293 294 /** 295 * Checks whether syncing is requested by the user, i.e. the user has at least started a Sync 296 * setup flow, and has not disabled syncing in settings. Note that even if this is true, other 297 * reasons might prevent Sync from actually starting up. 298 * 299 * @return true if the user wants to sync, false otherwise. 300 */ isSyncRequested()301 public boolean isSyncRequested() { 302 return ProfileSyncServiceJni.get().isSyncRequested( 303 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 304 } 305 306 /** 307 * Instances of this class keep sync paused until {@link #close} is called. Use 308 * {@link ProfileSyncService#getSetupInProgressHandle} to create. Please note that 309 * {@link #close} should be called on every instance of this class. 310 */ 311 public final class SyncSetupInProgressHandle { 312 private boolean mClosed; 313 SyncSetupInProgressHandle()314 private SyncSetupInProgressHandle() { 315 ThreadUtils.assertOnUiThread(); 316 if (++mSetupInProgressCounter == 1) { 317 setSetupInProgress(true); 318 } 319 } 320 close()321 public void close() { 322 ThreadUtils.assertOnUiThread(); 323 if (mClosed) return; 324 mClosed = true; 325 326 assert mSetupInProgressCounter > 0; 327 if (--mSetupInProgressCounter == 0) { 328 setSetupInProgress(false); 329 } 330 } 331 } 332 333 /** 334 * Called by the UI to prevent changes in sync settings from taking effect while these settings 335 * are being modified by the user. When sync settings UI is no longer visible, 336 * {@link SyncSetupInProgressHandle#close} has to be invoked for sync settings to be applied. 337 * Sync settings will remain paused as long as there are unclosed objects returned by this 338 * method. Please note that the behavior of SyncSetupInProgressHandle is slightly different from 339 * the equivalent C++ object, as Java instances don't commit sync settings as soon as any 340 * instance of SyncSetupInProgressHandle is closed. 341 */ getSetupInProgressHandle()342 public SyncSetupInProgressHandle getSetupInProgressHandle() { 343 return new SyncSetupInProgressHandle(); 344 } 345 setSetupInProgress(boolean inProgress)346 private void setSetupInProgress(boolean inProgress) { 347 ProfileSyncServiceJni.get().setSetupInProgress( 348 mNativeProfileSyncServiceAndroid, ProfileSyncService.this, inProgress); 349 } 350 addSyncStateChangedListener(SyncStateChangedListener listener)351 public void addSyncStateChangedListener(SyncStateChangedListener listener) { 352 ThreadUtils.assertOnUiThread(); 353 mListeners.add(listener); 354 } 355 removeSyncStateChangedListener(SyncStateChangedListener listener)356 public void removeSyncStateChangedListener(SyncStateChangedListener listener) { 357 ThreadUtils.assertOnUiThread(); 358 mListeners.remove(listener); 359 } 360 361 /** 362 * Called when the state of the native sync engine has changed, so various 363 * UI elements can update themselves. 364 */ 365 @CalledByNative syncStateChanged()366 protected void syncStateChanged() { 367 for (SyncStateChangedListener listener : mListeners) { 368 listener.syncStateChanged(); 369 } 370 } 371 setSyncAllowedByPlatform(boolean allowed)372 public void setSyncAllowedByPlatform(boolean allowed) { 373 ProfileSyncServiceJni.get().setSyncAllowedByPlatform( 374 mNativeProfileSyncServiceAndroid, ProfileSyncService.this, allowed); 375 } 376 377 /** 378 * Returns the actual passphrase type being used for encryption. The sync engine must be 379 * running (isEngineInitialized() returns true) before calling this function. 380 * <p/> 381 * This method should only be used if you want to know the raw value. For checking whether 382 * we should ask the user for a passphrase, use isPassphraseRequiredForPreferredDataTypes(). 383 */ getPassphraseType()384 public @PassphraseType int getPassphraseType() { 385 assert isEngineInitialized(); 386 int passphraseType = ProfileSyncServiceJni.get().getPassphraseType( 387 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 388 if (passphraseType < 0 || passphraseType > PassphraseType.MAX_VALUE) { 389 throw new IllegalArgumentException(); 390 } 391 return passphraseType; 392 } 393 394 /** 395 * Returns true if the current explicit passphrase time is defined. 396 */ hasExplicitPassphraseTime()397 public boolean hasExplicitPassphraseTime() { 398 assert isEngineInitialized(); 399 return ProfileSyncServiceJni.get().hasExplicitPassphraseTime( 400 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 401 } 402 403 /** 404 * Returns the current explicit passphrase time in milliseconds since epoch. 405 */ getExplicitPassphraseTime()406 public long getExplicitPassphraseTime() { 407 assert isEngineInitialized(); 408 return ProfileSyncServiceJni.get().getExplicitPassphraseTime( 409 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 410 } 411 getSyncEnterGooglePassphraseBodyWithDateText()412 public String getSyncEnterGooglePassphraseBodyWithDateText() { 413 assert isEngineInitialized(); 414 return ProfileSyncServiceJni.get().getSyncEnterGooglePassphraseBodyWithDateText( 415 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 416 } 417 getSyncEnterCustomPassphraseBodyWithDateText()418 public String getSyncEnterCustomPassphraseBodyWithDateText() { 419 assert isEngineInitialized(); 420 return ProfileSyncServiceJni.get().getSyncEnterCustomPassphraseBodyWithDateText( 421 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 422 } 423 getCurrentSignedInAccountText()424 public String getCurrentSignedInAccountText() { 425 assert isEngineInitialized(); 426 return ProfileSyncServiceJni.get().getCurrentSignedInAccountText( 427 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 428 } 429 getSyncEnterCustomPassphraseBodyText()430 public String getSyncEnterCustomPassphraseBodyText() { 431 return ProfileSyncServiceJni.get().getSyncEnterCustomPassphraseBodyText( 432 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 433 } 434 435 /** 436 * Checks if sync is currently set to use a custom passphrase. The sync engine must be running 437 * (isEngineInitialized() returns true) before calling this function. 438 * 439 * @return true if sync is using a custom passphrase. 440 */ isUsingSecondaryPassphrase()441 public boolean isUsingSecondaryPassphrase() { 442 assert isEngineInitialized(); 443 return ProfileSyncServiceJni.get().isUsingSecondaryPassphrase( 444 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 445 } 446 447 /** 448 * Checks if we need a passphrase to decrypt a currently-enabled data type. This returns false 449 * if a passphrase is needed for a type that is not currently enabled. 450 * 451 * @return true if we need a passphrase. 452 */ isPassphraseRequiredForPreferredDataTypes()453 public boolean isPassphraseRequiredForPreferredDataTypes() { 454 assert isEngineInitialized(); 455 return ProfileSyncServiceJni.get().isPassphraseRequiredForPreferredDataTypes( 456 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 457 } 458 459 /** 460 * Checks if trusted vault encryption keys are needed, independently of the currently-enabled 461 * data types. 462 * 463 * @return true if we need an encryption key. 464 */ isTrustedVaultKeyRequired()465 public boolean isTrustedVaultKeyRequired() { 466 assert isEngineInitialized(); 467 return ProfileSyncServiceJni.get().isTrustedVaultKeyRequired( 468 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 469 } 470 471 /** 472 * Checks if trusted vault encryption keys are needed to decrypt a currently-enabled data type. 473 * 474 * @return true if we need an encryption key for a type that is currently enabled. 475 */ isTrustedVaultKeyRequiredForPreferredDataTypes()476 public boolean isTrustedVaultKeyRequiredForPreferredDataTypes() { 477 assert isEngineInitialized(); 478 return ProfileSyncServiceJni.get().isTrustedVaultKeyRequiredForPreferredDataTypes( 479 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 480 } 481 482 /** 483 * Checks if encrypting all the data types is allowed. 484 * 485 * @return true if encrypting all data types is allowed, false if only passwords are allowed to 486 * be encrypted. 487 */ isEncryptEverythingAllowed()488 public boolean isEncryptEverythingAllowed() { 489 assert isEngineInitialized(); 490 return ProfileSyncServiceJni.get().isEncryptEverythingAllowed( 491 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 492 } 493 494 /** 495 * Checks if the user has chosen to encrypt all data types. Note that some data types (e.g. 496 * DEVICE_INFO) are never encrypted. 497 * 498 * @return true if all data types are encrypted, false if only passwords are encrypted. 499 */ isEncryptEverythingEnabled()500 public boolean isEncryptEverythingEnabled() { 501 assert isEngineInitialized(); 502 return ProfileSyncServiceJni.get().isEncryptEverythingEnabled( 503 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 504 } 505 setEncryptionPassphrase(String passphrase)506 public void setEncryptionPassphrase(String passphrase) { 507 assert isEngineInitialized(); 508 ProfileSyncServiceJni.get().setEncryptionPassphrase( 509 mNativeProfileSyncServiceAndroid, ProfileSyncService.this, passphrase); 510 } 511 setDecryptionPassphrase(String passphrase)512 public boolean setDecryptionPassphrase(String passphrase) { 513 assert isEngineInitialized(); 514 return ProfileSyncServiceJni.get().setDecryptionPassphrase( 515 mNativeProfileSyncServiceAndroid, ProfileSyncService.this, passphrase); 516 } 517 518 /** 519 * Returns whether this client has previously prompted the user for a 520 * passphrase error via the android system notifications. 521 * 522 * Can be called whether or not sync is initialized. 523 * 524 * @return Whether client has prompted for a passphrase error previously. 525 */ isPassphrasePrompted()526 public boolean isPassphrasePrompted() { 527 return ProfileSyncServiceJni.get().isPassphrasePrompted( 528 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 529 } 530 531 /** 532 * Sets whether this client has previously prompted the user for a 533 * passphrase error via the android system notifications. 534 * 535 * Can be called whether or not sync is initialized. 536 * 537 * @param prompted whether the client has prompted the user previously. 538 */ setPassphrasePrompted(boolean prompted)539 public void setPassphrasePrompted(boolean prompted) { 540 ProfileSyncServiceJni.get().setPassphrasePrompted( 541 mNativeProfileSyncServiceAndroid, ProfileSyncService.this, prompted); 542 } 543 544 /** 545 * Sets the the machine tag used by session sync. 546 */ setSessionsId(String sessionTag)547 public void setSessionsId(String sessionTag) { 548 ThreadUtils.assertOnUiThread(); 549 ProfileSyncServiceJni.get().setSyncSessionsId( 550 mNativeProfileSyncServiceAndroid, ProfileSyncService.this, sessionTag); 551 } 552 553 /** 554 * Gets the number of devices known to sync. 555 * 556 * @return number of syncing devices 557 */ getNumberOfSyncedDevices()558 public int getNumberOfSyncedDevices() { 559 return ProfileSyncServiceJni.get().getNumberOfSyncedDevices( 560 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 561 } 562 563 /** 564 * Records TrustedVaultKeyRetrievalTrigger histogram. 565 */ recordKeyRetrievalTrigger(@eyRetrievalTriggerForUMA int keyRetrievalTrigger)566 public void recordKeyRetrievalTrigger(@KeyRetrievalTriggerForUMA int keyRetrievalTrigger) { 567 ProfileSyncServiceJni.get().recordKeyRetrievalTrigger( 568 mNativeProfileSyncServiceAndroid, ProfileSyncService.this, keyRetrievalTrigger); 569 } 570 571 @VisibleForTesting getNativeProfileSyncServiceForTest()572 public long getNativeProfileSyncServiceForTest() { 573 return ProfileSyncServiceJni.get().getProfileSyncServiceForTest( 574 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 575 } 576 577 /** 578 * Returns the time when the last sync cycle was completed. 579 * 580 * @return The difference measured in microseconds, between last sync cycle completion time 581 * and 1 January 1970 00:00:00 UTC. 582 */ 583 @VisibleForTesting getLastSyncedTimeForTest()584 public long getLastSyncedTimeForTest() { 585 return ProfileSyncServiceJni.get().getLastSyncedTimeForTest( 586 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 587 } 588 589 @VisibleForTesting triggerRefresh()590 public void triggerRefresh() { 591 ProfileSyncServiceJni.get().triggerRefresh( 592 mNativeProfileSyncServiceAndroid, ProfileSyncService.this); 593 } 594 595 /** 596 * Callback for getAllNodes. 597 */ 598 public static class GetAllNodesCallback { 599 private String mNodesString; 600 601 // Invoked when getAllNodes completes. onResult(String nodesString)602 public void onResult(String nodesString) { 603 mNodesString = nodesString; 604 } 605 606 // Returns the result of GetAllNodes as a JSONArray. 607 @VisibleForTesting getNodesAsJsonArray()608 public JSONArray getNodesAsJsonArray() throws JSONException { 609 return new JSONArray(mNodesString); 610 } 611 } 612 613 /** 614 * Invokes the onResult method of the callback from native code. 615 */ 616 @CalledByNative onGetAllNodesResult(GetAllNodesCallback callback, String nodes)617 private static void onGetAllNodesResult(GetAllNodesCallback callback, String nodes) { 618 callback.onResult(nodes); 619 } 620 621 /** 622 * Retrieves a JSON version of local Sync data via the native GetAllNodes method. 623 * This method is asynchronous; the result will be sent to the callback. 624 */ 625 @VisibleForTesting getAllNodes(GetAllNodesCallback callback)626 public void getAllNodes(GetAllNodesCallback callback) { 627 ProfileSyncServiceJni.get().getAllNodes( 628 mNativeProfileSyncServiceAndroid, ProfileSyncService.this, callback); 629 } 630 modelTypeArrayToSet(int[] modelTypeArray)631 private static Set<Integer> modelTypeArrayToSet(int[] modelTypeArray) { 632 Set<Integer> modelTypeSet = new HashSet<Integer>(); 633 for (int i = 0; i < modelTypeArray.length; i++) { 634 modelTypeSet.add(modelTypeArray[i]); 635 } 636 return modelTypeSet; 637 } 638 modelTypeSetToArray(Set<Integer> modelTypeSet)639 private static int[] modelTypeSetToArray(Set<Integer> modelTypeSet) { 640 int[] modelTypeArray = new int[modelTypeSet.size()]; 641 int i = 0; 642 for (int modelType : modelTypeSet) { 643 modelTypeArray[i++] = modelType; 644 } 645 return modelTypeArray; 646 } 647 648 @NativeMethods 649 interface Natives { init(ProfileSyncService caller)650 long init(ProfileSyncService caller); 651 requestStart(long nativeProfileSyncServiceAndroid, ProfileSyncService caller)652 void requestStart(long nativeProfileSyncServiceAndroid, ProfileSyncService caller); requestStop(long nativeProfileSyncServiceAndroid, ProfileSyncService caller)653 void requestStop(long nativeProfileSyncServiceAndroid, ProfileSyncService caller); setSyncAllowedByPlatform( long nativeProfileSyncServiceAndroid, ProfileSyncService caller, boolean allowed)654 void setSyncAllowedByPlatform( 655 long nativeProfileSyncServiceAndroid, ProfileSyncService caller, boolean allowed); setSyncSessionsId( long nativeProfileSyncServiceAndroid, ProfileSyncService caller, String tag)656 void setSyncSessionsId( 657 long nativeProfileSyncServiceAndroid, ProfileSyncService caller, String tag); getAuthError(long nativeProfileSyncServiceAndroid, ProfileSyncService caller)658 int getAuthError(long nativeProfileSyncServiceAndroid, ProfileSyncService caller); requiresClientUpgrade( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)659 boolean requiresClientUpgrade( 660 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); setDecoupledFromAndroidMasterSync( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)661 void setDecoupledFromAndroidMasterSync( 662 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getDecoupledFromAndroidMasterSync( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)663 boolean getDecoupledFromAndroidMasterSync( 664 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isAuthenticatedAccountPrimary( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)665 boolean isAuthenticatedAccountPrimary( 666 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isEngineInitialized( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)667 boolean isEngineInitialized( 668 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isEncryptEverythingAllowed( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)669 boolean isEncryptEverythingAllowed( 670 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isEncryptEverythingEnabled( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)671 boolean isEncryptEverythingEnabled( 672 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isTransportStateActive( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)673 boolean isTransportStateActive( 674 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isPassphraseRequiredForPreferredDataTypes( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)675 boolean isPassphraseRequiredForPreferredDataTypes( 676 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isTrustedVaultKeyRequired( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)677 boolean isTrustedVaultKeyRequired( 678 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isTrustedVaultKeyRequiredForPreferredDataTypes( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)679 boolean isTrustedVaultKeyRequiredForPreferredDataTypes( 680 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isUsingSecondaryPassphrase( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)681 boolean isUsingSecondaryPassphrase( 682 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); setDecryptionPassphrase( long nativeProfileSyncServiceAndroid, ProfileSyncService caller, String passphrase)683 boolean setDecryptionPassphrase( 684 long nativeProfileSyncServiceAndroid, ProfileSyncService caller, String passphrase); setEncryptionPassphrase( long nativeProfileSyncServiceAndroid, ProfileSyncService caller, String passphrase)685 void setEncryptionPassphrase( 686 long nativeProfileSyncServiceAndroid, ProfileSyncService caller, String passphrase); getPassphraseType(long nativeProfileSyncServiceAndroid, ProfileSyncService caller)687 int getPassphraseType(long nativeProfileSyncServiceAndroid, ProfileSyncService caller); hasExplicitPassphraseTime( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)688 boolean hasExplicitPassphraseTime( 689 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getExplicitPassphraseTime( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)690 long getExplicitPassphraseTime( 691 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getSyncEnterGooglePassphraseBodyWithDateText( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)692 String getSyncEnterGooglePassphraseBodyWithDateText( 693 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getSyncEnterCustomPassphraseBodyWithDateText( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)694 String getSyncEnterCustomPassphraseBodyWithDateText( 695 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getCurrentSignedInAccountText( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)696 String getCurrentSignedInAccountText( 697 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getSyncEnterCustomPassphraseBodyText( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)698 String getSyncEnterCustomPassphraseBodyText( 699 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getNumberOfSyncedDevices( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)700 int getNumberOfSyncedDevices( 701 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getActiveDataTypes(long nativeProfileSyncServiceAndroid, ProfileSyncService caller)702 int[] getActiveDataTypes(long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getChosenDataTypes(long nativeProfileSyncServiceAndroid, ProfileSyncService caller)703 int[] getChosenDataTypes(long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getPreferredDataTypes( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)704 int[] getPreferredDataTypes( 705 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); setChosenDataTypes(long nativeProfileSyncServiceAndroid, ProfileSyncService caller, boolean syncEverything, int[] modelTypeArray)706 void setChosenDataTypes(long nativeProfileSyncServiceAndroid, ProfileSyncService caller, 707 boolean syncEverything, int[] modelTypeArray); triggerRefresh(long nativeProfileSyncServiceAndroid, ProfileSyncService caller)708 void triggerRefresh(long nativeProfileSyncServiceAndroid, ProfileSyncService caller); setSetupInProgress(long nativeProfileSyncServiceAndroid, ProfileSyncService caller, boolean inProgress)709 void setSetupInProgress(long nativeProfileSyncServiceAndroid, ProfileSyncService caller, 710 boolean inProgress); setFirstSetupComplete(long nativeProfileSyncServiceAndroid, ProfileSyncService caller, int syncFirstSetupCompleteSource)711 void setFirstSetupComplete(long nativeProfileSyncServiceAndroid, ProfileSyncService caller, 712 int syncFirstSetupCompleteSource); isFirstSetupComplete( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)713 boolean isFirstSetupComplete( 714 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isSyncRequested(long nativeProfileSyncServiceAndroid, ProfileSyncService caller)715 boolean isSyncRequested(long nativeProfileSyncServiceAndroid, ProfileSyncService caller); canSyncFeatureStart( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)716 boolean canSyncFeatureStart( 717 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isSyncActive(long nativeProfileSyncServiceAndroid, ProfileSyncService caller)718 boolean isSyncActive(long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isSyncDisabledByEnterprisePolicy( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)719 boolean isSyncDisabledByEnterprisePolicy( 720 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); hasKeepEverythingSynced( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)721 boolean hasKeepEverythingSynced( 722 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); hasUnrecoverableError( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)723 boolean hasUnrecoverableError( 724 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); isPassphrasePrompted( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)725 boolean isPassphrasePrompted( 726 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); setPassphrasePrompted( long nativeProfileSyncServiceAndroid, ProfileSyncService caller, boolean prompted)727 void setPassphrasePrompted( 728 long nativeProfileSyncServiceAndroid, ProfileSyncService caller, boolean prompted); getProfileSyncServiceForTest( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)729 long getProfileSyncServiceForTest( 730 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getLastSyncedTimeForTest( long nativeProfileSyncServiceAndroid, ProfileSyncService caller)731 long getLastSyncedTimeForTest( 732 long nativeProfileSyncServiceAndroid, ProfileSyncService caller); getAllNodes(long nativeProfileSyncServiceAndroid, ProfileSyncService caller, GetAllNodesCallback callback)733 void getAllNodes(long nativeProfileSyncServiceAndroid, ProfileSyncService caller, 734 GetAllNodesCallback callback); recordKeyRetrievalTrigger(long nativeProfileSyncServiceAndroid, ProfileSyncService caller, int keyRetrievalTrigger)735 void recordKeyRetrievalTrigger(long nativeProfileSyncServiceAndroid, 736 ProfileSyncService caller, int keyRetrievalTrigger); 737 } 738 } 739