Commit cdd2cdd8 authored by Victor Hugo Vianna Silva's avatar Victor Hugo Vianna Silva Committed by Commit Bot

Decouple Sync from Android master sync as soon as master sync is enabled

This CL modifies the behavior of the DecoupleSyncFromAndroidMasterSync
feature. When the feature is enabled, Sync will only decouple from
master sync and be re-enabled once the master toggle is first re-enabled.
The fact that the decoupling happened is persisted using the APIs from
crrev.com/c/2398524.

We also do some non-related code brush up:
- Shorten the implementation of some methods in AndroidSyncSettingsUtils.
- Deprecate one test constructor of AndroidSyncSettings.
- Add missing assertOnUiThread() to the methods to add/remove an
observer in AndroidSyncSettings.
- Restrict AndroidSyncSettingsTest#testAccountInitialization to the
case where the feature is disabled, which should have been done in
crrev.com/c/2366895.

Bug: 1125622
Change-Id: Ia37a1075b159754337c3c7308d9b789b8008ec21
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2398504
Commit-Queue: Victor Vianna <victorvianna@google.com>
Reviewed-by: default avatarBoris Sazonov <bsazonov@chromium.org>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Cr-Commit-Position: refs/heads/master@{#810274}
parent 1f34bc50
...@@ -56,6 +56,8 @@ public class AndroidSyncSettings { ...@@ -56,6 +56,8 @@ public class AndroidSyncSettings {
private boolean mMasterSyncEnabled; private boolean mMasterSyncEnabled;
private boolean mShouldDecoupleSyncFromMasterSync;
private final ObserverList<AndroidSyncSettingsObserver> mObservers = new ObserverList<>(); private final ObserverList<AndroidSyncSettingsObserver> mObservers = new ObserverList<>();
/** /**
...@@ -87,14 +89,16 @@ public class AndroidSyncSettings { ...@@ -87,14 +89,16 @@ public class AndroidSyncSettings {
sInstance = instance; sInstance = instance;
} }
/**
* @param account The sync account if sync is enabled, null otherwise.
*/
// TODO(crbug.com/1125622): Exposing these testing constructors that don't register the // TODO(crbug.com/1125622): Exposing these testing constructors that don't register the
// singleton instance can be dangerous when there's code that explicitly calls |get()| // singleton instance can be dangerous when there's code that explicitly calls |get()|
// (in that case, a new object would be returned, not the one constructed by the test). // (in that case, a new object would be returned, not the one constructed by the test).
// Consider exposing them as static methods that also register a singleton instance. // Consider exposing them as static methods that also register a singleton instance.
/**
* WARNING: Consider using |overrideForTests()| to inject a mock instead.
* @param account The sync account if sync is enabled, null otherwise.
*/
@VisibleForTesting @VisibleForTesting
@Deprecated
public AndroidSyncSettings(@Nullable Account account) { public AndroidSyncSettings(@Nullable Account account) {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
mContractAuthority = getContractAuthority(); mContractAuthority = getContractAuthority();
...@@ -104,6 +108,14 @@ public class AndroidSyncSettings { ...@@ -104,6 +108,14 @@ public class AndroidSyncSettings {
updateCachedSettings(); updateCachedSettings();
updateSyncability(); updateSyncability();
ProfileSyncService syncService = ProfileSyncService.get();
if (syncService != null
&& ChromeFeatureList.isEnabled(
ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC)) {
// Read initial persisted value.
mShouldDecoupleSyncFromMasterSync = syncService.getDecoupledFromAndroidMasterSync();
}
SyncStatusObserver androidOsListener = new SyncStatusObserver() { SyncStatusObserver androidOsListener = new SyncStatusObserver() {
@Override @Override
public void onStatusChanged(int which) { public void onStatusChanged(int which) {
...@@ -153,9 +165,7 @@ public class AndroidSyncSettings { ...@@ -153,9 +165,7 @@ public class AndroidSyncSettings {
*/ */
public boolean doesMasterSyncSettingAllowChromeSync() { public boolean doesMasterSyncSettingAllowChromeSync() {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
return mMasterSyncEnabled return mMasterSyncEnabled || mShouldDecoupleSyncFromMasterSync;
|| ChromeFeatureList.isEnabled(
ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC);
} }
/** /**
...@@ -200,6 +210,7 @@ public class AndroidSyncSettings { ...@@ -200,6 +210,7 @@ public class AndroidSyncSettings {
* Add a new AndroidSyncSettingsObserver. * Add a new AndroidSyncSettingsObserver.
*/ */
public void registerObserver(AndroidSyncSettingsObserver observer) { public void registerObserver(AndroidSyncSettingsObserver observer) {
ThreadUtils.assertOnUiThread();
mObservers.addObserver(observer); mObservers.addObserver(observer);
} }
...@@ -207,6 +218,7 @@ public class AndroidSyncSettings { ...@@ -207,6 +218,7 @@ public class AndroidSyncSettings {
* Remove an AndroidSyncSettingsObserver that was previously added. * Remove an AndroidSyncSettingsObserver that was previously added.
*/ */
public void unregisterObserver(AndroidSyncSettingsObserver observer) { public void unregisterObserver(AndroidSyncSettingsObserver observer) {
ThreadUtils.assertOnUiThread();
mObservers.removeObserver(observer); mObservers.removeObserver(observer);
} }
...@@ -262,7 +274,8 @@ public class AndroidSyncSettings { ...@@ -262,7 +274,8 @@ public class AndroidSyncSettings {
} }
/** /**
* Update the three cached settings from the content resolver. * Update the three cached settings from the content resolver and the
* master sync decoupling setting.
* *
* @return Whether either chromeSyncEnabled or masterSyncEnabled changed. * @return Whether either chromeSyncEnabled or masterSyncEnabled changed.
*/ */
...@@ -284,6 +297,17 @@ public class AndroidSyncSettings { ...@@ -284,6 +297,17 @@ public class AndroidSyncSettings {
mMasterSyncEnabled = mSyncContentResolverDelegate.getMasterSyncAutomatically(); mMasterSyncEnabled = mSyncContentResolverDelegate.getMasterSyncAutomatically();
} }
if (mAccount != null && ProfileSyncService.get() != null
&& ChromeFeatureList.isEnabled(
ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC)
&& mMasterSyncEnabled && !mShouldDecoupleSyncFromMasterSync) {
// Re-enabling master sync at least once should cause Sync to no longer care whether
// the former is enabled or not. This fact should be persisted via ProfileSyncService
// so it's known on the next startup.
mShouldDecoupleSyncFromMasterSync = true;
ProfileSyncService.get().setDecoupledFromAndroidMasterSync();
}
return oldChromeSyncEnabled != mChromeSyncEnabled return oldChromeSyncEnabled != mChromeSyncEnabled
|| oldMasterSyncEnabled != mMasterSyncEnabled; || oldMasterSyncEnabled != mMasterSyncEnabled;
} }
......
...@@ -88,6 +88,7 @@ public class ProfileSyncService { ...@@ -88,6 +88,7 @@ public class ProfileSyncService {
*/ */
@VisibleForTesting @VisibleForTesting
public static void overrideForTests(ProfileSyncService profileSyncService) { public static void overrideForTests(ProfileSyncService profileSyncService) {
ThreadUtils.assertOnUiThread();
sProfileSyncService = profileSyncService; sProfileSyncService = profileSyncService;
sInitialized = true; sInitialized = true;
} }
......
...@@ -9,6 +9,10 @@ import static androidx.test.espresso.action.ViewActions.click; ...@@ -9,6 +9,10 @@ import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.matcher.ViewMatchers.withText; import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
import static org.chromium.components.browser_ui.widget.highlight.ViewHighlighterTestUtils.checkHighlightOff; import static org.chromium.components.browser_ui.widget.highlight.ViewHighlighterTestUtils.checkHighlightOff;
import static org.chromium.components.browser_ui.widget.highlight.ViewHighlighterTestUtils.checkHighlightPulse; import static org.chromium.components.browser_ui.widget.highlight.ViewHighlighterTestUtils.checkHighlightPulse;
...@@ -35,6 +39,9 @@ import org.junit.BeforeClass; ...@@ -35,6 +39,9 @@ import org.junit.BeforeClass;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.chromium.base.ActivityState; import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus; import org.chromium.base.ApplicationStatus;
...@@ -59,7 +66,8 @@ import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksShim; ...@@ -59,7 +66,8 @@ import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksShim;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.sync.AndroidSyncSettingsTestUtils; import org.chromium.chrome.browser.sync.AndroidSyncSettings;
import org.chromium.chrome.browser.sync.AndroidSyncSettings.AndroidSyncSettingsObserver;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
...@@ -106,6 +114,8 @@ public class BookmarkTest { ...@@ -106,6 +114,8 @@ public class BookmarkTest {
@Rule @Rule
public ChromeRenderTestRule mRenderTestRule = public ChromeRenderTestRule mRenderTestRule =
ChromeRenderTestRule.Builder.withPublicCorpus().build(); ChromeRenderTestRule.Builder.withPublicCorpus().build();
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private static final String TEST_PAGE_URL_GOOGLE = "/chrome/test/data/android/google.html"; private static final String TEST_PAGE_URL_GOOGLE = "/chrome/test/data/android/google.html";
private static final String TEST_PAGE_TITLE_GOOGLE = "The Google"; private static final String TEST_PAGE_TITLE_GOOGLE = "The Google";
...@@ -125,6 +135,8 @@ public class BookmarkTest { ...@@ -125,6 +135,8 @@ public class BookmarkTest {
private String mTestPageFoo; private String mTestPageFoo;
private EmbeddedTestServer mTestServer; private EmbeddedTestServer mTestServer;
private @Nullable BookmarkActivity mBookmarkActivity; private @Nullable BookmarkActivity mBookmarkActivity;
@Mock
private AndroidSyncSettings mAndroidSyncSettings;
@BeforeClass @BeforeClass
public static void setUpBeforeActivityLaunched() { public static void setUpBeforeActivityLaunched() {
...@@ -145,8 +157,17 @@ public class BookmarkTest { ...@@ -145,8 +157,17 @@ public class BookmarkTest {
mActivityTestRule.getActivity().getActivityTab().getWebContents())); mActivityTestRule.getActivity().getActivityTab().getWebContents()));
mBookmarkBridge = mActivityTestRule.getActivity().getBookmarkBridgeForTesting(); mBookmarkBridge = mActivityTestRule.getActivity().getBookmarkBridgeForTesting();
// Stub Android master sync state to make sure promos aren't suppressed. // Stub AndroidSyncSettings state to make sure promos aren't suppressed.
AndroidSyncSettingsTestUtils.setUpAndroidSyncSettingsForTesting(); when(mAndroidSyncSettings.doesMasterSyncSettingAllowChromeSync()).thenReturn(true);
when(mAndroidSyncSettings.isSyncEnabled()).thenReturn(false);
when(mAndroidSyncSettings.isChromeSyncEnabled()).thenReturn(false);
doNothing()
.when(mAndroidSyncSettings)
.registerObserver(any(AndroidSyncSettingsObserver.class));
doNothing()
.when(mAndroidSyncSettings)
.unregisterObserver(any(AndroidSyncSettingsObserver.class));
AndroidSyncSettings.overrideForTests(mAndroidSyncSettings);
}); });
mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
mTestPage = mTestServer.getURL(TEST_PAGE_URL_GOOGLE); mTestPage = mTestServer.getURL(TEST_PAGE_URL_GOOGLE);
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
package org.chromium.chrome.browser.sync; package org.chromium.chrome.browser.sync;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.chromium.chrome.browser.sync.AndroidSyncSettingsTestUtils.getDoesMasterSyncAllowSyncOnUiThread; import static org.chromium.chrome.browser.sync.AndroidSyncSettingsTestUtils.getDoesMasterSyncAllowSyncOnUiThread;
import static org.chromium.chrome.browser.sync.AndroidSyncSettingsTestUtils.getIsChromeSyncEnabledOnUiThread; import static org.chromium.chrome.browser.sync.AndroidSyncSettingsTestUtils.getIsChromeSyncEnabledOnUiThread;
import static org.chromium.chrome.browser.sync.AndroidSyncSettingsTestUtils.getIsSyncEnabledOnUiThread; import static org.chromium.chrome.browser.sync.AndroidSyncSettingsTestUtils.getIsSyncEnabledOnUiThread;
...@@ -20,8 +24,10 @@ import org.junit.Rule; ...@@ -20,8 +24,10 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TestRule; import org.junit.rules.TestRule;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.chromium.base.FeatureList;
import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeFeatureList;
...@@ -116,21 +122,25 @@ public class AndroidSyncSettingsTest { ...@@ -116,21 +122,25 @@ public class AndroidSyncSettingsTest {
@Rule @Rule
public TestRule mChromeBrowserRule = new ChromeBrowserTestRule(); public TestRule mChromeBrowserRule = new ChromeBrowserTestRule();
@Rule @Rule
public TestRule mProcessorRule = new Features.JUnitProcessor(); public TestRule mProcessorRule = new Features.InstrumentationProcessor();
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private AndroidSyncSettings mAndroidSyncSettings; private AndroidSyncSettings mAndroidSyncSettings;
private CountingMockSyncContentResolverDelegate mSyncContentResolverDelegate; private CountingMockSyncContentResolverDelegate mSyncContentResolverDelegate;
@Mock
private ProfileSyncService mProfileSyncService;
private Account mAccount; private Account mAccount;
private Account mAlternateAccount; private Account mAlternateAccount;
private String mAuthority = AndroidSyncSettings.getContractAuthority(); private String mAuthority = AndroidSyncSettings.getContractAuthority();
@Before @Before
public void setUp() { public void setUp() {
FeatureList.setTestCanUseDefaultsForTesting();
mSyncContentResolverDelegate = new CountingMockSyncContentResolverDelegate(); mSyncContentResolverDelegate = new CountingMockSyncContentResolverDelegate();
TestThreadUtils.runOnUiThreadBlocking( TestThreadUtils.runOnUiThreadBlocking(() -> {
() -> SyncContentResolverDelegate.overrideForTests(mSyncContentResolverDelegate)); SyncContentResolverDelegate.overrideForTests(mSyncContentResolverDelegate);
ProfileSyncService.overrideForTests(mProfileSyncService);
});
FakeAccountManagerFacade fakeAccountManagerFacade = new FakeAccountManagerFacade(null); FakeAccountManagerFacade fakeAccountManagerFacade = new FakeAccountManagerFacade(null);
AccountManagerFacadeProvider.setInstanceForTests(fakeAccountManagerFacade); AccountManagerFacadeProvider.setInstanceForTests(fakeAccountManagerFacade);
...@@ -156,16 +166,6 @@ public class AndroidSyncSettingsTest { ...@@ -156,16 +166,6 @@ public class AndroidSyncSettingsTest {
} }
} }
private void setMasterSyncAllowsChromeSync() {
if (!ChromeFeatureList.isEnabled(
ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC)) {
mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
Assert.assertTrue(getDoesMasterSyncAllowSyncOnUiThread());
}
// If DecoupleSyncFromAndroidMasterSync is enabled, no need for any
// setup since master sync doesn't influence sync.
}
@After @After
public void tearDown() { public void tearDown() {
AccountManagerFacadeProvider.resetInstanceForTests(); AccountManagerFacadeProvider.resetInstanceForTests();
...@@ -174,6 +174,7 @@ public class AndroidSyncSettingsTest { ...@@ -174,6 +174,7 @@ public class AndroidSyncSettingsTest {
@Test @Test
@SmallTest @SmallTest
@Feature({"Sync"}) @Feature({"Sync"})
@Features.DisableFeatures(ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC)
public void testAccountInitialization() { public void testAccountInitialization() {
createAndroidSyncSettings(); createAndroidSyncSettings();
...@@ -250,9 +251,9 @@ public class AndroidSyncSettingsTest { ...@@ -250,9 +251,9 @@ public class AndroidSyncSettingsTest {
@SmallTest @SmallTest
@Feature({"Sync"}) @Feature({"Sync"})
public void testToggleAccountSyncFromApplication() { public void testToggleAccountSyncFromApplication() {
createAndroidSyncSettings(); mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
setMasterSyncAllowsChromeSync(); createAndroidSyncSettings();
TestThreadUtils.runOnUiThreadBlocking(() -> mAndroidSyncSettings.enableChromeSync()); TestThreadUtils.runOnUiThreadBlocking(() -> mAndroidSyncSettings.enableChromeSync());
Assert.assertTrue(getIsSyncEnabledOnUiThread()); Assert.assertTrue(getIsSyncEnabledOnUiThread());
...@@ -265,9 +266,9 @@ public class AndroidSyncSettingsTest { ...@@ -265,9 +266,9 @@ public class AndroidSyncSettingsTest {
@SmallTest @SmallTest
@Feature({"Sync"}) @Feature({"Sync"})
public void testToggleSyncabilityForMultipleAccounts() { public void testToggleSyncabilityForMultipleAccounts() {
createAndroidSyncSettings(); mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
setMasterSyncAllowsChromeSync(); createAndroidSyncSettings();
TestThreadUtils.runOnUiThreadBlocking(() -> { TestThreadUtils.runOnUiThreadBlocking(() -> {
mAndroidSyncSettings.enableChromeSync(); mAndroidSyncSettings.enableChromeSync();
...@@ -292,9 +293,9 @@ public class AndroidSyncSettingsTest { ...@@ -292,9 +293,9 @@ public class AndroidSyncSettingsTest {
@SmallTest @SmallTest
@Feature({"Sync"}) @Feature({"Sync"})
public void testSyncSettingsCaching() { public void testSyncSettingsCaching() {
createAndroidSyncSettings(); mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
setMasterSyncAllowsChromeSync(); createAndroidSyncSettings();
TestThreadUtils.runOnUiThreadBlocking(() -> { TestThreadUtils.runOnUiThreadBlocking(() -> {
mAndroidSyncSettings.enableChromeSync(); mAndroidSyncSettings.enableChromeSync();
...@@ -418,20 +419,71 @@ public class AndroidSyncSettingsTest { ...@@ -418,20 +419,71 @@ public class AndroidSyncSettingsTest {
@SmallTest @SmallTest
@Feature({"Sync"}) @Feature({"Sync"})
@Features.EnableFeatures(ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC) @Features.EnableFeatures(ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC)
// TODO(crbug.com/1105795): Remove this test after DecoupleSyncFromAndroidMasterSync has public void testMasterSyncAllowsSyncIfReEnabledOnce() {
// launched, since testToggleChromeSyncFromSettings() covers the same functionality. // Master sync is disabled on startup and the user hasn't gone through the decoupling flow
public void testSyncStateDoesNotDependOnMasterSync() { // in the past.
mSyncContentResolverDelegate.setMasterSyncAutomatically(false); mSyncContentResolverDelegate.setMasterSyncAutomatically(false);
mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, true);
TestThreadUtils.runOnUiThreadBlocking(() -> {
when(mProfileSyncService.getDecoupledFromAndroidMasterSync()).thenReturn(false);
});
// Sync must remain disabled as long as master sync is not re-enabled.
createAndroidSyncSettings(); createAndroidSyncSettings();
Assert.assertFalse(getDoesMasterSyncAllowSyncOnUiThread());
Assert.assertFalse(getIsSyncEnabledOnUiThread());
mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, true); // Re-enable master sync at least once. Sync is now re-enabled and decoupled from master
Assert.assertTrue(getIsChromeSyncEnabledOnUiThread()); // sync.
TestThreadUtils.runOnUiThreadBlocking(
() -> doNothing().when(mProfileSyncService).setDecoupledFromAndroidMasterSync());
mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
Assert.assertTrue(getDoesMasterSyncAllowSyncOnUiThread()); Assert.assertTrue(getDoesMasterSyncAllowSyncOnUiThread());
Assert.assertTrue(getIsSyncEnabledOnUiThread()); Assert.assertTrue(getIsSyncEnabledOnUiThread());
TestThreadUtils.runOnUiThreadBlocking(
() -> verify(mProfileSyncService).setDecoupledFromAndroidMasterSync());
mSyncContentResolverDelegate.setMasterSyncAutomatically(false);
Assert.assertTrue(getDoesMasterSyncAllowSyncOnUiThread());
Assert.assertTrue(getIsSyncEnabledOnUiThread());
}
mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, false); @Test
Assert.assertFalse(getIsChromeSyncEnabledOnUiThread()); @SmallTest
@Feature({"Sync"})
@Features.EnableFeatures(ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC)
public void testSyncStateRespectsPersistedDecouplingStateIfFeatureEnabled() {
// Master sync is disabled on startup, but the user has gone through the decoupling flow in
// the past and has the DecoupleSyncFromAndroidMasterSync feature enabled.
mSyncContentResolverDelegate.setMasterSyncAutomatically(false);
mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, true);
TestThreadUtils.runOnUiThreadBlocking(() -> {
when(mProfileSyncService.getDecoupledFromAndroidMasterSync()).thenReturn(true);
});
// Chrome becomes aware of the previous decoupling, so Sync can be enabled despite master
// sync being disabled.
createAndroidSyncSettings();
Assert.assertTrue(getDoesMasterSyncAllowSyncOnUiThread()); Assert.assertTrue(getDoesMasterSyncAllowSyncOnUiThread());
Assert.assertTrue(getIsSyncEnabledOnUiThread());
}
@Test
@SmallTest
@Feature({"Sync"})
@Features.DisableFeatures(ChromeFeatureList.DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC)
public void testSyncStateDoesNotRespectPersistedDecouplingStateIfFeatureDisabled() {
// The user went through the master sync decoupling flow in the past, but has the
// DecoupleSyncFromAndroidMasterSync feature disabled.
mSyncContentResolverDelegate.setMasterSyncAutomatically(false);
mSyncContentResolverDelegate.setSyncAutomatically(mAccount, mAuthority, true);
TestThreadUtils.runOnUiThreadBlocking(() -> {
when(mProfileSyncService.getDecoupledFromAndroidMasterSync()).thenReturn(true);
});
// Chrome should ignore that a previous decoupling happened. Sync should again respect
// master sync and stay disabled.
createAndroidSyncSettings();
Assert.assertFalse(getDoesMasterSyncAllowSyncOnUiThread());
Assert.assertFalse(getIsSyncEnabledOnUiThread()); Assert.assertFalse(getIsSyncEnabledOnUiThread());
} }
} }
...@@ -9,16 +9,13 @@ import androidx.annotation.VisibleForTesting; ...@@ -9,16 +9,13 @@ import androidx.annotation.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.util.concurrent.Callable;
/** /**
* A utility class for mocking AndroidSyncSettings. * A utility class for mocking AndroidSyncSettings.
*/ */
public class AndroidSyncSettingsTestUtils { public class AndroidSyncSettingsTestUtils {
/** /**
* Sets up AndroidSyncSettings with a mock SyncContentResolverDelegate and with Android's master * Sets up a MockSyncContentResolverDelegate with Android's master sync setting enabled.
* sync setting enabled. (This setting is found, e.g., under Settings > Accounts & Sync > * (This setting is found, e.g., under Settings > Accounts & Sync > Auto-sync data.)
* Auto-sync data.)
*/ */
@CalledByNative @CalledByNative
@VisibleForTesting @VisibleForTesting
...@@ -27,36 +24,20 @@ public class AndroidSyncSettingsTestUtils { ...@@ -27,36 +24,20 @@ public class AndroidSyncSettingsTestUtils {
delegate.setMasterSyncAutomatically(true); delegate.setMasterSyncAutomatically(true);
TestThreadUtils.runOnUiThreadBlocking( TestThreadUtils.runOnUiThreadBlocking(
() -> SyncContentResolverDelegate.overrideForTests(delegate)); () -> SyncContentResolverDelegate.overrideForTests(delegate));
// Explicitly pass null account to AndroidSyncSettings ctor. Normally, AndroidSyncSettings
// ctor uses IdentityManager to get the sync account, but some native tests call this method
// before profiles are initialized (when IdentityManager doesn't exist yet).
AndroidSyncSettings.overrideForTests(new AndroidSyncSettings(null));
} }
public static boolean getIsSyncEnabledOnUiThread() { public static boolean getIsSyncEnabledOnUiThread() {
return TestThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() { return TestThreadUtils.runOnUiThreadBlockingNoException(
@Override () -> AndroidSyncSettings.get().isSyncEnabled());
public Boolean call() {
return AndroidSyncSettings.get().isSyncEnabled();
}
});
} }
public static boolean getIsChromeSyncEnabledOnUiThread() { public static boolean getIsChromeSyncEnabledOnUiThread() {
return TestThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() { return TestThreadUtils.runOnUiThreadBlockingNoException(
@Override () -> AndroidSyncSettings.get().isChromeSyncEnabled());
public Boolean call() {
return AndroidSyncSettings.get().isChromeSyncEnabled();
}
});
} }
public static boolean getDoesMasterSyncAllowSyncOnUiThread() { public static boolean getDoesMasterSyncAllowSyncOnUiThread() {
return TestThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() { return TestThreadUtils.runOnUiThreadBlockingNoException(
@Override () -> AndroidSyncSettings.get().doesMasterSyncSettingAllowChromeSync());
public Boolean call() {
return AndroidSyncSettings.get().doesMasterSyncSettingAllowChromeSync();
}
});
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment