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)