From b8d6efcb29ede4dd881700526930b75a077f9a4e Mon Sep 17 00:00:00 2001 From: maxbogue Date: Mon, 29 Sep 2014 10:45:19 -0700 Subject: [PATCH] Massive refactor of the Android invalidation code. We want the invalidations code to exist as a component independent of sync (see bug). This CL seeks to move toward that for the Android invalidations codebase. Generally, things moved from //chrome/browser/invalidation to //components/invalidation, even if git didn't mark them as moves. To accomplish this, I had to unify where the JNI occurred. In Java, InvalidationService was renamed to InvalidationClientService as the class that communicates with GCM. A new InvalidationService class was introduced to handle JNI and other Java entry points to the component. Several methods from ProfileSyncService and InvalidationController moved to it. InvalidationController is now the bridge between sync and the invalidation component, and has no JNI nor C++ counterpart. InvalidationServiceFactory was added to assist in the creation and management of InvalidationService objects across the JNI boundary. BUG=259559 Review URL: https://codereview.chromium.org/459513002 Cr-Commit-Position: refs/heads/master@{#297202} --- chrome/android/DEPS | 1 + .../invalidation/InvalidationController.java | 41 +--- .../InvalidationServiceFactory.java | 50 +++++ .../browser/sync/ChromiumSyncAdapter.java | 7 +- .../browser/sync/ProfileSyncService.java | 33 ++-- .../invalidation/IntentSavingContext.java | 45 +++++ .../InvalidationControllerTest.java | 64 +------ .../invalidation/InvalidationServiceTest.java | 76 ++++++++ chrome/android/shell/java/AndroidManifest.xml | 4 +- .../sync_shell/java/AndroidManifest.xml | 4 +- .../browser/android/chrome_jni_registrar.cc | 7 +- .../invalidation_controller_android.cc | 75 -------- .../invalidation_controller_android.h | 41 ---- .../invalidation_service_android.cc | 107 ----------- .../invalidation_service_android_unittest.cc | 171 ----------------- .../invalidation_service_factory_android.cc | 53 ++++++ .../invalidation_service_factory_android.h | 23 +++ .../profile_invalidation_provider_factory.cc | 10 +- .../sync/profile_sync_service_android.cc | 62 ------ .../sync/profile_sync_service_android.h | 26 --- chrome/chrome.gyp | 1 + chrome/chrome_browser.gypi | 8 +- chrome/chrome_tests.gypi | 1 + chrome/chrome_tests_unit.gypi | 1 - .../test/util/browser/sync/SyncTestUtil.java | 5 +- components/components_tests.gyp | 6 +- components/invalidation.gypi | 60 ++++++ components/invalidation/BUILD.gn | 57 +++++- components/invalidation/DEPS | 1 + components/invalidation/android/DEPS | 3 + .../android/component_jni_registrar.cc | 30 +++ .../android/component_jni_registrar.h | 21 +++ .../InvalidationClientService.java | 15 +- .../invalidation/InvalidationService.java | 91 +++++++++ .../InvalidationClientServiceTest.java | 69 +++---- .../TestableInvalidationClientService.java | 9 +- .../invalidation_service_android.cc | 176 ++++++++++++++++++ .../invalidation_service_android.h | 62 +++--- .../invalidation_service_android_unittest.cc | 41 ++++ components/signin.gypi | 2 + components/test/DEPS | 1 + components/test/run_all_unittests.cc | 2 + 42 files changed, 868 insertions(+), 694 deletions(-) create mode 100644 chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java create mode 100644 chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/IntentSavingContext.java create mode 100644 chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java delete mode 100644 chrome/browser/invalidation/invalidation_controller_android.cc delete mode 100644 chrome/browser/invalidation/invalidation_controller_android.h delete mode 100644 chrome/browser/invalidation/invalidation_service_android.cc delete mode 100644 chrome/browser/invalidation/invalidation_service_android_unittest.cc create mode 100644 chrome/browser/invalidation/invalidation_service_factory_android.cc create mode 100644 chrome/browser/invalidation/invalidation_service_factory_android.h create mode 100644 components/invalidation/android/DEPS create mode 100644 components/invalidation/android/component_jni_registrar.cc create mode 100644 components/invalidation/android/component_jni_registrar.h rename sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java => components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java (97%) create mode 100644 components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationService.java rename sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java => components/invalidation/android/javatests/src/org/chromium/components/invalidation/InvalidationClientServiceTest.java (93%) rename sync/android/javatests/src/org/chromium/sync/notifier/TestableInvalidationService.java => components/invalidation/android/javatests/src/org/chromium/components/invalidation/TestableInvalidationClientService.java (93%) create mode 100644 components/invalidation/invalidation_service_android.cc rename {chrome/browser => components}/invalidation/invalidation_service_android.h (62%) create mode 100644 components/invalidation/invalidation_service_android_unittest.cc diff --git a/chrome/android/DEPS b/chrome/android/DEPS index c80012b5621e..32b2fa6695ea 100644 --- a/chrome/android/DEPS +++ b/chrome/android/DEPS @@ -1,3 +1,4 @@ include_rules = [ + "+components/invalidation", "+jni", ] diff --git a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java index 19bcdab4725b..3f953b768a22 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java @@ -10,13 +10,11 @@ import org.chromium.base.ApplicationState; import org.chromium.base.ApplicationStatus; -import org.chromium.base.CalledByNative; import org.chromium.base.VisibleForTesting; +import org.chromium.components.invalidation.InvalidationClientService; import org.chromium.sync.internal_api.pub.base.ModelType; -import org.chromium.sync.notifier.InvalidationClientNameProvider; import org.chromium.sync.notifier.InvalidationIntentProtocol; import org.chromium.sync.notifier.InvalidationPreferences; -import org.chromium.sync.notifier.InvalidationService; import org.chromium.sync.notifier.SyncStatusHelper; import java.util.Set; @@ -42,7 +40,7 @@ public class InvalidationController implements ApplicationStatus.ApplicationStat public void setRegisteredTypes(Account account, boolean allTypes, Set types) { Intent registerIntent = InvalidationIntentProtocol.createRegisterIntent(account, allTypes, types); - registerIntent.setClass(mContext, InvalidationService.class); + registerIntent.setClass(mContext, InvalidationClientService.class); mContext.startService(registerIntent); } @@ -62,29 +60,11 @@ public void refreshRegisteredTypes(Set types) { setRegisteredTypes(account, allTypes, types); } - /** - * Sets object ids for which the client should register for notification. This is intended for - * registering non-Sync types; Sync types are registered with {@code setRegisteredTypes}. - * - * @param objectSources The sources of the objects. - * @param objectNames The names of the objects. - */ - @CalledByNative - public void setRegisteredObjectIds(int[] objectSources, String[] objectNames) { - InvalidationPreferences invalidationPreferences = new InvalidationPreferences(mContext); - Account account = invalidationPreferences.getSavedSyncedAccount(); - Intent registerIntent = - InvalidationIntentProtocol.createRegisterIntent( - account, objectSources, objectNames); - registerIntent.setClass(mContext, InvalidationService.class); - mContext.startService(registerIntent); - } - /** * Starts the invalidation client. */ public void start() { - Intent intent = new Intent(mContext, InvalidationService.class); + Intent intent = new Intent(mContext, InvalidationClientService.class); mContext.startService(intent); } @@ -92,7 +72,7 @@ public void start() { * Stops the invalidation client. */ public void stop() { - Intent intent = new Intent(mContext, InvalidationService.class); + Intent intent = new Intent(mContext, InvalidationClientService.class); intent.putExtra(InvalidationIntentProtocol.EXTRA_STOP, true); mContext.startService(intent); } @@ -102,7 +82,6 @@ public void stop() { * * Calling this method will create the instance if it does not yet exist. */ - @CalledByNative public static InvalidationController get(Context context) { synchronized (LOCK) { if (sInstance == null) { @@ -133,16 +112,4 @@ public void onApplicationStateChange(int newState) { } } } - - /** - * Fetches the Invalidator client name. - * - * Note that there is a naming discrepancy here. In C++, we refer to the invalidation client - * identifier that is unique for every invalidation client instance in an account as the client - * ID. In Java, we call it the client name. - */ - @CalledByNative - public byte[] getInvalidatorClientId() { - return InvalidationClientNameProvider.get().getInvalidatorClientName(); - } } diff --git a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java new file mode 100644 index 000000000000..3b363b7b12f2 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java @@ -0,0 +1,50 @@ +// Copyright 2014 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.JNINamespace; +import org.chromium.base.ThreadUtils; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.components.invalidation.InvalidationService; + +import java.util.HashMap; +import java.util.Map; + +/** + * InvalidationServiceFactory maps Profiles to instances of + * {@link InvalidationService} instances. Each {@link Profile} will at most + * have one instance of this service. If the service does not already exist, + * it will be created on the first access. + */ +@JNINamespace("invalidation") +public final class InvalidationServiceFactory { + + private static final Map sServiceMap = + new HashMap(); + + private InvalidationServiceFactory() {} + + /** + * Returns Java InvalidationService for the given Profile. + */ + public static InvalidationService getForProfile(Profile profile) { + ThreadUtils.assertOnUiThread(); + InvalidationService service = sServiceMap.get(profile); + if (service == null) { + service = nativeGetForProfile(profile); + sServiceMap.put(profile, service); + } + return service; + } + + public static InvalidationService getForTest(Context context) { + return nativeGetForTest(context); + } + + private static native InvalidationService nativeGetForProfile(Profile profile); + private static native InvalidationService nativeGetForTest(Context context); +} diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ChromiumSyncAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ChromiumSyncAdapter.java index 23d227727c39..1ba89c4fde94 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ChromiumSyncAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ChromiumSyncAdapter.java @@ -19,6 +19,8 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.library_loader.ProcessInitException; +import org.chromium.chrome.browser.invalidation.InvalidationServiceFactory; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.content.browser.BrowserStartupController; import java.util.concurrent.Semaphore; @@ -167,12 +169,13 @@ public void onFailure() { @VisibleForTesting public void requestSync(int objectSource, String objectId, long version, String payload) { - ProfileSyncService.get(mApplication) + InvalidationServiceFactory.getForProfile(Profile.getLastUsedProfile()) .requestSyncFromNativeChrome(objectSource, objectId, version, payload); } @VisibleForTesting public void requestSyncForAllTypes() { - ProfileSyncService.get(mApplication).requestSyncFromNativeChromeForAllTypes(); + InvalidationServiceFactory.getForProfile(Profile.getLastUsedProfile()) + .requestSyncFromNativeChromeForAllTypes(); } } diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java index d47f8e0547cc..aac2631f5590 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java @@ -11,6 +11,8 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.identity.UniqueIdentificationGenerator; +import org.chromium.chrome.browser.invalidation.InvalidationServiceFactory; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.sync.internal_api.pub.SyncDecryptionPassphraseType; import org.chromium.sync.internal_api.pub.base.ModelType; @@ -35,8 +37,11 @@ */ public class ProfileSyncService { + /** + * Listener for the underlying sync status. + */ public interface SyncStateChangedListener { - // Invoked when the underlying sync status has changed. + // Invoked when the status has changed. public void syncStateChanged(); } @@ -138,25 +143,13 @@ public void syncSignInWithAuthToken(String account, String authToken) { syncSignIn(account); } - public void requestSyncFromNativeChrome( - int objectSource, String objectId, long version, String payload) { - ThreadUtils.assertOnUiThread(); - nativeNudgeSyncer( - mNativeProfileSyncServiceAndroid, objectSource, objectId, version, payload); - } - + // TODO(maxbogue): Remove once downstream use is removed. See http://crbug.com/259559. + // Callers should use InvalidationService.requestSyncFromNativeChromeForAllTypes() instead. + @Deprecated public void requestSyncFromNativeChromeForAllTypes() { ThreadUtils.assertOnUiThread(); - nativeNudgeSyncerForAllTypes(mNativeProfileSyncServiceAndroid); - } - - /** - * Nudge the syncer to start a new sync cycle. - */ - @VisibleForTesting - public void requestSyncCycleForTest() { - ThreadUtils.assertOnUiThread(); - requestSyncFromNativeChromeForAllTypes(); + InvalidationServiceFactory.getForProfile(Profile.getLastUsedProfile()) + .requestSyncFromNativeChromeForAllTypes(); } public String querySyncStatus() { @@ -545,10 +538,6 @@ private static String modelTypeSelectionToStringForTest(long modelTypeSelection) } // Native methods - private native void nativeNudgeSyncer( - long nativeProfileSyncServiceAndroid, int objectSource, String objectId, long version, - String payload); - private native void nativeNudgeSyncerForAllTypes(long nativeProfileSyncServiceAndroid); private native long nativeInit(); private native void nativeEnableSync(long nativeProfileSyncServiceAndroid); private native void nativeDisableSync(long nativeProfileSyncServiceAndroid); diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/IntentSavingContext.java b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/IntentSavingContext.java new file mode 100644 index 000000000000..ba04beb15033 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/IntentSavingContext.java @@ -0,0 +1,45 @@ +// Copyright 2014 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.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; + +import org.chromium.base.test.util.AdvancedMockContext; + +import java.util.ArrayList; +import java.util.List; + +/** + * Mock context that saves all intents given to {@code startService}. + */ +public class IntentSavingContext extends AdvancedMockContext { + private final List mStartedIntents = new ArrayList(); + + IntentSavingContext(Context targetContext) { + super(targetContext); + } + + @Override + public ComponentName startService(Intent intent) { + mStartedIntents.add(intent); + return new ComponentName(this, getClass()); + } + + int getNumStartedIntents() { + return mStartedIntents.size(); + } + + Intent getStartedIntent(int idx) { + return mStartedIntents.get(idx); + } + + @Override + public PackageManager getPackageManager() { + return getBaseContext().getPackageManager(); + } +} diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java index ed9ea0cb034b..3d862848f2e6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java @@ -6,25 +6,19 @@ import android.accounts.Account; import android.app.Activity; -import android.content.ComponentName; -import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.SmallTest; -import com.google.ipc.invalidation.external.client.types.ObjectId; - import org.chromium.base.ActivityState; import org.chromium.base.ApplicationState; import org.chromium.base.ApplicationStatus; import org.chromium.base.CollectionUtil; -import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.Feature; +import org.chromium.components.invalidation.InvalidationClientService; import org.chromium.sync.internal_api.pub.base.ModelType; import org.chromium.sync.notifier.InvalidationIntentProtocol; import org.chromium.sync.notifier.InvalidationPreferences; -import org.chromium.sync.notifier.InvalidationService; import org.chromium.sync.notifier.SyncStatusHelper; import org.chromium.sync.signin.AccountManagerHelper; import org.chromium.sync.signin.ChromeSigninController; @@ -288,67 +282,13 @@ public void setRegisteredTypes( assertEquals(true, resultAllTypes.get()); } - @SmallTest - @Feature({"Sync"}) - public void testSetRegisteredObjectIds() { - InvalidationController controller = new InvalidationController(mContext); - ObjectId bookmark = ModelType.BOOKMARK.toObjectId(); - controller.setRegisteredObjectIds(new int[] {1, 2, bookmark.getSource()}, - new String[] {"a", "b", new String(bookmark.getName())}); - assertEquals(1, mContext.getNumStartedIntents()); - - // Validate destination. - Intent intent = mContext.getStartedIntent(0); - validateIntentComponent(intent); - assertEquals(InvalidationIntentProtocol.ACTION_REGISTER, intent.getAction()); - - // Validate registered object ids. The bookmark object should not be registered since it is - // a Sync type. - assertNull(intent.getStringArrayListExtra( - InvalidationIntentProtocol.EXTRA_REGISTERED_TYPES)); - Set objectIds = InvalidationIntentProtocol.getRegisteredObjectIds(intent); - assertEquals(2, objectIds.size()); - assertTrue(objectIds.contains(ObjectId.newInstance(1, "a".getBytes()))); - assertTrue(objectIds.contains(ObjectId.newInstance(2, "b".getBytes()))); - } - /** * Asserts that {@code intent} is destined for the correct component. */ private static void validateIntentComponent(Intent intent) { assertNotNull(intent.getComponent()); - assertEquals(InvalidationService.class.getName(), + assertEquals(InvalidationClientService.class.getName(), intent.getComponent().getClassName()); } - /** - * Mock context that saves all intents given to {@code startService}. - */ - private static class IntentSavingContext extends AdvancedMockContext { - private final List mStartedIntents = new ArrayList(); - - IntentSavingContext(Context targetContext) { - super(targetContext); - } - - @Override - public ComponentName startService(Intent intent) { - mStartedIntents.add(intent); - return new ComponentName(this, getClass()); - } - - int getNumStartedIntents() { - return mStartedIntents.size(); - } - - Intent getStartedIntent(int idx) { - return mStartedIntents.get(idx); - } - - @Override - public PackageManager getPackageManager() { - return getBaseContext().getPackageManager(); - } - } - } diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java new file mode 100644 index 000000000000..884b10060d9c --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java @@ -0,0 +1,76 @@ +// 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.Intent; +import android.test.UiThreadTest; +import android.test.suitebuilder.annotation.SmallTest; + +import com.google.ipc.invalidation.external.client.types.ObjectId; + +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.shell.ChromeShellTestBase; +import org.chromium.components.invalidation.InvalidationClientService; +import org.chromium.components.invalidation.InvalidationService; +import org.chromium.sync.internal_api.pub.base.ModelType; +import org.chromium.sync.notifier.InvalidationIntentProtocol; +import org.chromium.sync.notifier.SyncStatusHelper; +import org.chromium.sync.test.util.MockSyncContentResolverDelegate; + +import java.util.Set; + +/** + * Tests for {@link InvalidationService}. + */ +public class InvalidationServiceTest extends ChromeShellTestBase { + private IntentSavingContext mContext; + + @Override + protected void setUp() throws Exception { + super.setUp(); + startChromeBrowserProcessSync(getInstrumentation().getTargetContext()); + mContext = new IntentSavingContext(getInstrumentation().getTargetContext()); + // We don't want to use the system content resolver, so we override it. + MockSyncContentResolverDelegate delegate = new MockSyncContentResolverDelegate(); + // Android master sync can safely always be on. + delegate.setMasterSyncAutomatically(true); + SyncStatusHelper.overrideSyncStatusHelperForTests(mContext, delegate); + } + + @SmallTest + @UiThreadTest + @Feature({"Sync"}) + public void testSetRegisteredObjectIds() { + InvalidationService service = InvalidationServiceFactory.getForTest(mContext); + ObjectId bookmark = ModelType.BOOKMARK.toObjectId(); + service.setRegisteredObjectIds(new int[] {1, 2, bookmark.getSource()}, + new String[] {"a", "b", new String(bookmark.getName())}); + assertEquals(1, mContext.getNumStartedIntents()); + + // Validate destination. + Intent intent = mContext.getStartedIntent(0); + validateIntentComponent(intent); + assertEquals(InvalidationIntentProtocol.ACTION_REGISTER, intent.getAction()); + + // Validate registered object ids. The bookmark object should not be registered since it is + // a Sync type. + assertNull(intent.getStringArrayListExtra( + InvalidationIntentProtocol.EXTRA_REGISTERED_TYPES)); + Set objectIds = InvalidationIntentProtocol.getRegisteredObjectIds(intent); + assertEquals(2, objectIds.size()); + assertTrue(objectIds.contains(ObjectId.newInstance(1, "a".getBytes()))); + assertTrue(objectIds.contains(ObjectId.newInstance(2, "b".getBytes()))); + } + + /** + * Asserts that {@code intent} is destined for the correct component. + */ + private static void validateIntentComponent(Intent intent) { + assertNotNull(intent.getComponent()); + assertEquals(InvalidationClientService.class.getName(), + intent.getComponent().getClassName()); + } + +} diff --git a/chrome/android/shell/java/AndroidManifest.xml b/chrome/android/shell/java/AndroidManifest.xml index 442b5b5c8dfa..e18acc777a62 100644 --- a/chrome/android/shell/java/AndroidManifest.xml +++ b/chrome/android/shell/java/AndroidManifest.xml @@ -181,8 +181,8 @@ - + diff --git a/chrome/android/sync_shell/java/AndroidManifest.xml b/chrome/android/sync_shell/java/AndroidManifest.xml index 27deba3a0abe..358b88b0b5c8 100644 --- a/chrome/android/sync_shell/java/AndroidManifest.xml +++ b/chrome/android/sync_shell/java/AndroidManifest.xml @@ -176,8 +176,8 @@ - + diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index da7f67b4d369..b00c16f6c090 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc @@ -44,7 +44,7 @@ #include "chrome/browser/dom_distiller/dom_distiller_service_factory_android.h" #include "chrome/browser/dom_distiller/tab_utils_android.h" #include "chrome/browser/history/android/sqlite_cursor.h" -#include "chrome/browser/invalidation/invalidation_controller_android.h" +#include "chrome/browser/invalidation/invalidation_service_factory_android.h" #include "chrome/browser/lifetime/application_lifetime_android.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.h" #include "chrome/browser/prerender/external_prerender_handler_android.h" @@ -76,6 +76,7 @@ #include "components/bookmarks/common/android/component_jni_registrar.h" #include "components/dom_distiller/android/component_jni_registrar.h" #include "components/gcm_driver/android/component_jni_registrar.h" +#include "components/invalidation/android/component_jni_registrar.h" #include "components/navigation_interception/component_jni_registrar.h" #include "components/variations/android/component_jni_registrar.h" #include "components/web_contents_delegate_android/component_jni_registrar.h" @@ -94,6 +95,7 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = { { "Bookmarks", bookmarks::android::RegisterBookmarks }, { "DomDistiller", dom_distiller::android::RegisterDomDistiller }, { "GCMDriver", gcm::android::RegisterGCMDriverJni }, + { "Invalidation", invalidation::android::RegisterInvalidationJni }, { "NavigationInterception", navigation_interception::RegisterNavigationInterceptionJni }, { "WebContentsDelegateAndroid", @@ -148,9 +150,10 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = { { "ForeignSessionHelper", ForeignSessionHelper::RegisterForeignSessionHelper }, { "InfoBarContainer", RegisterInfoBarContainer }, + { "InvalidationServiceFactory", + invalidation::InvalidationServiceFactoryAndroid::Register }, { "ShortcutHelper", ShortcutHelper::RegisterShortcutHelper }, { "IntentHelper", RegisterIntentHelper }, - { "InvalidationController", invalidation::RegisterInvalidationController }, { "JavascriptAppModalDialog", JavascriptAppModalDialogAndroid::RegisterJavascriptAppModalDialog }, { "LogoBridge", RegisterLogoBridge }, diff --git a/chrome/browser/invalidation/invalidation_controller_android.cc b/chrome/browser/invalidation/invalidation_controller_android.cc deleted file mode 100644 index 021027c4d0c0..000000000000 --- a/chrome/browser/invalidation/invalidation_controller_android.cc +++ /dev/null @@ -1,75 +0,0 @@ -// 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. - -#include "chrome/browser/invalidation/invalidation_controller_android.h" - -#include -#include - -#include "base/android/jni_array.h" -#include "chrome/jni/InvalidationController_jni.h" -#include "google/cacheinvalidation/include/types.h" - -namespace invalidation { - -InvalidationControllerAndroid::InvalidationControllerAndroid() {} - -InvalidationControllerAndroid::~InvalidationControllerAndroid() {} - -void InvalidationControllerAndroid::SetRegisteredObjectIds( - const syncer::ObjectIdSet& ids) { - // Get a reference to the Java invalidation controller. - JNIEnv* env = base::android::AttachCurrentThread(); - DCHECK(env); - if (invalidation_controller_.is_null()) { - invalidation_controller_.Reset(Java_InvalidationController_get( - env, - base::android::GetApplicationContext())); - } - - // To call the corresponding method on the Java invalidation controller, split - // the object ids into object source and object name arrays. - std::vector sources; - std::vector names; - syncer::ObjectIdSet::const_iterator id; - for (id = ids.begin(); id != ids.end(); ++id) { - sources.push_back(id->source()); - names.push_back(id->name()); - } - - Java_InvalidationController_setRegisteredObjectIds( - env, - invalidation_controller_.obj(), - base::android::ToJavaIntArray(env, sources).obj(), - base::android::ToJavaArrayOfStrings(env, names).obj()); -} - -std::string InvalidationControllerAndroid::GetInvalidatorClientId() { - JNIEnv* env = base::android::AttachCurrentThread(); - DCHECK(env); - if (invalidation_controller_.is_null()) { - invalidation_controller_.Reset(Java_InvalidationController_get( - env, - base::android::GetApplicationContext())); - } - - // Ask the Java code to for the invalidator ID it's currently using. - base::android::ScopedJavaLocalRef<_jbyteArray*> id_bytes_java = - Java_InvalidationController_getInvalidatorClientId( - env, - invalidation_controller_.obj()); - - // Convert it into a more convenient format for C++. - std::vector id_bytes; - base::android::JavaByteArrayToByteVector(env, id_bytes_java.obj(), &id_bytes); - std::string id(id_bytes.begin(), id_bytes.end()); - - return id; -} - -bool RegisterInvalidationController(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace invalidation diff --git a/chrome/browser/invalidation/invalidation_controller_android.h b/chrome/browser/invalidation/invalidation_controller_android.h deleted file mode 100644 index c55601faa435..000000000000 --- a/chrome/browser/invalidation/invalidation_controller_android.h +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_CONTROLLER_ANDROID_H_ -#define CHROME_BROWSER_INVALIDATION_INVALIDATION_CONTROLLER_ANDROID_H_ - -#include - -#include "base/android/jni_android.h" -#include "base/android/jni_weak_ref.h" -#include "components/invalidation/invalidation_util.h" - -namespace invalidation { - -// Controls invalidation registration on Android. This class is a wrapper for -// the Java class org.chromium.sync.notifier.InvalidationController. -class InvalidationControllerAndroid { - public: - InvalidationControllerAndroid(); - virtual ~InvalidationControllerAndroid(); - - // Sets object ids for which the invalidation client should register for - // notification. - virtual void SetRegisteredObjectIds(const syncer::ObjectIdSet& ids); - - // Asks the Java code to return the client ID it chose to use. - std::string GetInvalidatorClientId(); - - private: - // The Java invalidation controller. - base::android::ScopedJavaGlobalRef invalidation_controller_; - - DISALLOW_COPY_AND_ASSIGN(InvalidationControllerAndroid); -}; - -bool RegisterInvalidationController(JNIEnv* env); - -} // namespace invalidation - -#endif // CHROME_BROWSER_INVALIDATION_INVALIDATION_CONTROLLER_ANDROID_H_ diff --git a/chrome/browser/invalidation/invalidation_service_android.cc b/chrome/browser/invalidation/invalidation_service_android.cc deleted file mode 100644 index 5c62ecf5a3a0..000000000000 --- a/chrome/browser/invalidation/invalidation_service_android.cc +++ /dev/null @@ -1,107 +0,0 @@ -// 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. - -#include "chrome/browser/invalidation/invalidation_service_android.h" - -#include "base/callback.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/invalidation/invalidation_controller_android.h" -#include "components/invalidation/object_id_invalidation_map.h" -#include "content/public/browser/notification_service.h" - -namespace invalidation { - -InvalidationServiceAndroid::InvalidationServiceAndroid( - Profile* profile, - InvalidationControllerAndroid* invalidation_controller) - : invalidator_state_(syncer::INVALIDATIONS_ENABLED), - invalidation_controller_(invalidation_controller), - logger_() { - DCHECK(CalledOnValidThread()); - DCHECK(invalidation_controller); - registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, - content::Source(profile)); -} - -InvalidationServiceAndroid::~InvalidationServiceAndroid() { } - -void InvalidationServiceAndroid::RegisterInvalidationHandler( - syncer::InvalidationHandler* handler) { - DCHECK(CalledOnValidThread()); - invalidator_registrar_.RegisterHandler(handler); - logger_.OnRegistration(handler->GetOwnerName()); -} - -void InvalidationServiceAndroid::UpdateRegisteredInvalidationIds( - syncer::InvalidationHandler* handler, - const syncer::ObjectIdSet& ids) { - DCHECK(CalledOnValidThread()); - invalidator_registrar_.UpdateRegisteredIds(handler, ids); - invalidation_controller_->SetRegisteredObjectIds( - invalidator_registrar_.GetAllRegisteredIds()); - logger_.OnUpdateIds(invalidator_registrar_.GetSanitizedHandlersIdsMap()); -} - -void InvalidationServiceAndroid::UnregisterInvalidationHandler( - syncer::InvalidationHandler* handler) { - DCHECK(CalledOnValidThread()); - invalidator_registrar_.UnregisterHandler(handler); - logger_.OnUnregistration(handler->GetOwnerName()); -} - -syncer::InvalidatorState -InvalidationServiceAndroid::GetInvalidatorState() const { - DCHECK(CalledOnValidThread()); - return invalidator_state_; -} - -std::string InvalidationServiceAndroid::GetInvalidatorClientId() const { - DCHECK(CalledOnValidThread()); - return invalidation_controller_->GetInvalidatorClientId(); -} - -InvalidationLogger* InvalidationServiceAndroid::GetInvalidationLogger() { - return &logger_; -} - -void InvalidationServiceAndroid::RequestDetailedStatus( - base::Callback return_callback) const { -} - -IdentityProvider* InvalidationServiceAndroid::GetIdentityProvider() { - return NULL; -} - -void InvalidationServiceAndroid::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_REMOTE); - - content::Details - state_details(details); - const syncer::ObjectIdInvalidationMap object_invalidation_map = - *(state_details.ptr()); - - // An empty map implies that we should invalidate all. - const syncer::ObjectIdInvalidationMap& effective_invalidation_map = - object_invalidation_map.Empty() ? - syncer::ObjectIdInvalidationMap::InvalidateAll( - invalidator_registrar_.GetAllRegisteredIds()) : - object_invalidation_map; - - invalidator_registrar_.DispatchInvalidationsToHandlers( - effective_invalidation_map); - logger_.OnInvalidation(effective_invalidation_map); -} - -void InvalidationServiceAndroid::TriggerStateChangeForTest( - syncer::InvalidatorState state) { - DCHECK(CalledOnValidThread()); - invalidator_state_ = state; - invalidator_registrar_.UpdateInvalidatorState(invalidator_state_); -} - -} // namespace invalidation diff --git a/chrome/browser/invalidation/invalidation_service_android_unittest.cc b/chrome/browser/invalidation/invalidation_service_android_unittest.cc deleted file mode 100644 index 1cce59a6c3a0..000000000000 --- a/chrome/browser/invalidation/invalidation_service_android_unittest.cc +++ /dev/null @@ -1,171 +0,0 @@ -// 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. - -#include "chrome/browser/invalidation/invalidation_service_android.h" - -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/invalidation/invalidation_controller_android.h" -#include "chrome/test/base/testing_profile.h" -#include "components/invalidation/fake_invalidation_handler.h" -#include "components/invalidation/invalidation_service_test_template.h" -#include "content/public/browser/notification_service.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace invalidation { - -class MockInvalidationControllerAndroid : public InvalidationControllerAndroid { - public: - MockInvalidationControllerAndroid() {} - virtual ~MockInvalidationControllerAndroid() {} - - virtual void SetRegisteredObjectIds(const syncer::ObjectIdSet& ids) OVERRIDE { - registered_ids_ = ids; - } - - syncer::ObjectIdSet registered_ids_; -}; - -class InvalidationServiceAndroidTestDelegate { - public: - InvalidationServiceAndroidTestDelegate() {} - - ~InvalidationServiceAndroidTestDelegate() {} - - void CreateInvalidationService() { - profile_.reset(new TestingProfile()); - invalidation_service_android_.reset( - new InvalidationServiceAndroid( - profile_.get(), - new MockInvalidationControllerAndroid())); - } - - InvalidationService* GetInvalidationService() { - return invalidation_service_android_.get(); - } - - void DestroyInvalidationService() { - invalidation_service_android_.reset(); - } - - void TriggerOnInvalidatorStateChange(syncer::InvalidatorState state) { - invalidation_service_android_->TriggerStateChangeForTest(state); - } - - void TriggerOnIncomingInvalidation( - const syncer::ObjectIdInvalidationMap& invalidation_map) { - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, - content::Source(profile_.get()), - content::Details( - &invalidation_map)); - } - - scoped_ptr profile_; - scoped_ptr invalidation_service_android_; -}; - -INSTANTIATE_TYPED_TEST_CASE_P( - AndroidInvalidationServiceTest, InvalidationServiceTest, - InvalidationServiceAndroidTestDelegate); - -class InvalidationServiceAndroidRegistrationTest : public testing::Test { - protected: - InvalidationServiceAndroidRegistrationTest() - : invalidation_controller_(new MockInvalidationControllerAndroid()), - invalidation_service_(&profile_, invalidation_controller_) {} - - virtual ~InvalidationServiceAndroidRegistrationTest() {} - - // Get the invalidation service being tested. - InvalidationService& invalidation_service() { - return invalidation_service_; - } - - // Get the number of objects which are registered. - size_t RegisteredObjectCount() { - return registered_ids().size(); - } - - // Determines if the given object id is registered with the invalidation - // controller. - bool IsRegistered(const invalidation::ObjectId& id) { - return registered_ids().find(id) != registered_ids().end(); - } - - private: - // Get the set of objects registered with the invalidation controller. - const syncer::ObjectIdSet& registered_ids() { - return invalidation_controller_->registered_ids_; - } - - TestingProfile profile_; - MockInvalidationControllerAndroid* invalidation_controller_; - InvalidationServiceAndroid invalidation_service_; -}; - -TEST_F(InvalidationServiceAndroidRegistrationTest, NoObjectRegistration) { - syncer::FakeInvalidationHandler handler; - invalidation_service().RegisterInvalidationHandler(&handler); - EXPECT_EQ(0U, RegisteredObjectCount()); - invalidation_service().UnregisterInvalidationHandler(&handler); -} - -TEST_F(InvalidationServiceAndroidRegistrationTest, UpdateObjectRegistration) { - syncer::FakeInvalidationHandler handler; - invalidation::ObjectId id1(1, "A"); - invalidation::ObjectId id2(2, "B"); - syncer::ObjectIdSet ids; - invalidation_service().RegisterInvalidationHandler(&handler); - - // Register for both objects. - ids.insert(id1); - ids.insert(id2); - invalidation_service().UpdateRegisteredInvalidationIds(&handler, ids); - EXPECT_EQ(2U, RegisteredObjectCount()); - EXPECT_TRUE(IsRegistered(id1)); - EXPECT_TRUE(IsRegistered(id2)); - - // Unregister for object 2. - ids.erase(id2); - invalidation_service().UpdateRegisteredInvalidationIds(&handler, ids); - EXPECT_EQ(1U, RegisteredObjectCount()); - EXPECT_TRUE(IsRegistered(id1)); - - // Unregister for object 1. - ids.erase(id1); - invalidation_service().UpdateRegisteredInvalidationIds(&handler, ids); - EXPECT_EQ(0U, RegisteredObjectCount()); - - invalidation_service().UnregisterInvalidationHandler(&handler); -} - -#if defined(OS_ANDROID) - -class InvalidationServiceAndroidTest : public testing::Test { - public: - InvalidationServiceAndroidTest() - : invalidation_service_(&profile_, new InvalidationControllerAndroid()) {} - virtual ~InvalidationServiceAndroidTest() {} - - InvalidationService& invalidation_service() { - return invalidation_service_; - } - - private: - TestingProfile profile_; - InvalidationServiceAndroid invalidation_service_; -}; - -TEST_F(InvalidationServiceAndroidTest, FetchClientId) { - const std::string id1 = invalidation_service().GetInvalidatorClientId(); - ASSERT_FALSE(id1.empty()); - - // If nothing else, the ID should be consistent. - const std::string id2 = invalidation_service().GetInvalidatorClientId(); - ASSERT_EQ(id1, id2); -} - -#endif - -} // namespace invalidation diff --git a/chrome/browser/invalidation/invalidation_service_factory_android.cc b/chrome/browser/invalidation/invalidation_service_factory_android.cc new file mode 100644 index 000000000000..4f6b55cd98c7 --- /dev/null +++ b/chrome/browser/invalidation/invalidation_service_factory_android.cc @@ -0,0 +1,53 @@ +// Copyright 2014 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. + +#include "chrome/browser/invalidation/invalidation_service_factory_android.h" + +#include "base/android/jni_android.h" +#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_android.h" +#include "components/invalidation/invalidation_service_android.h" +#include "components/invalidation/profile_invalidation_provider.h" +#include "jni/InvalidationServiceFactory_jni.h" + +using base::android::ScopedJavaLocalRef; + +namespace invalidation { + +jobject InvalidationServiceFactoryAndroid::GetForProfile(JNIEnv* env, + jclass clazz, + jobject j_profile) { + Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); + invalidation::ProfileInvalidationProvider* provider = + ProfileInvalidationProviderFactory::GetForProfile(profile); + InvalidationServiceAndroid* service_android = + static_cast( + provider->GetInvalidationService()); + return service_android->java_ref_.obj(); +} + +jobject InvalidationServiceFactoryAndroid::GetForTest(JNIEnv* env, + jclass clazz, + jobject j_context) { + InvalidationServiceAndroid* service_android = + new InvalidationServiceAndroid(j_context); + return service_android->java_ref_.obj(); +} + +jobject GetForProfile(JNIEnv* env, jclass clazz, jobject j_profile) { + return InvalidationServiceFactoryAndroid::GetForProfile( + env, clazz, j_profile); +} + +jobject GetForTest(JNIEnv* env, jclass clazz, jobject j_context) { + return InvalidationServiceFactoryAndroid::GetForTest( + env, clazz, j_context); +} + +bool InvalidationServiceFactoryAndroid::Register(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace invalidation diff --git a/chrome/browser/invalidation/invalidation_service_factory_android.h b/chrome/browser/invalidation/invalidation_service_factory_android.h new file mode 100644 index 000000000000..c4edb3aabc15 --- /dev/null +++ b/chrome/browser/invalidation/invalidation_service_factory_android.h @@ -0,0 +1,23 @@ +// Copyright 2014 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. + +#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_FACTORY_ANDROID_H_ +#define CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_FACTORY_ANDROID_H_ + +#include + +namespace invalidation { + +// This class should not be used except from the Java class +// InvalidationServiceFactory. +class InvalidationServiceFactoryAndroid { + public: + static jobject GetForProfile(JNIEnv* env, jclass clazz, jobject j_profile); + static jobject GetForTest(JNIEnv* env, jclass clazz, jobject j_context); + static bool Register(JNIEnv* env); +}; + +} // namespace invalidation + +#endif // CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_FACTORY_ANDROID_H_ diff --git a/chrome/browser/invalidation/profile_invalidation_provider_factory.cc b/chrome/browser/invalidation/profile_invalidation_provider_factory.cc index 3c1bc710204b..bba9b3309c66 100644 --- a/chrome/browser/invalidation/profile_invalidation_provider_factory.cc +++ b/chrome/browser/invalidation/profile_invalidation_provider_factory.cc @@ -30,8 +30,8 @@ #include "net/url_request/url_request_context_getter.h" #if defined(OS_ANDROID) -#include "chrome/browser/invalidation/invalidation_controller_android.h" -#include "chrome/browser/invalidation/invalidation_service_android.h" +#include "base/android/jni_android.h" +#include "components/invalidation/invalidation_service_android.h" #endif // defined(OS_ANDROID) #if defined(OS_CHROMEOS) @@ -94,15 +94,12 @@ void ProfileInvalidationProviderFactory::RegisterTestingFactory( KeyedService* ProfileInvalidationProviderFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { - Profile* profile = static_cast(context); - if (testing_factory_) return testing_factory_(context); #if defined(OS_ANDROID) return new ProfileInvalidationProvider(scoped_ptr( - new InvalidationServiceAndroid(profile, - new InvalidationControllerAndroid()))); + new InvalidationServiceAndroid(base::android::GetApplicationContext()))); #else scoped_ptr identity_provider; @@ -117,6 +114,7 @@ KeyedService* ProfileInvalidationProviderFactory::BuildServiceInstanceFor( chromeos::DeviceOAuth2TokenServiceFactory::Get())); } #endif + Profile* profile = Profile::FromBrowserContext(context); if (!identity_provider) { identity_provider.reset(new ProfileIdentityProvider( diff --git a/chrome/browser/sync/profile_sync_service_android.cc b/chrome/browser/sync/profile_sync_service_android.cc index 567297cc9c73..7bfaff741865 100644 --- a/chrome/browser/sync/profile_sync_service_android.cc +++ b/chrome/browser/sync/profile_sync_service_android.cc @@ -15,7 +15,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/about_sync_util.h" @@ -23,13 +22,10 @@ #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/sync_ui_util.h" #include "chrome/grit/generated_resources.h" -#include "components/invalidation/object_id_invalidation_map.h" #include "components/signin/core/browser/signin_manager.h" #include "components/sync_driver/pref_names.h" #include "components/sync_driver/sync_prefs.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" #include "google/cacheinvalidation/types.pb.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/google_service_auth_error.h" @@ -92,42 +88,6 @@ ProfileSyncServiceAndroid::~ProfileSyncServiceAndroid() { RemoveObserver(); } -void ProfileSyncServiceAndroid::SendNudgeNotification( - int object_source, - const std::string& str_object_id, - int64 version, - const std::string& state) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - // TODO(nileshagrawal): Merge this with ChromeInvalidationClient::Invalidate. - // Construct the ModelTypeStateMap and send it over with the notification. - invalidation::ObjectId object_id( - object_source, - str_object_id); - syncer::ObjectIdInvalidationMap object_ids_with_states; - if (version == ipc::invalidation::Constants::UNKNOWN) { - object_ids_with_states.Insert( - syncer::Invalidation::InitUnknownVersion(object_id)); - } else { - ObjectIdVersionMap::iterator it = - max_invalidation_versions_.find(object_id); - if ((it != max_invalidation_versions_.end()) && - (version <= it->second)) { - DVLOG(1) << "Dropping redundant invalidation with version " << version; - return; - } - max_invalidation_versions_[object_id] = version; - object_ids_with_states.Insert( - syncer::Invalidation::Init(object_id, version, state)); - } - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, - content::Source(profile_), - content::Details( - &object_ids_with_states)); -} - void ProfileSyncServiceAndroid::OnStateChanged() { // Notify the java world that our sync state has changed. JNIEnv* env = AttachCurrentThread(); @@ -504,28 +464,6 @@ std::string ProfileSyncServiceAndroid::ModelTypeSelectionToStringForTest( return ConvertJavaStringToUTF8(string); } -void ProfileSyncServiceAndroid::NudgeSyncer(JNIEnv* env, - jobject obj, - jint objectSource, - jstring objectId, - jlong version, - jstring state) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - SendNudgeNotification(objectSource, ConvertJavaStringToUTF8(env, objectId), - version, ConvertJavaStringToUTF8(env, state)); -} - -void ProfileSyncServiceAndroid::NudgeSyncerForAllTypes(JNIEnv* env, - jobject obj) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - syncer::ObjectIdInvalidationMap object_ids_with_states; - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, - content::Source(profile_), - content::Details( - &object_ids_with_states)); -} - // static ProfileSyncServiceAndroid* ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid() { diff --git a/chrome/browser/sync/profile_sync_service_android.h b/chrome/browser/sync/profile_sync_service_android.h index 66e859cbd4f6..993b19287580 100644 --- a/chrome/browser/sync/profile_sync_service_android.h +++ b/chrome/browser/sync/profile_sync_service_android.h @@ -34,20 +34,6 @@ class ProfileSyncServiceAndroid : public ProfileSyncServiceObserver { // This method should be called once right after contructing the object. void Init(); - // Called from Java when we need to nudge native syncer. The |objectSource|, - // |objectId|, |version| and |payload| values should come from an - // invalidation. - void NudgeSyncer(JNIEnv* env, - jobject obj, - jint objectSource, - jstring objectId, - jlong version, - jstring payload); - - // Called from Java when we need to nudge native syncer but have lost state on - // which types have changed. - void NudgeSyncerForAllTypes(JNIEnv* env, jobject obj); - // Called from Java when the user manually enables sync void EnableSync(JNIEnv* env, jobject obj); @@ -225,13 +211,6 @@ class ProfileSyncServiceAndroid : public ProfileSyncServiceObserver { virtual ~ProfileSyncServiceAndroid(); // Remove observers to profile sync service. void RemoveObserver(); - // Called from Java when we need to nudge native syncer. The |object_source|, - // |objectId|, |version| and |payload| values should come from an - // invalidation. - void SendNudgeNotification(int object_source, - const std::string& str_object_id, - int64 version, - const std::string& payload); Profile* profile_; ProfileSyncService* sync_service_; @@ -242,11 +221,6 @@ class ProfileSyncServiceAndroid : public ProfileSyncServiceObserver { // Java-side ProfileSyncService object. JavaObjectWeakGlobalRef weak_java_profile_sync_service_; - // The invalidation API spec allows for the possibility of redundant - // invalidations, so keep track of the max versions and drop - // invalidations with old versions. - ObjectIdVersionMap max_invalidation_versions_; - DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceAndroid); }; diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index db9e88f79fc5..40ec2bbacce6 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -591,6 +591,7 @@ '../components/components.gyp:bookmarks_java', '../components/components.gyp:dom_distiller_core_java', '../components/components.gyp:gcm_driver_java', + '../components/components.gyp:invalidation_java', '../components/components.gyp:navigation_interception_java', '../components/components.gyp:sessions', '../components/components.gyp:variations_java', diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 026edf9fd882..d434a0584711 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -585,10 +585,8 @@ 'browser/internal_auth.h', 'browser/intranet_redirect_detector.cc', 'browser/intranet_redirect_detector.h', - 'browser/invalidation/invalidation_controller_android.cc', - 'browser/invalidation/invalidation_controller_android.h', - 'browser/invalidation/invalidation_service_android.cc', - 'browser/invalidation/invalidation_service_android.h', + 'browser/invalidation/invalidation_service_factory_android.cc', + 'browser/invalidation/invalidation_service_factory_android.h', 'browser/invalidation/profile_invalidation_provider_factory.cc', 'browser/invalidation/profile_invalidation_provider_factory.h', 'browser/io_thread.cc', @@ -2761,7 +2759,7 @@ 'android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java', 'android/java/src/org/chromium/chrome/browser/infobar/SavePasswordInfoBarDelegate.java', 'android/java/src/org/chromium/chrome/browser/infobar/TranslateInfoBarDelegate.java', - 'android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java', + 'android/java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java', 'android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java' ], }, diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 613edfdce102..fce3e37368ad 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -2799,6 +2799,7 @@ 'chrome_java_test_support', '../base/base.gyp:base', '../base/base.gyp:base_java_test_support', + '../components/components.gyp:invalidation_javatests', '../content/content_shell_and_tests.gyp:content_java_test_support', '../sync/sync.gyp:sync_javatests', ], diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index e338438368fc..d982db2a85bf 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -488,7 +488,6 @@ 'browser/install_verification/win/module_verification_test.cc', 'browser/install_verification/win/module_verification_test.h', 'browser/invalidation/gcm_invalidation_bridge_unittest.cc', - 'browser/invalidation/invalidation_service_android_unittest.cc', 'browser/invalidation/invalidator_storage_unittest.cc', 'browser/invalidation/ticl_profile_settings_provider_unittest.cc', 'browser/io_thread_unittest.cc', diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java index d525a4ff59ee..7c2d35e4bbdc 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/sync/SyncTestUtil.java @@ -16,6 +16,8 @@ import org.chromium.base.CommandLine; import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.AdvancedMockContext; +import org.chromium.chrome.browser.invalidation.InvalidationServiceFactory; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.sync.ProfileSyncService; import org.chromium.chrome.test.util.TestHttpServerClient; import org.chromium.content.browser.test.util.Criteria; @@ -198,7 +200,8 @@ public static void triggerSyncAndWaitForCompletion(final Context context) ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - ProfileSyncService.get(context).requestSyncCycleForTest(); + InvalidationServiceFactory.getForProfile(Profile.getLastUsedProfile()) + .requestSyncFromNativeChromeForAllTypes(); } }); diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 54fd1652725b..9e6af71b8b63 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp @@ -606,16 +606,19 @@ ], }], ['OS == "android"', { + 'sources': [ + 'invalidation/invalidation_service_android_unittest.cc', + ], 'sources!': [ 'gcm_driver/gcm_account_mapper_unittest.cc', 'gcm_driver/gcm_channel_status_request_unittest.cc', 'gcm_driver/gcm_client_impl_unittest.cc', 'gcm_driver/gcm_delayed_task_controller_unittest.cc', 'gcm_driver/gcm_driver_desktop_unittest.cc', + 'gcm_driver/gcm_stats_recorder_impl_unittest.cc', 'feedback/feedback_common_unittest.cc', 'feedback/feedback_data_unittest.cc', 'feedback/feedback_uploader_unittest.cc', - 'gcm_driver/gcm_stats_recorder_impl_unittest.cc', 'signin/core/browser/mutable_profile_oauth2_token_service_unittest.cc', 'storage_monitor/media_storage_util_unittest.cc', 'storage_monitor/storage_info_unittest.cc', @@ -850,6 +853,7 @@ 'type': 'none', 'dependencies': [ 'components_unittests', + 'components.gyp:invalidation_java', ], 'variables': { 'test_suite_name': 'components_unittests', diff --git a/components/invalidation.gypi b/components/invalidation.gypi index 3da96511bd13..8378c2cd26ed 100644 --- a/components/invalidation.gypi +++ b/components/invalidation.gypi @@ -10,6 +10,7 @@ 'type': 'static_library', 'dependencies': [ '../base/base.gyp:base', + '../base/base.gyp:base_prefs', '../google_apis/google_apis.gyp:google_apis', '../jingle/jingle.gyp:notifier', '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation', @@ -101,6 +102,17 @@ 'invalidation/ticl_settings_provider.h', ], }], + ['OS == "android"', { + 'dependencies': [ + 'invalidation_jni_headers', + ], + 'sources': [ + 'invalidation/android/component_jni_registrar.cc', + 'invalidation/android/component_jni_registrar.h', + 'invalidation/invalidation_service_android.cc', + 'invalidation/invalidation_service_android.h', + ], + }], ], }, @@ -150,7 +162,55 @@ 'invalidation/p2p_invalidation_service.h', ], }], + ['OS == "android"', { + 'dependencies': [ + 'invalidation_jni_headers', + ], + }], ], }, ], + 'conditions': [ + ['OS == "android"', { + 'targets': [ + { + 'target_name': 'invalidation_java', + 'type': 'none', + 'dependencies': [ + '../base/base.gyp:base', + '../sync/sync.gyp:sync_java', + '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_javalib', + ], + 'variables': { + 'java_in_dir': 'invalidation/android/java', + }, + 'includes': [ '../build/java.gypi' ], + }, + { + 'target_name': 'invalidation_javatests', + 'type': 'none', + 'dependencies': [ + 'invalidation_java', + '../base/base.gyp:base_java_test_support', + ], + 'variables': { + 'java_in_dir': 'invalidation/android/javatests', + }, + 'includes': [ '../build/java.gypi' ], + }, + { + 'target_name': 'invalidation_jni_headers', + 'type': 'none', + 'sources': [ + 'invalidation/android/java/src/org/chromium/components/invalidation/InvalidationService.java', + ], + 'variables': { + 'jni_gen_package': 'components/invalidation', + }, + 'includes': [ '../build/jni_generator.gypi' ], + }, + ], + }, + ], + ], } diff --git a/components/invalidation/BUILD.gn b/components/invalidation/BUILD.gn index c1e581b3da0c..b39fe28fa3b5 100644 --- a/components/invalidation/BUILD.gn +++ b/components/invalidation/BUILD.gn @@ -1,6 +1,9 @@ # Copyright 2014 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. +if (is_android) { + import("//build/config/android/rules.gni") +} static_library("invalidation") { sources = [ @@ -75,6 +78,15 @@ static_library("invalidation") { "ticl_settings_provider.h", ] } + if (is_android) { + sources += [ + "android/component_jni_registrar.cc", + "android/component_jni_registrar.h", + "invalidation_service_android.cc", + "invalidation_service_android.h", + ] + deps += [ ":jni_headers" ] + } public_deps = [ "//third_party/cacheinvalidation", @@ -94,6 +106,21 @@ static_library("invalidation") { ] } +static_library("unittests") { + testonly = true + sources = [] + deps = [ + ":invalidation", + ":test_support", + ] + if (is_android) { + deps += [ + ":javatests", + ":jni_headers", + ] + } +} + static_library("test_support") { testonly = true sources = [ @@ -120,7 +147,11 @@ static_library("test_support") { "p2p_invalidation_service.h", ] } - + if (is_android) { + deps += [ + ":jni_headers", + ] + } deps = [ "//base", "//components/gcm_driver:test_support", @@ -137,3 +168,27 @@ static_library("test_support") { # "//third_party/cacheinvalidation/src/google/cacheinvalidation:cacheinvalidation_proto_cpp", ] } + +if (is_android) { + static_library("java") { + deps = [ + "//base", + "//sync:java", + "//third_party/cacheinvalidation:javalib", + ] + sources = [ + ] + } + static_library("javatests") { + deps = [ + ":java", + "//base:java_test_support", + ] + } + generate_jni("jni_headers") { + sources = [ + "android/java/src/org/chromium/components/invalidation/InvalidationService.java", + ] + jni_package = "components/invalidation" + } +} diff --git a/components/invalidation/DEPS b/components/invalidation/DEPS index 215635581aa3..6a1570f64292 100644 --- a/components/invalidation/DEPS +++ b/components/invalidation/DEPS @@ -9,6 +9,7 @@ include_rules = [ "+google/cacheinvalidation", "+google_apis/gaia", "+google_apis/gcm", + "+jni", "+jingle/notifier", "+net/base/backoff_entry.h", "+net/base/mock_host_resolver.h", diff --git a/components/invalidation/android/DEPS b/components/invalidation/android/DEPS new file mode 100644 index 000000000000..05b9658453f1 --- /dev/null +++ b/components/invalidation/android/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+sync", +] diff --git a/components/invalidation/android/component_jni_registrar.cc b/components/invalidation/android/component_jni_registrar.cc new file mode 100644 index 000000000000..67cb5c71798c --- /dev/null +++ b/components/invalidation/android/component_jni_registrar.cc @@ -0,0 +1,30 @@ +// Copyright 2014 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. + +#include "components/invalidation/android/component_jni_registrar.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_registrar.h" +#include "base/basictypes.h" +#include "components/invalidation/invalidation_service_android.h" + +namespace invalidation { + +namespace android { + +static base::android::RegistrationMethod kInvalidationRegisteredMethods[] = { + {"InvalidationService", + invalidation::InvalidationServiceAndroid::RegisterJni}, +}; + +bool RegisterInvalidationJni(JNIEnv* env) { + return base::android::RegisterNativeMethods( + env, + kInvalidationRegisteredMethods, + arraysize(kInvalidationRegisteredMethods)); +} + +} // namespace android + +} // namespace invalidation diff --git a/components/invalidation/android/component_jni_registrar.h b/components/invalidation/android/component_jni_registrar.h new file mode 100644 index 000000000000..7fb44c4826e6 --- /dev/null +++ b/components/invalidation/android/component_jni_registrar.h @@ -0,0 +1,21 @@ +// Copyright 2014 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. + +#ifndef COMPONENTS_INVALIDATION_ANDROID_COMPONENT_JNI_REGISTRAR_H_ +#define COMPONENTS_INVALIDATION_ANDROID_COMPONENT_JNI_REGISTRAR_H_ + +#include + +namespace invalidation { + +namespace android { + +// Register all JNI bindings necessary for the invalidation component. +bool RegisterInvalidationJni(JNIEnv* env); + +} // namespace android + +} // namespace invalidation + +#endif // COMPONENTS_INVALIDATION_ANDROID_COMPONENT_JNI_REGISTRAR_H_ diff --git a/sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java b/components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java similarity index 97% rename from sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java rename to components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java index 6986f5f482bb..27d2894a252b 100644 --- a/sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java +++ b/components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java @@ -2,7 +2,7 @@ // 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; +package org.chromium.components.invalidation; import android.accounts.Account; import android.app.PendingIntent; @@ -22,14 +22,17 @@ import org.chromium.base.CollectionUtil; import org.chromium.base.VisibleForTesting; import org.chromium.sync.internal_api.pub.base.ModelType; +import org.chromium.sync.notifier.InvalidationClientNameProvider; +import org.chromium.sync.notifier.InvalidationIntentProtocol; +import org.chromium.sync.notifier.InvalidationPreferences; import org.chromium.sync.notifier.InvalidationPreferences.EditContext; +import org.chromium.sync.notifier.SyncStatusHelper; import org.chromium.sync.signin.AccountManagerHelper; import org.chromium.sync.signin.ChromeSigninController; import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Random; import java.util.Set; import javax.annotation.Nullable; @@ -50,16 +53,14 @@ * * @author dsmyers@google.com */ -public class InvalidationService extends AndroidListener { +public class InvalidationClientService extends AndroidListener { /* This class must be public because it is exposed as a service. */ /** Notification client typecode. */ @VisibleForTesting static final int CLIENT_TYPE = ClientType.CHROME_SYNC_ANDROID; - private static final String TAG = "InvalidationService"; - - private static final Random RANDOM = new Random(); + private static final String TAG = "InvalidationClientService"; /** * Whether the underlying notification client has been started. This boolean is updated when a @@ -207,7 +208,7 @@ account, invalidAuthToken, getOAuth2ScopeWithType(), @Override public void tokenAvailable(String token) { if (token != null) { - setAuthToken(InvalidationService.this.getApplicationContext(), + setAuthToken(InvalidationClientService.this.getApplicationContext(), pendingIntent, token, getOAuth2ScopeWithType()); } } diff --git a/components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationService.java b/components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationService.java new file mode 100644 index 000000000000..e8bf675789d7 --- /dev/null +++ b/components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationService.java @@ -0,0 +1,91 @@ +// Copyright 2014 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.invalidation; + +import android.accounts.Account; +import android.content.Context; +import android.content.Intent; + +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; +import org.chromium.base.ThreadUtils; +import org.chromium.base.VisibleForTesting; +import org.chromium.sync.notifier.InvalidationClientNameProvider; +import org.chromium.sync.notifier.InvalidationIntentProtocol; +import org.chromium.sync.notifier.InvalidationPreferences; + +/** + * Wrapper for invalidations::InvalidationServiceAndroid. + * + * Serves as the bridge between Java and C++ for the invalidations component. + */ +@JNINamespace("invalidation") +public class InvalidationService { + private final Context mContext; + + private final long mNativeInvalidationServiceAndroid; + + private InvalidationService(Context context, long nativeInvalidationServiceAndroid) { + mContext = context.getApplicationContext(); + if (mContext == null) { + throw new NullPointerException("mContext is null."); + } + mNativeInvalidationServiceAndroid = nativeInvalidationServiceAndroid; + } + + public void requestSyncFromNativeChrome( + int objectSource, String objectId, long version, String payload) { + ThreadUtils.assertOnUiThread(); + nativeRequestSync( + mNativeInvalidationServiceAndroid, objectSource, objectId, version, payload); + } + + public void requestSyncFromNativeChromeForAllTypes() { + ThreadUtils.assertOnUiThread(); + nativeRequestSyncForAllTypes(mNativeInvalidationServiceAndroid); + } + + @CalledByNative + private static InvalidationService create( + Context context, long nativeInvalidationServiceAndroid) { + ThreadUtils.assertOnUiThread(); + return new InvalidationService(context, nativeInvalidationServiceAndroid); + } + + /** + * Sets object ids for which the client should register for notification. This is intended for + * registering non-Sync types; Sync types are registered with {@code setRegisteredTypes}. + * + * @param objectSources The sources of the objects. + * @param objectNames The names of the objects. + */ + @VisibleForTesting + @CalledByNative + public void setRegisteredObjectIds(int[] objectSources, String[] objectNames) { + InvalidationPreferences invalidationPreferences = new InvalidationPreferences(mContext); + Account account = invalidationPreferences.getSavedSyncedAccount(); + Intent registerIntent = + InvalidationIntentProtocol.createRegisterIntent( + account, objectSources, objectNames); + registerIntent.setClass(mContext, InvalidationClientService.class); + mContext.startService(registerIntent); + } + + /** + * Fetches the Invalidator client name. + * + * Note that there is a naming discrepancy here. In C++, we refer to the invalidation client + * identifier that is unique for every invalidation client instance in an account as the client + * ID. In Java, we call it the client name. + */ + @CalledByNative + private byte[] getInvalidatorClientId() { + return InvalidationClientNameProvider.get().getInvalidatorClientName(); + } + + private native void nativeRequestSync(long nativeInvalidationServiceAndroid, + int objectSource, String objectId, long version, String payload); + private native void nativeRequestSyncForAllTypes(long nativeInvalidationServiceAndroid); +} diff --git a/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java b/components/invalidation/android/javatests/src/org/chromium/components/invalidation/InvalidationClientServiceTest.java similarity index 93% rename from sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java rename to components/invalidation/android/javatests/src/org/chromium/components/invalidation/InvalidationClientServiceTest.java index 258c7b65c32b..ffbdc151bed7 100644 --- a/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java +++ b/components/invalidation/android/javatests/src/org/chromium/components/invalidation/InvalidationClientServiceTest.java @@ -2,7 +2,7 @@ // 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; +package org.chromium.components.invalidation; import android.accounts.Account; import android.content.ComponentName; @@ -21,6 +21,8 @@ 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.InvalidationIntentProtocol; +import org.chromium.sync.notifier.InvalidationPreferences; import org.chromium.sync.notifier.InvalidationPreferences.EditContext; import org.chromium.sync.signin.AccountManagerHelper; @@ -32,19 +34,20 @@ import java.util.Set; /** - * Tests for the {@link InvalidationService}. + * Tests for the {@link InvalidationClientService}. * * @author dsmyers@google.com (Daniel Myers) */ -public class InvalidationServiceTest extends ServiceTestCase { +public class InvalidationClientServiceTest extends + ServiceTestCase { /** Id used when creating clients. */ private static final byte[] CLIENT_ID = new byte[]{0, 4, 7}; /** Intents provided to {@link #startService}. */ private List mStartServiceIntents; - public InvalidationServiceTest() { - super(TestableInvalidationService.class); + public InvalidationClientServiceTest() { + super(TestableInvalidationClientService.class); } @Override @@ -55,7 +58,7 @@ public void setUp() throws Exception { @Override public ComponentName startService(Intent intent) { mStartServiceIntents.add(intent); - return new ComponentName(this, InvalidationServiceTest.class); + return new ComponentName(this, InvalidationClientServiceTest.class); } }); setupService(); @@ -63,11 +66,11 @@ public ComponentName startService(Intent intent) { @Override public void tearDown() throws Exception { - if (InvalidationService.getIsClientStartedForTest()) { + if (InvalidationClientService.getIsClientStartedForTest()) { Intent stopIntent = createStopIntent(); getService().onHandleIntent(stopIntent); } - assertFalse(InvalidationService.getIsClientStartedForTest()); + assertFalse(InvalidationClientService.getIsClientStartedForTest()); super.tearDown(); } @@ -82,7 +85,7 @@ public void testComputeRegistrationOps() { Set unregAccumulator = new HashSet(); // Empty existing and desired registrations should yield empty operation sets. - InvalidationService.computeRegistrationOps( + InvalidationClientService.computeRegistrationOps( ModelType.modelTypesToObjectIds( CollectionUtil.newHashSet(ModelType.BOOKMARK, ModelType.SESSION)), ModelType.modelTypesToObjectIds( @@ -92,7 +95,7 @@ public void testComputeRegistrationOps() { assertEquals(0, unregAccumulator.size()); // Equal existing and desired registrations should yield empty operation sets. - InvalidationService.computeRegistrationOps(new HashSet(), + InvalidationClientService.computeRegistrationOps(new HashSet(), new HashSet(), regAccumulator, unregAccumulator); assertEquals(0, regAccumulator.size()); assertEquals(0, unregAccumulator.size()); @@ -102,7 +105,7 @@ public void testComputeRegistrationOps() { Set desiredTypes = CollectionUtil.newHashSet( ModelType.BOOKMARK.toObjectId(), ModelType.SESSION.toObjectId()); - InvalidationService.computeRegistrationOps( + InvalidationClientService.computeRegistrationOps( new HashSet(), desiredTypes, regAccumulator, unregAccumulator); @@ -115,7 +118,7 @@ public void testComputeRegistrationOps() { // Unequal existing and desired registrations should yield both registrations and // unregistrations. We should unregister TYPED_URL and register BOOKMARK, keeping SESSION. - InvalidationService.computeRegistrationOps( + InvalidationClientService.computeRegistrationOps( CollectionUtil.newHashSet( ModelType.SESSION.toObjectId(), ModelType.TYPED_URL.toObjectId()), CollectionUtil.newHashSet( @@ -146,10 +149,10 @@ public void testReady() { // Issue ready. getService().ready(CLIENT_ID); - assertTrue(Arrays.equals(CLIENT_ID, InvalidationService.getClientIdForTest())); + assertTrue(Arrays.equals(CLIENT_ID, InvalidationClientService.getClientIdForTest())); byte[] otherCid = "otherCid".getBytes(); getService().ready(otherCid); - assertTrue(Arrays.equals(otherCid, InvalidationService.getClientIdForTest())); + assertTrue(Arrays.equals(otherCid, InvalidationClientService.getClientIdForTest())); // Verify registrations issued. assertEquals(CollectionUtil.newHashSet( @@ -466,11 +469,11 @@ public void testStartAndStopClient() { Intent startIntent = createStartIntent(); getService().onHandleIntent(startIntent); - assertTrue(InvalidationService.getIsClientStartedForTest()); + assertTrue(InvalidationClientService.getIsClientStartedForTest()); Intent stopIntent = createStopIntent(); getService().onHandleIntent(stopIntent); - assertFalse(InvalidationService.getIsClientStartedForTest()); + assertFalse(InvalidationClientService.getIsClientStartedForTest()); // The issued intents should have been an AndroidListener start intent followed by an // AndroidListener stop intent. @@ -492,14 +495,14 @@ public void testClientStopsWhenShouldNotBeRunning() { // Start the service. Intent startIntent = createStartIntent(); getService().onHandleIntent(startIntent); - assertTrue(InvalidationService.getIsClientStartedForTest()); + assertTrue(InvalidationClientService.getIsClientStartedForTest()); // Change configuration. getService().setShouldRunStates(false, false); // Send an Intent and verify that the service stops. getService().onHandleIntent(startIntent); - assertFalse(InvalidationService.getIsClientStartedForTest()); + assertFalse(InvalidationClientService.getIsClientStartedForTest()); // The issued intents should have been an AndroidListener start intent followed by an // AndroidListener stop intent. @@ -526,7 +529,7 @@ public void testRegistrationIntent() { getService().onHandleIntent(registrationIntent); // Verify client started and state written. - assertTrue(InvalidationService.getIsClientStartedForTest()); + assertTrue(InvalidationClientService.getIsClientStartedForTest()); InvalidationPreferences invPrefs = new InvalidationPreferences(getContext()); assertEquals(account, invPrefs.getSavedSyncedAccount()); assertEquals(ModelType.modelTypesToSyncTypesForTest(desiredRegistrations), @@ -677,7 +680,7 @@ public void testRegistrationIntentNoProxyTabsUsingReady() { getService().onHandleIntent(registrationIntent); // Verify client started and state written. - assertTrue(InvalidationService.getIsClientStartedForTest()); + assertTrue(InvalidationClientService.getIsClientStartedForTest()); InvalidationPreferences invPrefs = new InvalidationPreferences(getContext()); assertEquals(account, invPrefs.getSavedSyncedAccount()); assertEquals(CollectionUtil.newHashSet(ModelType.ALL_TYPES_TYPE), @@ -687,7 +690,7 @@ public void testRegistrationIntentNoProxyTabsUsingReady() { // Set client to be ready. This triggers registrations. getService().ready(CLIENT_ID); - assertTrue(Arrays.equals(CLIENT_ID, InvalidationService.getClientIdForTest())); + assertTrue(Arrays.equals(CLIENT_ID, InvalidationClientService.getClientIdForTest())); // Ensure registrations are correct. Set expectedTypes = @@ -707,7 +710,7 @@ public void testRegistrationIntentNoProxyTabsAlreadyWithClientId() { getService().onHandleIntent(registrationIntent); // Verify client started and state written. - assertTrue(InvalidationService.getIsClientStartedForTest()); + assertTrue(InvalidationClientService.getIsClientStartedForTest()); InvalidationPreferences invPrefs = new InvalidationPreferences(getContext()); assertEquals(account, invPrefs.getSavedSyncedAccount()); assertEquals(new HashSet(), invPrefs.getSavedSyncedTypes()); @@ -716,7 +719,7 @@ public void testRegistrationIntentNoProxyTabsAlreadyWithClientId() { // Make sure client is ready. getService().ready(CLIENT_ID); - assertTrue(Arrays.equals(CLIENT_ID, InvalidationService.getClientIdForTest())); + assertTrue(Arrays.equals(CLIENT_ID, InvalidationClientService.getClientIdForTest())); // Choose to register for all types in an already ready client. registrationIntent = createRegisterIntent(account, true, null); @@ -746,7 +749,7 @@ public void testRegistrationIntentWhenClientShouldNotBeRunning() { getService().onHandleIntent(registrationIntent); // Verify state written but client not started. - assertFalse(InvalidationService.getIsClientStartedForTest()); + assertFalse(InvalidationClientService.getIsClientStartedForTest()); InvalidationPreferences invPrefs = new InvalidationPreferences(getContext()); assertEquals(account, invPrefs.getSavedSyncedAccount()); assertEquals(ModelType.modelTypesToSyncTypesForTest(desiredRegistrations), @@ -773,7 +776,7 @@ public void testDeferredRegistrationsIssued() { Intent registrationIntent = createRegisterIntent(account, false, desiredRegistrations); getService().onHandleIntent(registrationIntent); - assertTrue(InvalidationService.getIsClientStartedForTest()); + assertTrue(InvalidationClientService.getIsClientStartedForTest()); assertEquals(1, mStartServiceIntents.size()); assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0))); InvalidationPreferences invPrefs = new InvalidationPreferences(getContext()); @@ -802,34 +805,34 @@ public void testDeferredRegistrationsIssued() { public void testRegistrationRetries() { /* * Test plan: validate that the alarm receiver used by the AndroidListener underlying - * InvalidationService is correctly configured in the manifest and retries registrations - * with exponential backoff. May need to be implemented as a downstream Chrome for Android - * test. + * InvalidationClientService is correctly configured in the manifest and retries + * registrations with exponential backoff. May need to be implemented as a downstream + * Chrome for Android test. */ // TODO(dsmyers): implement. // Bug: https://code.google.com/p/chromium/issues/detail?id=172398 } - /** Creates an intent to start the InvalidationService. */ + /** Creates an intent to start the InvalidationClientService. */ private Intent createStartIntent() { Intent intent = new Intent(); return intent; } - /** Creates an intent to stop the InvalidationService. */ + /** Creates an intent to stop the InvalidationClientService. */ private Intent createStopIntent() { Intent intent = new Intent(); intent.putExtra(InvalidationIntentProtocol.EXTRA_STOP, true); return intent; } - /** Creates an intent to register some types with the InvalidationService. */ + /** Creates an intent to register some types with the InvalidationClientService. */ private Intent createRegisterIntent(Account account, boolean allTypes, Set types) { Intent intent = InvalidationIntentProtocol.createRegisterIntent(account, allTypes, types); return intent; } - /** Creates an intent to register some types with the InvalidationService. */ + /** Creates an intent to register some types with the InvalidationClientService. */ private Intent createRegisterIntent( Account account, int[] objectSources, String[] objectNames) { Intent intent = InvalidationIntentProtocol.createRegisterIntent( @@ -840,7 +843,7 @@ private Intent createRegisterIntent( /** Returns whether {@code intent} is an {@link AndroidListener} start intent. */ private boolean isAndroidListenerStartIntent(Intent intent) { Intent startIntent = AndroidListener.createStartIntent(getContext(), - InvalidationService.CLIENT_TYPE, "unused".getBytes()); + InvalidationClientService.CLIENT_TYPE, "unused".getBytes()); return intent.getExtras().keySet().equals(startIntent.getExtras().keySet()); } diff --git a/sync/android/javatests/src/org/chromium/sync/notifier/TestableInvalidationService.java b/components/invalidation/android/javatests/src/org/chromium/components/invalidation/TestableInvalidationClientService.java similarity index 93% rename from sync/android/javatests/src/org/chromium/sync/notifier/TestableInvalidationService.java rename to components/invalidation/android/javatests/src/org/chromium/components/invalidation/TestableInvalidationClientService.java index dd4a93204496..d52390a5d875 100644 --- a/sync/android/javatests/src/org/chromium/sync/notifier/TestableInvalidationService.java +++ b/components/invalidation/android/javatests/src/org/chromium/components/invalidation/TestableInvalidationClientService.java @@ -2,7 +2,7 @@ // 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; +package org.chromium.components.invalidation; import android.accounts.Account; import android.content.ComponentName; @@ -19,12 +19,12 @@ import java.util.Set; /** - * Subclass of {@link InvalidationService} that captures events and allows controlling + * Subclass of {@link InvalidationClientService} that captures events and allows controlling * whether or not Chrome is in the foreground and sync is enabled. * * @author dsmyers@google.com (Daniel Myers) */ -public class TestableInvalidationService extends InvalidationService { +public class TestableInvalidationClientService extends InvalidationClientService { /** Object ids given to {@link #register}, one list element per call. */ final List> mRegistrations = new ArrayList>(); @@ -51,9 +51,6 @@ public class TestableInvalidationService extends InvalidationService { /** Whether sync is enabled. */ private boolean mIsSyncEnabled = false; - public TestableInvalidationService() { - } - @Override public void acknowledge(byte[] ackHandle) { mAcknowledgements.add(ackHandle); diff --git a/components/invalidation/invalidation_service_android.cc b/components/invalidation/invalidation_service_android.cc new file mode 100644 index 000000000000..cccad4015fbb --- /dev/null +++ b/components/invalidation/invalidation_service_android.cc @@ -0,0 +1,176 @@ +// Copyright 2014 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. + +#include "components/invalidation/invalidation_service_android.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/callback.h" +#include "components/invalidation/object_id_invalidation_map.h" +#include "google/cacheinvalidation/types.pb.h" +#include "jni/InvalidationService_jni.h" + +using base::android::ConvertJavaStringToUTF8; +using base::android::ConvertUTF8ToJavaString; + +namespace invalidation { + +InvalidationServiceAndroid::InvalidationServiceAndroid(jobject context) + : invalidator_state_(syncer::INVALIDATIONS_ENABLED), + logger_() { + DCHECK(CalledOnValidThread()); + JNIEnv* env = base::android::AttachCurrentThread(); + base::android::ScopedJavaLocalRef local_java_ref = + Java_InvalidationService_create(env, + context, + reinterpret_cast(this)); + java_ref_.Reset(env, local_java_ref.obj()); +} + +InvalidationServiceAndroid::~InvalidationServiceAndroid() { } + +void InvalidationServiceAndroid::RegisterInvalidationHandler( + syncer::InvalidationHandler* handler) { + DCHECK(CalledOnValidThread()); + invalidator_registrar_.RegisterHandler(handler); + logger_.OnRegistration(handler->GetOwnerName()); +} + +void InvalidationServiceAndroid::UpdateRegisteredInvalidationIds( + syncer::InvalidationHandler* handler, + const syncer::ObjectIdSet& ids) { + DCHECK(CalledOnValidThread()); + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + invalidator_registrar_.UpdateRegisteredIds(handler, ids); + const syncer::ObjectIdSet& registered_ids = + invalidator_registrar_.GetAllRegisteredIds(); + + // To call the corresponding method on the Java invalidation service, split + // the object ids into object source and object name arrays. + std::vector sources; + std::vector names; + syncer::ObjectIdSet::const_iterator id; + for (id = registered_ids.begin(); id != registered_ids.end(); ++id) { + sources.push_back(id->source()); + names.push_back(id->name()); + } + + Java_InvalidationService_setRegisteredObjectIds( + env, + java_ref_.obj(), + base::android::ToJavaIntArray(env, sources).obj(), + base::android::ToJavaArrayOfStrings(env, names).obj()); + + logger_.OnUpdateIds(invalidator_registrar_.GetSanitizedHandlersIdsMap()); +} + +void InvalidationServiceAndroid::UnregisterInvalidationHandler( + syncer::InvalidationHandler* handler) { + DCHECK(CalledOnValidThread()); + invalidator_registrar_.UnregisterHandler(handler); + logger_.OnUnregistration(handler->GetOwnerName()); +} + +syncer::InvalidatorState +InvalidationServiceAndroid::GetInvalidatorState() const { + DCHECK(CalledOnValidThread()); + return invalidator_state_; +} + +std::string InvalidationServiceAndroid::GetInvalidatorClientId() const { + DCHECK(CalledOnValidThread()); + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + // Ask the Java code to for the invalidator ID it's currently using. + base::android::ScopedJavaLocalRef<_jbyteArray*> id_bytes_java = + Java_InvalidationService_getInvalidatorClientId(env, java_ref_.obj()); + + // Convert it into a more convenient format for C++. + std::vector id_bytes; + base::android::JavaByteArrayToByteVector(env, id_bytes_java.obj(), &id_bytes); + std::string id(id_bytes.begin(), id_bytes.end()); + + return id; +} + +InvalidationLogger* InvalidationServiceAndroid::GetInvalidationLogger() { + return &logger_; +} + +void InvalidationServiceAndroid::RequestDetailedStatus( + base::Callback return_callback) const { +} + +IdentityProvider* InvalidationServiceAndroid::GetIdentityProvider() { + return NULL; +} + +void InvalidationServiceAndroid::TriggerStateChangeForTest( + syncer::InvalidatorState state) { + DCHECK(CalledOnValidThread()); + invalidator_state_ = state; + invalidator_registrar_.UpdateInvalidatorState(invalidator_state_); +} + +void InvalidationServiceAndroid::RequestSync(JNIEnv* env, + jobject obj, + jint object_source, + jstring java_object_id, + jlong version, + jstring java_state) { + invalidation::ObjectId object_id(object_source, + ConvertJavaStringToUTF8(env, java_object_id)); + + syncer::ObjectIdInvalidationMap object_ids_with_states; + + if (version == ipc::invalidation::Constants::UNKNOWN) { + object_ids_with_states.Insert( + syncer::Invalidation::InitUnknownVersion(object_id)); + } else { + ObjectIdVersionMap::iterator it = + max_invalidation_versions_.find(object_id); + if ((it != max_invalidation_versions_.end()) && + (version <= it->second)) { + DVLOG(1) << "Dropping redundant invalidation with version " << version; + return; + } + max_invalidation_versions_[object_id] = version; + object_ids_with_states.Insert( + syncer::Invalidation::Init(object_id, version, + ConvertJavaStringToUTF8(env, java_state))); + } + + DispatchInvalidations(object_ids_with_states); +} + +void InvalidationServiceAndroid::RequestSyncForAllTypes(JNIEnv* env, + jobject obj) { + syncer::ObjectIdInvalidationMap object_ids_with_states; + DispatchInvalidations(object_ids_with_states); +} + +void InvalidationServiceAndroid::DispatchInvalidations( + syncer::ObjectIdInvalidationMap& object_invalidation_map) { + // An empty map implies that we should invalidate all. + const syncer::ObjectIdInvalidationMap& effective_invalidation_map = + object_invalidation_map.Empty() ? + syncer::ObjectIdInvalidationMap::InvalidateAll( + invalidator_registrar_.GetAllRegisteredIds()) : + object_invalidation_map; + + invalidator_registrar_.DispatchInvalidationsToHandlers( + effective_invalidation_map); + logger_.OnInvalidation(effective_invalidation_map); +} + +// static +bool InvalidationServiceAndroid::RegisterJni(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace invalidation diff --git a/chrome/browser/invalidation/invalidation_service_android.h b/components/invalidation/invalidation_service_android.h similarity index 62% rename from chrome/browser/invalidation/invalidation_service_android.h rename to components/invalidation/invalidation_service_android.h index 63af3fc3d0c3..6790db3b9091 100644 --- a/chrome/browser/invalidation/invalidation_service_android.h +++ b/components/invalidation/invalidation_service_android.h @@ -2,9 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_ANDROID_H_ -#define CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_ANDROID_H_ +#ifndef COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_ANDROID_H_ +#define COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_ANDROID_H_ +#include +#include + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" @@ -13,28 +18,18 @@ #include "components/invalidation/invalidation_service.h" #include "components/invalidation/invalidator_registrar.h" #include "components/keyed_service/core/keyed_service.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" - -class Profile; namespace invalidation { -class InvalidationControllerAndroid; + class InvalidationLogger; // This InvalidationService is used to deliver invalidations on Android. The // Android operating system has its own mechanisms for delivering invalidations. -// This class uses the NotificationService to communicate with a thin wrapper -// around Android's invalidations service. class InvalidationServiceAndroid : public base::NonThreadSafe, - public InvalidationService, - public content::NotificationObserver { + public InvalidationService { public: - // Takes ownership of |invalidation_controller|. - InvalidationServiceAndroid( - Profile* profile, - InvalidationControllerAndroid* invalidation_controller); + InvalidationServiceAndroid(jobject context); virtual ~InvalidationServiceAndroid(); // InvalidationService implementation. @@ -57,28 +52,51 @@ class InvalidationServiceAndroid OVERRIDE; virtual IdentityProvider* GetIdentityProvider() OVERRIDE; - // content::NotificationObserver implementation. - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; + void RequestSync(JNIEnv* env, + jobject obj, + jint object_source, + jstring object_id, + jlong version, + jstring state); + + void RequestSyncForAllTypes(JNIEnv* env, jobject obj); // The InvalidationServiceAndroid always reports that it is enabled. // This is used only by unit tests. void TriggerStateChangeForTest(syncer::InvalidatorState state); + static bool RegisterJni(JNIEnv* env); + private: + typedef std::map ObjectIdVersionMap; + + // Friend class so that InvalidationServiceFactoryAndroid has access to + // private member object java_ref_. + friend class InvalidationServiceFactoryAndroid; + + // Points to a Java instance of InvalidationService. + base::android::ScopedJavaGlobalRef java_ref_; + syncer::InvalidatorRegistrar invalidator_registrar_; - content::NotificationRegistrar registrar_; syncer::InvalidatorState invalidator_state_; - scoped_ptr invalidation_controller_; + + // The invalidation API spec allows for the possibility of redundant + // invalidations, so keep track of the max versions and drop + // invalidations with old versions. + ObjectIdVersionMap max_invalidation_versions_; // The invalidation logger object we use to record state changes // and invalidations. InvalidationLogger logger_; + void DispatchInvalidations( + syncer::ObjectIdInvalidationMap& object_invalidation_map); + DISALLOW_COPY_AND_ASSIGN(InvalidationServiceAndroid); }; } // namespace invalidation -#endif // CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_ANDROID_H_ +#endif // COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_ANDROID_H_ diff --git a/components/invalidation/invalidation_service_android_unittest.cc b/components/invalidation/invalidation_service_android_unittest.cc new file mode 100644 index 000000000000..a03a97320a5d --- /dev/null +++ b/components/invalidation/invalidation_service_android_unittest.cc @@ -0,0 +1,41 @@ +// 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. + +#include "components/invalidation/invalidation_service_android.h" + +#include "base/android/jni_android.h" +#include "components/invalidation/fake_invalidation_handler.h" +#include "components/invalidation/invalidation_service_test_template.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace invalidation { + +#if defined(OS_ANDROID) + +class InvalidationServiceAndroidTest : public testing::Test { + public: + InvalidationServiceAndroidTest() : + invalidation_service_(base::android::GetApplicationContext()) {} + virtual ~InvalidationServiceAndroidTest() {} + + InvalidationService& invalidation_service() { + return invalidation_service_; + } + + private: + InvalidationServiceAndroid invalidation_service_; +}; + +TEST_F(InvalidationServiceAndroidTest, FetchClientId) { + const std::string id1 = invalidation_service().GetInvalidatorClientId(); + ASSERT_FALSE(id1.empty()); + + // If nothing else, the ID should be consistent. + const std::string id2 = invalidation_service().GetInvalidatorClientId(); + ASSERT_EQ(id1, id2); +} + +#endif + +} // namespace invalidation diff --git a/components/signin.gypi b/components/signin.gypi index 5f9993ef9a85..de11b647ab70 100644 --- a/components/signin.gypi +++ b/components/signin.gypi @@ -26,6 +26,8 @@ 'type': 'static_library', 'dependencies': [ '../base/base.gyp:base', + '../base/base.gyp:base_i18n', + '../base/base.gyp:base_prefs', '../crypto/crypto.gyp:crypto', '../google_apis/google_apis.gyp:google_apis', '../net/net.gyp:net', diff --git a/components/test/DEPS b/components/test/DEPS index 57345fcf2660..ad35ec873653 100644 --- a/components/test/DEPS +++ b/components/test/DEPS @@ -1,6 +1,7 @@ include_rules = [ # To initialize the global data of content_settings. "+components/content_settings/core/common", + "+components/invalidation/android/component_jni_registrar.h", "+content/public/test", "+ui/base/android/ui_base_jni_registrar.h", "+ui/base/resource/resource_bundle.h", diff --git a/components/test/run_all_unittests.cc b/components/test/run_all_unittests.cc index 9664cce93c27..b31397b34efb 100644 --- a/components/test/run_all_unittests.cc +++ b/components/test/run_all_unittests.cc @@ -25,6 +25,7 @@ #if defined(OS_ANDROID) #include "base/android/jni_android.h" +#include "components/invalidation/android/component_jni_registrar.h" #include "ui/base/android/ui_base_jni_registrar.h" #include "ui/gfx/android/gfx_jni_registrar.h" #endif @@ -52,6 +53,7 @@ class ComponentsTestSuite : public base::TestSuite { JNIEnv* env = base::android::AttachCurrentThread(); gfx::android::RegisterJni(env); ui::android::RegisterJni(env); + invalidation::android::RegisterInvalidationJni(env); #endif #if defined(OS_MACOSX) && !defined(OS_IOS)