Commit ef4c2d2d authored by Marc Treib's avatar Marc Treib Committed by Commit Bot

Delete more unused Android invalidations code

The whole folder components/sync/notifier was part of the old
invalidations system and can go away:
InvalidationPreferences and InvalidationIntentProtocol were trivially
unused.
InvalidationClientNameProvider/Generator and its implementations were
not fully unused: A global provider instance was set up with a
generator, but it was never actually used.

Bug: 1029481
Change-Id: I490620d1a75e1fa66993788e9b1f1ff79d7fe3a4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2266957
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
Auto-Submit: Marc Treib <treib@chromium.org>
Reviewed-by: default avatarMikel Astiz <mastiz@chromium.org>
Reviewed-by: default avatarTommy Nyquist <nyquist@chromium.org>
Cr-Commit-Position: refs/heads/master@{#782916}
parent e493c6f3
...@@ -1050,7 +1050,6 @@ android_library("chrome_test_java") { ...@@ -1050,7 +1050,6 @@ android_library("chrome_test_java") {
"//components/signin/public/android:java", "//components/signin/public/android:java",
"//components/sync:sync_java_test_support", "//components/sync:sync_java_test_support",
"//components/sync/android:sync_java", "//components/sync/android:sync_java",
"//components/sync/android:sync_javatests",
"//components/sync/protocol:protocol_java", "//components/sync/protocol:protocol_java",
"//components/url_formatter/android:url_formatter_java", "//components/url_formatter/android:url_formatter_java",
"//components/user_prefs/android:java", "//components/user_prefs/android:java",
......
...@@ -873,7 +873,6 @@ chrome_java_sources = [ ...@@ -873,7 +873,6 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterService.java", "java/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterService.java",
"java/src/org/chromium/chrome/browser/invalidation/ResumableDelayedTaskRunner.java", "java/src/org/chromium/chrome/browser/invalidation/ResumableDelayedTaskRunner.java",
"java/src/org/chromium/chrome/browser/invalidation/SessionsInvalidationManager.java", "java/src/org/chromium/chrome/browser/invalidation/SessionsInvalidationManager.java",
"java/src/org/chromium/chrome/browser/invalidation/UniqueIdInvalidationClientNameGenerator.java",
"java/src/org/chromium/chrome/browser/language/LanguageAskPrompt.java", "java/src/org/chromium/chrome/browser/language/LanguageAskPrompt.java",
"java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java", "java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java",
"java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java", "java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java",
......
...@@ -55,7 +55,6 @@ import org.chromium.chrome.browser.homepage.HomepageManager; ...@@ -55,7 +55,6 @@ import org.chromium.chrome.browser.homepage.HomepageManager;
import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory; import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory;
import org.chromium.chrome.browser.identity.UuidBasedUniqueIdentificationGenerator; import org.chromium.chrome.browser.identity.UuidBasedUniqueIdentificationGenerator;
import org.chromium.chrome.browser.incognito.IncognitoTabLauncher; import org.chromium.chrome.browser.incognito.IncognitoTabLauncher;
import org.chromium.chrome.browser.invalidation.UniqueIdInvalidationClientNameGenerator;
import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.locale.LocaleManager;
import org.chromium.chrome.browser.media.MediaCaptureNotificationService; import org.chromium.chrome.browser.media.MediaCaptureNotificationService;
import org.chromium.chrome.browser.media.MediaViewerUtils; import org.chromium.chrome.browser.media.MediaViewerUtils;
...@@ -169,11 +168,6 @@ public class ProcessInitializationHandler { ...@@ -169,11 +168,6 @@ public class ProcessInitializationHandler {
AccountManagerFacadeProvider.setInstance( AccountManagerFacadeProvider.setInstance(
new AccountManagerFacadeImpl(AppHooks.get().createAccountManagerDelegate())); new AccountManagerFacadeImpl(AppHooks.get().createAccountManagerDelegate()));
// Set the unique identification generator for invalidations. The
// invalidations system can start and attempt to fetch the client ID
// very early. We need this generator to be ready before that happens.
UniqueIdInvalidationClientNameGenerator.doInitializeAndInstallGenerator(application);
// Set minimum Tango log level. This sets an in-memory static field, and needs to be // Set minimum Tango log level. This sets an in-memory static field, and needs to be
// set in the ApplicationContext instead of an activity, since Tango can be woken up // set in the ApplicationContext instead of an activity, since Tango can be woken up
// by the system directly though messages from GCM. // by the system directly though messages from GCM.
......
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.invalidation;
import android.content.Context;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.browser.identity.UniqueIdentificationGenerator;
import org.chromium.chrome.browser.identity.UuidBasedUniqueIdentificationGenerator;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.components.sync.notifier.InvalidationClientNameGenerator;
import org.chromium.components.sync.notifier.InvalidationClientNameProvider;
/**
* An InvalidationClientNameGenerator that wraps an UniqueIdentificationGenerator.
*
* If the right kind of UniqueIdentificationGenerator is provided, then this will produce IDs that
* are unique and consistent across restarts.
*/
public class UniqueIdInvalidationClientNameGenerator implements InvalidationClientNameGenerator {
/**
* Called during early init to make this InvalidationClientNameGenerator the default.
*
* This should be called very early during initialization to setup the invalidation client name.
*/
public static void doInitializeAndInstallGenerator(Context context) {
UniqueIdentificationGenerator idGenerator = new UuidBasedUniqueIdentificationGenerator(
context, ChromePreferenceKeys.INVALIDATIONS_UUID_PREF_KEY);
InvalidationClientNameGenerator clientNameGenerator =
new UniqueIdInvalidationClientNameGenerator(idGenerator);
InvalidationClientNameProvider.get().setPreferredClientNameGenerator(clientNameGenerator);
}
private final UniqueIdentificationGenerator mGenerator;
UniqueIdInvalidationClientNameGenerator(UniqueIdentificationGenerator generator) {
mGenerator = generator;
}
@Override
public byte[] generateInvalidatorClientName() {
return ApiCompatibilityUtils.getBytesUtf8(mGenerator.getUniqueId(null));
}
}
...@@ -459,11 +459,6 @@ public final class ChromePreferenceKeys { ...@@ -459,11 +459,6 @@ public final class ChromePreferenceKeys {
public static final String INCOGNITO_SHORTCUT_ADDED = "incognito-shortcut-added"; public static final String INCOGNITO_SHORTCUT_ADDED = "incognito-shortcut-added";
/**
* Key for UUID-based generator used for Chrome Invalidations (sync, etc.).
*/
public static final String INVALIDATIONS_UUID_PREF_KEY = "chromium.invalidations.uuid";
/** /**
* When the user is shown a badge that the current Android OS version is unsupported, and they * When the user is shown a badge that the current Android OS version is unsupported, and they
* tap it to display the menu (which has additional information), we store the current version * tap it to display the menu (which has additional information), we store the current version
......
...@@ -47,6 +47,7 @@ public class DeprecatedChromePreferenceKeys { ...@@ -47,6 +47,7 @@ public class DeprecatedChromePreferenceKeys {
"chrome_home_opt_out_snackbar_shown", "chrome_home_opt_out_snackbar_shown",
"chrome_home_user_enabled", "chrome_home_user_enabled",
"chrome_modern_design_enabled", "chrome_modern_design_enabled",
"chromium.invalidations.uuid",
"click_to_call_open_dialer_directly", "click_to_call_open_dialer_directly",
"crash_dump_upload", "crash_dump_upload",
"crash_dump_upload_no_cellular", "crash_dump_upload_no_cellular",
......
...@@ -109,7 +109,6 @@ public class GrandfatheredChromePreferenceKeys { ...@@ -109,7 +109,6 @@ public class GrandfatheredChromePreferenceKeys {
ChromePreferenceKeys.HOMEPAGE_ENABLED, ChromePreferenceKeys.HOMEPAGE_ENABLED,
ChromePreferenceKeys.HOMEPAGE_USE_DEFAULT_URI, ChromePreferenceKeys.HOMEPAGE_USE_DEFAULT_URI,
ChromePreferenceKeys.INCOGNITO_SHORTCUT_ADDED, ChromePreferenceKeys.INCOGNITO_SHORTCUT_ADDED,
ChromePreferenceKeys.INVALIDATIONS_UUID_PREF_KEY,
ChromePreferenceKeys.LATEST_UNSUPPORTED_VERSION, ChromePreferenceKeys.LATEST_UNSUPPORTED_VERSION,
ChromePreferenceKeys.LOCALE_MANAGER_AUTO_SWITCH, ChromePreferenceKeys.LOCALE_MANAGER_AUTO_SWITCH,
ChromePreferenceKeys.LOCALE_MANAGER_PROMO_SHOWN, ChromePreferenceKeys.LOCALE_MANAGER_PROMO_SHOWN,
......
...@@ -25,32 +25,6 @@ android_library("sync_java") { ...@@ -25,32 +25,6 @@ android_library("sync_java") {
"java/src/org/chromium/components/sync/SyncConstants.java", "java/src/org/chromium/components/sync/SyncConstants.java",
"java/src/org/chromium/components/sync/SyncContentResolverDelegate.java", "java/src/org/chromium/components/sync/SyncContentResolverDelegate.java",
"java/src/org/chromium/components/sync/SystemSyncContentResolverDelegate.java", "java/src/org/chromium/components/sync/SystemSyncContentResolverDelegate.java",
"java/src/org/chromium/components/sync/notifier/InvalidationClientNameGenerator.java",
"java/src/org/chromium/components/sync/notifier/InvalidationClientNameProvider.java",
"java/src/org/chromium/components/sync/notifier/InvalidationIntentProtocol.java",
"java/src/org/chromium/components/sync/notifier/InvalidationPreferences.java",
"java/src/org/chromium/components/sync/notifier/RandomizedInvalidationClientNameGenerator.java",
]
}
android_library("sync_javatests") {
testonly = true
deps = [
":sync_java",
"//base:base_java",
"//base:base_java_test_support",
"//components/signin/core/browser/android:java",
"//components/signin/core/browser/android:signin_java_test_support",
"//components/sync:sync_java_test_support",
"//third_party/android_deps:com_google_code_findbugs_jsr305_java",
"//third_party/android_support_test_runner:runner_java",
"//third_party/cacheinvalidation:cacheinvalidation_javalib",
"//third_party/cacheinvalidation:cacheinvalidation_proto_java",
"//third_party/junit",
]
sources = [
"javatests/src/org/chromium/components/sync/notifier/InvalidationClientNameProviderTest.java",
"javatests/src/org/chromium/components/sync/notifier/InvalidationPreferencesTest.java",
] ]
} }
......
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.sync.notifier;
/** Interface for classes that create an Invalidation client's name. */
public interface InvalidationClientNameGenerator { public byte[] generateInvalidatorClientName(); }
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.sync.notifier;
/**
* An injectable singleton that provides an invalidation client with an appropriate unique name.
*
* This singleton will always provide a somewhat reasonable name. With proper support from outside
* components, it will be able to provide a name that is consistent across restarts.
*/
public class InvalidationClientNameProvider {
private static final Object LOCK = new Object();
private static InvalidationClientNameProvider sInstance;
private final Object mLock;
private InvalidationClientNameGenerator mGenerator;
private byte[] mUniqueId;
public static InvalidationClientNameProvider get() {
synchronized (LOCK) {
if (sInstance == null) {
sInstance = new InvalidationClientNameProvider();
}
return sInstance;
}
}
InvalidationClientNameProvider() {
mLock = new Object();
mGenerator = new RandomizedInvalidationClientNameGenerator();
}
/** Returns a consistent unique string of bytes for use as an invalidator client ID. */
public byte[] getInvalidatorClientName() {
synchronized (mLock) {
if (mUniqueId == null) {
mUniqueId = mGenerator.generateInvalidatorClientName();
}
return mUniqueId;
}
}
public void setPreferredClientNameGenerator(InvalidationClientNameGenerator generator) {
mGenerator = generator;
}
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.sync.notifier;
import android.accounts.Account;
import android.content.Intent;
import com.google.ipc.invalidation.external.client.types.ObjectId;
import com.google.protos.ipc.invalidation.Types;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.CollectionUtil;
import org.chromium.components.sync.ModelTypeHelper;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
/**
* Constants and utility methods to create the intents used to communicate between the
* controller and the invalidation client library.
*/
public class InvalidationIntentProtocol {
/**
* Action set on register intents.
*/
public static final String ACTION_REGISTER =
"org.chromium.components.sync.notifier.ACTION_REGISTER_TYPES";
/**
* Parcelable-valued intent extra containing the account of the user.
*/
public static final String EXTRA_ACCOUNT = "account";
/**
* String-list-valued intent extra of the syncable types to sync.
*/
public static final String EXTRA_REGISTERED_TYPES = "registered_types";
/**
* Int-array-valued intent extra containing sources of objects to register for.
* The array is parallel to EXTRA_REGISTERED_OBJECT_NAMES.
*/
public static final String EXTRA_REGISTERED_OBJECT_SOURCES = "registered_object_sources";
/**
* String-array-valued intent extra containing names of objects to register for.
* The array is parallel to EXTRA_REGISTERED_OBJECT_SOURCES.
*/
public static final String EXTRA_REGISTERED_OBJECT_NAMES = "registered_object_names";
/**
* Boolean-valued intent extra indicating that the service should be stopped.
*/
public static final String EXTRA_STOP = "stop";
/**
* Create an Intent that will start the invalidation listener service and
* register for the specified types.
*/
public static Intent createRegisterIntent(Account account, Set<Integer> types) {
Intent registerIntent = new Intent(ACTION_REGISTER);
String[] selectedTypesArray = new String[types.size()];
int pos = 0;
for (Integer type : types) {
selectedTypesArray[pos++] = ModelTypeHelper.toNotificationType(type);
}
registerIntent.putStringArrayListExtra(
EXTRA_REGISTERED_TYPES, CollectionUtil.newArrayList(selectedTypesArray));
registerIntent.putExtra(EXTRA_ACCOUNT, account);
return registerIntent;
}
/**
* Create an Intent that will start the invalidation listener service and
* register for the object ids with the specified sources and names.
* Sync-specific objects are filtered out of the request since Sync types
* are registered using the other version of createRegisterIntent.
*/
public static Intent createRegisterIntent(
Account account, int[] objectSources, String[] objectNames) {
if (objectSources.length != objectNames.length) {
throw new IllegalArgumentException(
"objectSources and objectNames must have the same length");
}
// Add all non-Sync objects to new lists.
ArrayList<Integer> sources = new ArrayList<Integer>();
ArrayList<String> names = new ArrayList<String>();
for (int i = 0; i < objectSources.length; i++) {
if (objectSources[i] != Types.ObjectSource.CHROME_SYNC) {
sources.add(objectSources[i]);
names.add(objectNames[i]);
}
}
Intent registerIntent = new Intent(ACTION_REGISTER);
registerIntent.putIntegerArrayListExtra(EXTRA_REGISTERED_OBJECT_SOURCES, sources);
registerIntent.putStringArrayListExtra(EXTRA_REGISTERED_OBJECT_NAMES, names);
registerIntent.putExtra(EXTRA_ACCOUNT, account);
return registerIntent;
}
/** Returns whether {@code intent} is a stop intent. */
public static boolean isStop(Intent intent) {
return intent.getBooleanExtra(EXTRA_STOP, false);
}
/** Returns whether {@code intent} is a registered types change intent. */
public static boolean isRegisteredTypesChange(Intent intent) {
return intent.hasExtra(EXTRA_REGISTERED_TYPES)
|| intent.hasExtra(EXTRA_REGISTERED_OBJECT_SOURCES);
}
/** Returns the object ids for which to register contained in the intent. */
public static Set<ObjectId> getRegisteredObjectIds(Intent intent) {
ArrayList<Integer> objectSources =
intent.getIntegerArrayListExtra(EXTRA_REGISTERED_OBJECT_SOURCES);
ArrayList<String> objectNames =
intent.getStringArrayListExtra(EXTRA_REGISTERED_OBJECT_NAMES);
if (objectSources == null || objectNames == null
|| objectSources.size() != objectNames.size()) {
return null;
}
Set<ObjectId> objectIds = new HashSet<ObjectId>(objectSources.size());
for (int i = 0; i < objectSources.size(); i++) {
objectIds.add(ObjectId.newInstance(
objectSources.get(i), ApiCompatibilityUtils.getBytesUtf8(objectNames.get(i))));
}
return objectIds;
}
private InvalidationIntentProtocol() {
// Disallow instantiation.
}
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.sync.notifier;
import android.accounts.Account;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.util.Base64;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.ipc.invalidation.external.client.types.ObjectId;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* Class to manage the preferences used by the invalidation client.
* <p>
* This class provides methods to read and write the preferences used by the invalidation client.
* <p>
* To read a preference, call the appropriate {@code get...} method.
* <p>
* To write a preference, first call {@link #edit} to obtain a {@link EditContext}. Then, make
* one or more calls to a {@code set...} method, providing the same edit context to each call.
* Finally, call {@link #commit(EditContext)} to save the changes to stable storage.
*
* @author dsmyers@google.com (Daniel Myers)
*/
public class InvalidationPreferences {
/**
* Wrapper around a {@link android.content.SharedPreferences.Editor} for the preferences.
* Used to avoid exposing raw preference objects to users of this class.
*/
@SuppressLint("CommitPrefEdits")
public static class EditContext {
private final SharedPreferences.Editor mEditor;
EditContext() {
mEditor = ContextUtils.getAppSharedPreferences().edit();
}
}
/**
* Internal class to wrap constants for preference keys.
*/
@VisibleForTesting
public static class PrefKeys {
/**
* Shared preference key to store the invalidation types that we want to register
* for.
*/
@VisibleForTesting
public static final String SYNC_TANGO_TYPES = "sync_tango_types";
/**
* Shared preference key to store tango object ids for additional objects that we want to
* register for.
*/
@VisibleForTesting
public static final String TANGO_OBJECT_IDS = "tango_object_ids";
/** Shared preference key to store the name of the account in use. */
@VisibleForTesting
public static final String SYNC_ACCT_NAME = "sync_acct_name";
/** Shared preference key to store the type of account in use. */
static final String SYNC_ACCT_TYPE = "sync_acct_type";
/** Shared preference key to store internal notification client library state. */
static final String SYNC_TANGO_INTERNAL_STATE = "sync_tango_internal_state";
}
private static final String TAG = "InvalidationPrefs";
// Only one commit call can be in progress at a time.
private static final Object sCommitLock = new Object();
/** Returns a new {@link EditContext} to modify the preferences managed by this class. */
public EditContext edit() {
return new EditContext();
}
/**
* Applies the changes accumulated in {@code editContext}. Returns whether they were
* successfully written.
* <p>
* NOTE: this method performs blocking I/O and must not be called from the UI thread.
*/
public boolean commit(EditContext editContext) {
synchronized (sCommitLock) {
if (!editContext.mEditor.commit()) {
Log.w(TAG, "Failed to commit invalidation preferences");
return false;
}
return true;
}
}
/** Returns the saved sync types, or {@code null} if none exist. */
@Nullable
public Set<String> getSavedSyncedTypes() {
SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
Set<String> syncedTypes = preferences.getStringSet(PrefKeys.SYNC_TANGO_TYPES, null);
// Wrap with unmodifiableSet to ensure it's never modified. See crbug.com/568369.
return syncedTypes == null ? null : Collections.unmodifiableSet(syncedTypes);
}
/** Sets the saved sync types to {@code syncTypes} in {@code editContext}. */
public void setSyncTypes(EditContext editContext, Collection<String> syncTypes) {
if (syncTypes == null) throw new NullPointerException("syncTypes is null.");
Set<String> selectedTypesSet = new HashSet<String>(syncTypes);
editContext.mEditor.putStringSet(PrefKeys.SYNC_TANGO_TYPES, selectedTypesSet);
}
/** Returns the saved non-sync object ids, or {@code null} if none exist. */
@Nullable
public Set<ObjectId> getSavedObjectIds() {
SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
Set<String> objectIdStrings = preferences.getStringSet(PrefKeys.TANGO_OBJECT_IDS, null);
if (objectIdStrings == null) {
return null;
}
Set<ObjectId> objectIds = new HashSet<ObjectId>(objectIdStrings.size());
for (String objectIdString : objectIdStrings) {
ObjectId objectId = getObjectId(objectIdString);
if (objectId != null) {
objectIds.add(objectId);
}
}
return objectIds;
}
/** Sets the saved non-sync object ids */
public void setObjectIds(EditContext editContext, Collection<ObjectId> objectIds) {
if (objectIds == null) throw new NullPointerException("objectIds is null.");
Set<String> objectIdStrings = new HashSet<String>(objectIds.size());
for (ObjectId objectId : objectIds) {
objectIdStrings.add(getObjectIdString(objectId));
}
editContext.mEditor.putStringSet(PrefKeys.TANGO_OBJECT_IDS, objectIdStrings);
}
/** Returns the saved account, or {@code null} if none exists. */
@Nullable
public Account getSavedSyncedAccount() {
SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
String accountName = preferences.getString(PrefKeys.SYNC_ACCT_NAME, null);
String accountType = preferences.getString(PrefKeys.SYNC_ACCT_TYPE, null);
if (accountName == null || accountType == null) {
return null;
}
return new Account(accountName, accountType);
}
/** Sets the saved account to {@code account} in {@code editContext}. */
public void setAccount(EditContext editContext, Account account) {
editContext.mEditor.putString(PrefKeys.SYNC_ACCT_NAME, account.name);
editContext.mEditor.putString(PrefKeys.SYNC_ACCT_TYPE, account.type);
}
/** Returns the notification client internal state. */
@Nullable
public byte[] getInternalNotificationClientState() {
SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
String base64State = preferences.getString(PrefKeys.SYNC_TANGO_INTERNAL_STATE, null);
if (base64State == null) {
return null;
}
try {
return Base64.decode(base64State, Base64.DEFAULT);
} catch (java.lang.IllegalArgumentException e) {
return null;
}
}
/** Sets the notification client internal state to {@code state}. */
public void setInternalNotificationClientState(EditContext editContext, byte[] state) {
editContext.mEditor.putString(
PrefKeys.SYNC_TANGO_INTERNAL_STATE, Base64.encodeToString(state, Base64.DEFAULT));
}
/** Converts the given object id to a string for storage in preferences. */
private String getObjectIdString(ObjectId objectId) {
return objectId.getSource() + ":" + new String(objectId.getName());
}
/**
* Converts the given object id string stored in preferences to an object id.
* Returns null if the string does not represent a valid object id.
*/
private ObjectId getObjectId(String objectIdString) {
int separatorPos = objectIdString.indexOf(':');
// Ensure that the separator is surrounded by at least one character on each side.
if (separatorPos < 1 || separatorPos == objectIdString.length() - 1) {
return null;
}
int objectSource;
try {
objectSource = Integer.parseInt(objectIdString.substring(0, separatorPos));
} catch (NumberFormatException e) {
return null;
}
byte[] objectName =
ApiCompatibilityUtils.getBytesUtf8(objectIdString.substring(separatorPos + 1));
return ObjectId.newInstance(objectSource, objectName);
}
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.sync.notifier;
import android.util.Base64;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.annotations.MainDex;
import java.util.Random;
/**
* Generates a fully random client ID.
*
* This ID will not persist across restarts. Using this ID will break the invalidator's "reflection
* blocking" feature. That's unfortunate, but better than using a hard-coded ID. A hard-coded ID
* could prevent invalidations from being delivered.
*/
@MainDex
class RandomizedInvalidationClientNameGenerator implements InvalidationClientNameGenerator {
private static final Random RANDOM = new Random();
RandomizedInvalidationClientNameGenerator() {}
/**
* Generates a random ID prefixed with the string "BadID".
*
* The prefix is intended to grab attention. We should never use it in real builds. Hopefully,
* it will induce someone to file a bug if they see it.
*
* However, as bad as it is, this ID is better than a hard-coded default or none at all. See
* the class description for more details.
*/
@Override
public byte[] generateInvalidatorClientName() {
byte[] randomBytes = new byte[8];
RANDOM.nextBytes(randomBytes);
String encoded = Base64.encodeToString(randomBytes, 0, randomBytes.length, Base64.NO_WRAP);
String idString = "BadID" + encoded;
return ApiCompatibilityUtils.getBytesUtf8(idString);
}
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.sync.notifier;
import androidx.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Feature;
import java.util.Arrays;
/** Tests for the {@link InvalidationClientNameProvider} */
@RunWith(BaseJUnit4ClassRunner.class)
public class InvalidationClientNameProviderTest {
private InvalidationClientNameProvider mProvider;
@Before
public void setUp() {
mProvider = new InvalidationClientNameProvider();
}
@Test
@SmallTest
@Feature({"Sync"})
public void testFallbackClientId() {
// Test that the InvalidationController consistently returns the same ID even when it has to
// resort to its "fallback" ID generation code.
byte[] id1 = mProvider.getInvalidatorClientName();
byte[] id2 = mProvider.getInvalidatorClientName();
// We expect the returned IDs to be consistent in every call.
Assert.assertTrue("Expected returned IDs to be consistent", Arrays.equals(id1, id2));
// Even if initialize the generator late, the ID will remain consistent.
registerHardCodedGenerator(mProvider);
// IDs should still be consistent, even if we change the generator.
// (In the real program, the generator should be set before anyone invokes the
// getInvalidatorClientName() and never change afterwards. We test this anyway to make sure
// nothing will blow up if someone accidentally violates that constraint.)
byte[] id3 = mProvider.getInvalidatorClientName();
Assert.assertTrue("Changing generators should not affect returned ID consistency",
Arrays.equals(id2, id3));
}
@Test
@SmallTest
@Feature({"Sync"})
public void testPreRegisteredGenerator() {
registerHardCodedGenerator(mProvider);
byte[] id = mProvider.getInvalidatorClientName();
byte[] id2 = mProvider.getInvalidatorClientName();
// Expect that consistent IDs are maintained when using a custom generator, too.
Assert.assertTrue("Custom generators should return consistent IDs", Arrays.equals(id, id2));
}
private static void registerHardCodedGenerator(InvalidationClientNameProvider provider) {
provider.setPreferredClientNameGenerator(new InvalidationClientNameGenerator() {
@Override
public byte[] generateInvalidatorClientName() {
return ApiCompatibilityUtils.getBytesUtf8("Testable ID");
}
});
}
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.sync.notifier;
import android.accounts.Account;
import androidx.test.filters.SmallTest;
import com.google.ipc.invalidation.external.client.types.ObjectId;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.CollectionUtil;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Feature;
import java.util.Arrays;
import java.util.Set;
/**
* Tests for the {@link InvalidationPreferences}.
*
* @author dsmyers@google.com (Daniel Myers)
*/
@RunWith(BaseJUnit4ClassRunner.class)
public class InvalidationPreferencesTest {
@Test
@SmallTest
@Feature({"Sync"})
public void testReadMissingData() {
/*
* Test plan: read saved state from empty preferences. Verify that null is returned.
*/
InvalidationPreferences invPreferences = new InvalidationPreferences();
Assert.assertNull(invPreferences.getSavedSyncedAccount());
Assert.assertNull(invPreferences.getSavedSyncedTypes());
Assert.assertNull(invPreferences.getSavedObjectIds());
Assert.assertNull(invPreferences.getInternalNotificationClientState());
}
@Test
@SmallTest
@Feature({"Sync"})
public void testReadWriteAndReadData() {
/*
* Test plan: write and read back saved state. Verify that the returned state is what
* was written.
*/
InvalidationPreferences invPreferences = new InvalidationPreferences();
InvalidationPreferences.EditContext editContext = invPreferences.edit();
// Write mix of valid and invalid types to disk to test that preferences are not
// interpreting the data. Invalid types should never be written to disk in practice.
Set<String> syncTypes = CollectionUtil.newHashSet("BOOKMARK", "INVALID");
Set<ObjectId> objectIds = CollectionUtil.newHashSet(
ObjectId.newInstance(1, ApiCompatibilityUtils.getBytesUtf8("obj1")),
ObjectId.newInstance(2, ApiCompatibilityUtils.getBytesUtf8("obj2")));
Account account = new Account("test@example.com", "bogus");
byte[] internalClientState = new byte[] {100, 101, 102};
invPreferences.setSyncTypes(editContext, syncTypes);
invPreferences.setObjectIds(editContext, objectIds);
invPreferences.setAccount(editContext, account);
invPreferences.setInternalNotificationClientState(editContext, internalClientState);
// Nothing should yet have been written.
Assert.assertNull(invPreferences.getSavedSyncedAccount());
Assert.assertNull(invPreferences.getSavedSyncedTypes());
Assert.assertNull(invPreferences.getSavedObjectIds());
// Write the new data and verify that they are correctly read back.
invPreferences.commit(editContext);
Assert.assertEquals(account, invPreferences.getSavedSyncedAccount());
Assert.assertEquals(syncTypes, invPreferences.getSavedSyncedTypes());
Assert.assertEquals(objectIds, invPreferences.getSavedObjectIds());
Assert.assertTrue(Arrays.equals(
internalClientState, invPreferences.getInternalNotificationClientState()));
}
}
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