summaryrefslogtreecommitdiffstats
path: root/sync/android
diff options
context:
space:
mode:
authornyquist@chromium.org <nyquist@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-11 19:01:36 +0000
committernyquist@chromium.org <nyquist@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-11 19:01:36 +0000
commit970670d613287319d6c4e9018bd412eb6662f192 (patch)
tree8643e69723283223bc07f0bda8bb39969ff7f148 /sync/android
parent6d6fe4afae5ad084c9bd3447e6853a739cbccaa6 (diff)
downloadchromium_src-970670d613287319d6c4e9018bd412eb6662f192.zip
chromium_src-970670d613287319d6c4e9018bd412eb6662f192.tar.gz
chromium_src-970670d613287319d6c4e9018bd412eb6662f192.tar.bz2
[sync] Add ModelTypeResolver and control types
Adds a few new things: * Some control ModelTypes (NIGORI, EXPERIMENTS). * Now we always register control types through setRegisteredTypes() * Add support for ModelType groups (for AUTOFILL / AUTOFILL_PROFILES) * Support for refreshing the cacheinvalidation registration. BUG=113164 Review URL: https://codereview.chromium.org/12217027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@181730 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync/android')
-rw-r--r--sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java54
-rw-r--r--sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java30
-rw-r--r--sync/android/java/src/org/chromium/sync/notifier/ModelTypeResolver.java17
-rw-r--r--sync/android/java/src/org/chromium/sync/notifier/ModelTypeResolverImpl.java37
-rw-r--r--sync/android/javatests/src/org/chromium/sync/notifier/InvalidationControllerTest.java99
-rw-r--r--sync/android/javatests/src/org/chromium/sync/notifier/ModelTypeResolverTest.java72
6 files changed, 301 insertions, 8 deletions
diff --git a/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java b/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java
index afe6201..4ada2fe 100644
--- a/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java
+++ b/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java
@@ -6,11 +6,14 @@ package org.chromium.sync.internal_api.pub.base;
import android.util.Log;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.ipc.invalidation.external.client.types.ObjectId;
import com.google.protos.ipc.invalidation.Types;
import java.util.Collection;
+import java.util.HashSet;
import java.util.Set;
/**
@@ -30,17 +33,25 @@ public enum ModelType {
*/
BOOKMARK("BOOKMARK"),
/**
+ * Flags to enable experimental features.
+ */
+ EXPERIMENTS("EXPERIMENTS", true),
+ /**
+ * An object representing a set of Nigori keys.
+ */
+ NIGORI("NIGORI", true),
+ /**
* A password entry.
*/
PASSWORD("PASSWORD"),
/**
- * A typed_url folder or a typed_url object.
+ * An object representing a browser session or tab.
*/
- TYPED_URL("TYPED_URL"),
+ SESSION("SESSION"),
/**
- * An object representing a browser session or tab.
+ * A typed_url folder or a typed_url object.
*/
- SESSION("SESSION");
+ TYPED_URL("TYPED_URL");
/** Special type representing all possible types. */
public static final String ALL_TYPES_TYPE = "ALL_TYPES";
@@ -49,8 +60,18 @@ public enum ModelType {
private final String mModelType;
+ /**
+ * True if this is a control type.
+ */
+ private final boolean mControl;
+
ModelType(String modelType) {
+ this(modelType, false);
+ }
+
+ ModelType(String modelType, boolean control) {
mModelType = modelType;
+ mControl = control;
}
public ObjectId toObjectId() {
@@ -83,7 +104,7 @@ public enum ModelType {
Set<ModelType> modelTypes = Sets.newHashSetWithExpectedSize(syncTypes.size());
for (String syncType : syncTypes) {
try {
- modelTypes.add(ModelType.valueOf(syncType));
+ modelTypes.add(valueOf(syncType));
} catch (IllegalArgumentException exception) {
// Drop invalid sync types.
Log.w(TAG, "Could not translate sync type to model type: " + syncType);
@@ -110,4 +131,27 @@ public enum ModelType {
}
return objectIds;
}
+
+ /**
+ * Returns a set of all the control {@link ModelType}s.
+ */
+ public static Set<ModelType> controlTypes() {
+ Set<ModelType> controlTypes = new HashSet<ModelType>();
+ for (ModelType modelType : values()) {
+ if (modelType.mControl) {
+ controlTypes.add(modelType);
+ }
+ }
+ return controlTypes;
+ }
+
+ /**
+ * Returns a Multimap of all the {@link ModelType} groups. The key is the main
+ * {@link ModelType}, and the value is a collection of {@link ModelType}s in the same group.
+ */
+ public static Multimap<ModelType, ModelType> modelTypeGroups() {
+ Multimap<ModelType, ModelType> modelTypeGroups = HashMultimap.create();
+ modelTypeGroups.put(AUTOFILL, AUTOFILL_PROFILE);
+ return modelTypeGroups;
+ }
}
diff --git a/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java b/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java
index 0f4b7d4..9b91c98 100644
--- a/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java
+++ b/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java
@@ -18,6 +18,7 @@ import com.google.common.collect.Lists;
import org.chromium.sync.internal_api.pub.base.ModelType;
+import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nullable;
@@ -113,12 +114,31 @@ public class InvalidationController {
* @param types Set of types for which to register. Ignored if {@code allTypes == true}.
*/
public void setRegisteredTypes(Account account, boolean allTypes, Set<ModelType> types) {
- Intent registerIntent = IntentProtocol.createRegisterIntent(account, allTypes, types);
+ Set<ModelType> typesToRegister = getModelTypeResolver().resolveModelTypes(types);
+ Intent registerIntent = IntentProtocol.createRegisterIntent(account, allTypes,
+ typesToRegister);
setDestinationClassName(registerIntent);
mContext.startService(registerIntent);
}
/**
+ * Reads all stored preferences and calls
+ * {@link #setRegisteredTypes(android.accounts.Account, boolean, java.util.Set)} with the stored
+ * values. It can be used on startup of Chrome to ensure we always have a consistent set of
+ * registrations.
+ */
+ public void refreshRegisteredTypes() {
+ InvalidationPreferences invalidationPreferences = new InvalidationPreferences(mContext);
+ Set<String> savedSyncedTypes = invalidationPreferences.getSavedSyncedTypes();
+ Account account = invalidationPreferences.getSavedSyncedAccount();
+ boolean allTypes = savedSyncedTypes != null &&
+ savedSyncedTypes.contains(ModelType.ALL_TYPES_TYPE);
+ Set<ModelType> modelTypes = savedSyncedTypes == null ?
+ new HashSet<ModelType>() : ModelType.syncTypesToModelTypes(savedSyncedTypes);
+ setRegisteredTypes(account, allTypes, modelTypes);
+ }
+
+ /**
* Starts the invalidation client.
*/
public void start() {
@@ -152,7 +172,8 @@ public class InvalidationController {
/**
* Creates an instance using {@code context} to send intents.
*/
- private InvalidationController(Context context) {
+ @VisibleForTesting
+ InvalidationController(Context context) {
this.mContext = Preconditions.checkNotNull(context.getApplicationContext());
}
@@ -192,4 +213,9 @@ public class InvalidationController {
}
return null;
}
+
+ @VisibleForTesting
+ ModelTypeResolver getModelTypeResolver() {
+ return new ModelTypeResolverImpl();
+ }
}
diff --git a/sync/android/java/src/org/chromium/sync/notifier/ModelTypeResolver.java b/sync/android/java/src/org/chromium/sync/notifier/ModelTypeResolver.java
new file mode 100644
index 0000000..7a30e2f
--- /dev/null
+++ b/sync/android/java/src/org/chromium/sync/notifier/ModelTypeResolver.java
@@ -0,0 +1,17 @@
+// Copyright (c) 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.sync.notifier;
+
+import org.chromium.sync.internal_api.pub.base.ModelType;
+
+import java.util.Set;
+
+/**
+ * A utility class that supports groups of {@link ModelType}s and also supports adding the default
+ * set of {@link ModelType}s.
+ */
+interface ModelTypeResolver {
+ Set<ModelType> resolveModelTypes(Set<ModelType> modelTypes);
+}
diff --git a/sync/android/java/src/org/chromium/sync/notifier/ModelTypeResolverImpl.java b/sync/android/java/src/org/chromium/sync/notifier/ModelTypeResolverImpl.java
new file mode 100644
index 0000000..27a8e6d
--- /dev/null
+++ b/sync/android/java/src/org/chromium/sync/notifier/ModelTypeResolverImpl.java
@@ -0,0 +1,37 @@
+// Copyright (c) 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.sync.notifier;
+
+import com.google.common.collect.Multimap;
+
+import org.chromium.sync.internal_api.pub.base.ModelType;
+
+import java.util.HashSet;
+import java.util.Set;
+
+class ModelTypeResolverImpl implements ModelTypeResolver {
+ @Override
+ public Set<ModelType> resolveModelTypes(Set<ModelType> modelTypes) {
+ // Create a new set that we will return as a result, and add all original ModelTypes.
+ Set<ModelType> typesWithGroups = new HashSet<ModelType>();
+ Set<ModelType> modelTypesNonNull =
+ modelTypes == null ? new HashSet<ModelType>() : modelTypes;
+ typesWithGroups.addAll(modelTypesNonNull);
+
+ Multimap<ModelType, ModelType> modelTypeGroups = ModelType.modelTypeGroups();
+ // Remove ModelTypes that are specified, that does not have their group ModelType specified.
+ for (ModelType modelType : modelTypeGroups.keySet()) {
+ if (modelTypesNonNull.contains(modelType)) {
+ typesWithGroups.addAll(modelTypeGroups.get(modelType));
+ } else {
+ typesWithGroups.removeAll(modelTypeGroups.get(modelType));
+ }
+ }
+
+ // Add all control types.
+ typesWithGroups.addAll(ModelType.controlTypes());
+ return typesWithGroups;
+ }
+}
diff --git a/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationControllerTest.java b/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationControllerTest.java
index 0a84273..b7f96e3 100644
--- a/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationControllerTest.java
+++ b/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationControllerTest.java
@@ -19,9 +19,14 @@ import org.chromium.base.test.util.AdvancedMockContext;
import org.chromium.base.test.util.Feature;
import org.chromium.sync.internal_api.pub.base.ModelType;
import org.chromium.sync.notifier.InvalidationController.IntentProtocol;
+import org.chromium.sync.signin.AccountManagerHelper;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Tests for the {@link InvalidationController}.
@@ -61,8 +66,22 @@ public class InvalidationControllerTest extends InstrumentationTestCase {
@SmallTest
@Feature({"Sync"})
public void testRegisterForSpecificTypes() {
+ final String controllerFlag = "resolveModelTypes";
+ final ModelTypeResolver resolver = new ModelTypeResolver() {
+ @Override
+ public Set<ModelType> resolveModelTypes(Set<ModelType> modelTypes) {
+ mContext.setFlag(controllerFlag);
+ return modelTypes;
+ }
+ };
+ InvalidationController controller = new InvalidationController(mContext) {
+ @Override
+ ModelTypeResolver getModelTypeResolver() {
+ return resolver;
+ }
+ };
Account account = new Account("test@example.com", "bogus");
- mController.setRegisteredTypes(account, false,
+ controller.setRegisteredTypes(account, false,
Sets.newHashSet(ModelType.BOOKMARK, ModelType.SESSION));
assertEquals(1, mContext.getNumStartedIntents());
@@ -81,6 +100,7 @@ public class InvalidationControllerTest extends InstrumentationTestCase {
Set<String> actualTypes = Sets.newHashSet();
actualTypes.addAll(intent.getStringArrayListExtra(IntentProtocol.EXTRA_REGISTERED_TYPES));
assertEquals(expectedTypes, actualTypes);
+ assertTrue(mContext.isFlagSet(controllerFlag));
}
@SmallTest
@@ -109,6 +129,83 @@ public class InvalidationControllerTest extends InstrumentationTestCase {
@SmallTest
@Feature({"Sync"})
+ public void testRefreshShouldReadValuesFromDiskWithSpecificTypes() {
+ // Store some preferences for ModelTypes and account. We are using the helper class
+ // for this, so we don't have to deal with low-level details such as preference keys.
+ InvalidationPreferences invalidationPreferences = new InvalidationPreferences(mContext);
+ InvalidationPreferences.EditContext edit = invalidationPreferences.edit();
+ Set<String> storedModelTypes = new HashSet<String>();
+ storedModelTypes.add(ModelType.BOOKMARK.name());
+ storedModelTypes.add(ModelType.TYPED_URL.name());
+ invalidationPreferences.setSyncTypes(edit, storedModelTypes);
+ Account storedAccount = AccountManagerHelper.createAccountFromName("test@gmail.com");
+ invalidationPreferences.setAccount(edit, storedAccount);
+ invalidationPreferences.commit(edit);
+
+ // Ensure all calls to {@link InvalidationController#setRegisteredTypes} store values
+ // we can inspect in the test.
+ final AtomicReference<Account> resultAccount = new AtomicReference<Account>();
+ final AtomicBoolean resultAllTypes = new AtomicBoolean();
+ final AtomicReference<Set<ModelType>> resultTypes = new AtomicReference<Set<ModelType>>();
+ InvalidationController controller = new InvalidationController(mContext) {
+ @Override
+ public void setRegisteredTypes(
+ Account account, boolean allTypes, Set<ModelType> types) {
+ resultAccount.set(account);
+ resultAllTypes.set(allTypes);
+ resultTypes.set(types);
+ }
+ };
+
+ // Execute the test.
+ controller.refreshRegisteredTypes();
+
+ // Validate the values.
+ assertEquals(storedAccount, resultAccount.get());
+ assertEquals(false, resultAllTypes.get());
+ assertEquals(ModelType.syncTypesToModelTypes(storedModelTypes), resultTypes.get());
+ }
+
+ @SmallTest
+ @Feature({"Sync"})
+ public void testRefreshShouldReadValuesFromDiskWithAllTypes() {
+ // Store preferences for the ModelType.ALL_TYPES_TYPE and account. We are using the
+ // helper class for this, so we don't have to deal with low-level details such as preference
+ // keys.
+ InvalidationPreferences invalidationPreferences = new InvalidationPreferences(mContext);
+ InvalidationPreferences.EditContext edit = invalidationPreferences.edit();
+ List<String> storedModelTypes = new ArrayList<String>();
+ storedModelTypes.add(ModelType.ALL_TYPES_TYPE);
+ invalidationPreferences.setSyncTypes(edit, storedModelTypes);
+ Account storedAccount = AccountManagerHelper.createAccountFromName("test@gmail.com");
+ invalidationPreferences.setAccount(edit, storedAccount);
+ invalidationPreferences.commit(edit);
+
+ // Ensure all calls to {@link InvalidationController#setRegisteredTypes} store values
+ // we can inspect in the test.
+ final AtomicReference<Account> resultAccount = new AtomicReference<Account>();
+ final AtomicBoolean resultAllTypes = new AtomicBoolean();
+ final AtomicReference<Set<ModelType>> resultTypes = new AtomicReference<Set<ModelType>>();
+ InvalidationController controller = new InvalidationController(mContext) {
+ @Override
+ public void setRegisteredTypes(
+ Account account, boolean allTypes, Set<ModelType> types) {
+ resultAccount.set(account);
+ resultAllTypes.set(allTypes);
+ resultTypes.set(types);
+ }
+ };
+
+ // Execute the test.
+ controller.refreshRegisteredTypes();
+
+ // Validate the values.
+ assertEquals(storedAccount, resultAccount.get());
+ assertEquals(true, resultAllTypes.get());
+ }
+
+ @SmallTest
+ @Feature({"Sync"})
public void testGetContractAuthority() throws Exception {
assertEquals(mContext.getPackageName(), mController.getContractAuthority());
}
diff --git a/sync/android/javatests/src/org/chromium/sync/notifier/ModelTypeResolverTest.java b/sync/android/javatests/src/org/chromium/sync/notifier/ModelTypeResolverTest.java
new file mode 100644
index 0000000..aa53eb8
--- /dev/null
+++ b/sync/android/javatests/src/org/chromium/sync/notifier/ModelTypeResolverTest.java
@@ -0,0 +1,72 @@
+// Copyright (c) 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.sync.notifier;
+
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.sync.internal_api.pub.base.ModelType;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class ModelTypeResolverTest extends InstrumentationTestCase {
+ @SmallTest
+ @Feature({"Sync"})
+ public void testControlTypesShouldAlwaysBeAddedEvenForNullModelTypes() throws Exception {
+ ModelTypeResolverImpl resolver = new ModelTypeResolverImpl();
+ Set<ModelType> result = resolver.resolveModelTypes(null);
+ assertNotNull(result);
+ assertEquals("Size should be the same as number of control types",
+ ModelType.controlTypes().size(), result.size());
+ assertTrue("Should contain all control ModelTypes",
+ result.containsAll(ModelType.controlTypes()));
+ }
+
+ @SmallTest
+ @Feature({"Sync"})
+ public void testControlTypesShouldAlwaysBeAdded() throws Exception {
+ ModelTypeResolverImpl resolver = new ModelTypeResolverImpl();
+ Set<ModelType> result = resolver.resolveModelTypes(new HashSet<ModelType>());
+ assertNotNull(result);
+ assertEquals("Size should be the same as number of control types",
+ ModelType.controlTypes().size(), result.size());
+ assertTrue("Should contain all control ModelTypes",
+ result.containsAll(ModelType.controlTypes()));
+ }
+
+ @SmallTest
+ @Feature({"Sync"})
+ public void testAddingAutofillShouldAddAutofillProfile() throws Exception {
+ Set<ModelType> modelTypes = new HashSet<ModelType>();
+ modelTypes.add(ModelType.AUTOFILL);
+ ModelTypeResolverImpl resolver = new ModelTypeResolverImpl();
+ Set<ModelType> result = resolver.resolveModelTypes(modelTypes);
+ assertNotNull(result);
+ assertEquals("Size should be 2 plus the number of control types",
+ 2 + ModelType.controlTypes().size(), result.size());
+ assertTrue("Should have AUTOFILL ModelType", result.contains(ModelType.AUTOFILL));
+ assertTrue("Should have AUTOFILL_PROFILE ModelType",
+ result.contains(ModelType.AUTOFILL_PROFILE));
+ }
+
+ @SmallTest
+ @Feature({"Sync"})
+ public void testModelTypesThatArePartOfGroupsShouldStillWork() throws Exception {
+ Set<ModelType> modelTypes = new HashSet<ModelType>();
+ modelTypes.add(ModelType.BOOKMARK);
+ modelTypes.add(ModelType.SESSION);
+ modelTypes.add(ModelType.TYPED_URL);
+ ModelTypeResolverImpl resolver = new ModelTypeResolverImpl();
+ Set<ModelType> result = resolver.resolveModelTypes(modelTypes);
+ assertNotNull(result);
+ assertEquals("Size should be " + modelTypes.size() + " plus the number of control types",
+ modelTypes.size() + ModelType.controlTypes().size(), result.size());
+ assertTrue("Should have BOOKMARK ModelType", result.contains(ModelType.BOOKMARK));
+ assertTrue("Should have SESSION ModelType", result.contains(ModelType.SESSION));
+ assertTrue("Should have TYPED_URL ModelType", result.contains(ModelType.TYPED_URL));
+ }
+}