Implement InstanceIDAndroid using InstanceIDWithSubtype.java
Replaces the previous stub implementation with a fully functional
implementation backed by InstanceIDWithSubtype.java.
Part of a series of patches:
1. https://codereview.chromium.org/1832833002 adds InstanceIDWithSubtype
2. this patch
3. https://codereview.chromium.org/1829023002 adds fake and test
4. https://codereview.chromium.org/1854093002 enables InstanceID by default
5. https://codereview.chromium.org/1851423003 switches Push to InstanceIDs
BUG=589461
Review URL: https://codereview.chromium.org/1830983002
Cr-Commit-Position: refs/heads/master@{#387646}
diff --git a/components/gcm_driver.gypi b/components/gcm_driver.gypi
index 6590f8b..042397f 100644
--- a/components/gcm_driver.gypi
+++ b/components/gcm_driver.gypi
@@ -175,6 +175,8 @@
],
'sources': [
# Note: file list duplicated in GN build.
+ 'gcm_driver/instance_id/android/component_jni_registrar.cc',
+ 'gcm_driver/instance_id/android/component_jni_registrar.h',
'gcm_driver/instance_id/instance_id.cc',
'gcm_driver/instance_id/instance_id.h',
'gcm_driver/instance_id/instance_id_android.cc',
@@ -186,6 +188,9 @@
],
'conditions': [
['OS == "android"', {
+ 'dependencies': [
+ 'instance_id_driver_jni_headers',
+ ],
'sources!': [
'gcm_driver/instance_id/instance_id_impl.cc',
'gcm_driver/instance_id/instance_id_impl.h',
@@ -300,8 +305,7 @@
'target_name': 'gcm_driver_java',
'type': 'none',
'dependencies': [
- '../base/base.gyp:base',
- # TODO(johnme): Fix the layering violation of depending on content/
+ '../base/base.gyp:base_java',
'../content/content.gyp:content_java',
'../sync/sync.gyp:sync_java',
],
@@ -322,6 +326,31 @@
},
'includes': [ '../build/jni_generator.gypi' ],
},
+ {
+ # GN version: //components/gcm_driver/instance_id/android:instance_id_driver_java
+ 'target_name': 'instance_id_driver_java',
+ 'type': 'none',
+ 'dependencies': [
+ '../base/base.gyp:base_java',
+ '../third_party/android_tools/android_tools.gyp:google_play_services_javalib',
+ ],
+ 'variables': {
+ 'java_in_dir': 'gcm_driver/instance_id/android/java',
+ },
+ 'includes': [ '../build/java.gypi' ],
+ },
+ {
+ # GN version: //components/gcm_driver/instance_id/android:jni_headers
+ 'target_name': 'instance_id_driver_jni_headers',
+ 'type': 'none',
+ 'sources': [
+ 'gcm_driver/instance_id/android/java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java',
+ ],
+ 'variables': {
+ 'jni_gen_package': 'components/gcm_driver/instance_id',
+ },
+ 'includes': [ '../build/jni_generator.gypi' ],
+ },
],
},
],
diff --git a/components/gcm_driver/android/BUILD.gn b/components/gcm_driver/android/BUILD.gn
index af75f01f..3f674c61 100644
--- a/components/gcm_driver/android/BUILD.gn
+++ b/components/gcm_driver/android/BUILD.gn
@@ -17,9 +17,7 @@
deps = [
"//base:base_java",
"//content/public/android:content_java",
- "//sync/android:sync_java",
"//third_party/android_tools:android_gcm_java",
- "//third_party/cacheinvalidation:cacheinvalidation_javalib",
"//third_party/jsr-305:jsr_305_javalib",
]
diff --git a/components/gcm_driver/android/component_jni_registrar.cc b/components/gcm_driver/android/component_jni_registrar.cc
index 0ef0601..025820c 100644
--- a/components/gcm_driver/android/component_jni_registrar.cc
+++ b/components/gcm_driver/android/component_jni_registrar.cc
@@ -14,7 +14,7 @@
namespace android {
static base::android::RegistrationMethod kGCMDriverRegisteredMethods[] = {
- {"GCMDriver", gcm::GCMDriverAndroid::RegisterBindings},
+ {"GCMDriver", gcm::GCMDriverAndroid::RegisterJni},
};
bool RegisterGCMDriverJni(JNIEnv* env) {
diff --git a/components/gcm_driver/gcm_driver_android.cc b/components/gcm_driver/gcm_driver_android.cc
index 21bcfa0..40e204d 100644
--- a/components/gcm_driver/gcm_driver_android.cc
+++ b/components/gcm_driver/gcm_driver_android.cc
@@ -111,7 +111,7 @@
}
// static
-bool GCMDriverAndroid::RegisterBindings(JNIEnv* env) {
+bool GCMDriverAndroid::RegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}
diff --git a/components/gcm_driver/gcm_driver_android.h b/components/gcm_driver/gcm_driver_android.h
index 5944b85..ab5c9f3 100644
--- a/components/gcm_driver/gcm_driver_android.h
+++ b/components/gcm_driver/gcm_driver_android.h
@@ -51,7 +51,7 @@
const base::android::JavaParamRef<jobjectArray>& data_keys_and_values);
// Register JNI methods.
- static bool RegisterBindings(JNIEnv* env);
+ static bool RegisterJni(JNIEnv* env);
// GCMDriver implementation:
void OnSignedIn() override;
diff --git a/components/gcm_driver/instance_id/BUILD.gn b/components/gcm_driver/instance_id/BUILD.gn
index 3e77929..ec00c0b 100644
--- a/components/gcm_driver/instance_id/BUILD.gn
+++ b/components/gcm_driver/instance_id/BUILD.gn
@@ -5,6 +5,8 @@
# GYP version: components/gcm_driver.gypi:instance_id_driver
source_set("instance_id") {
sources = [
+ "android/component_jni_registrar.cc",
+ "android/component_jni_registrar.h",
"instance_id.cc",
"instance_id.h",
"instance_id_driver.cc",
@@ -29,6 +31,7 @@
"instance_id_android.cc",
"instance_id_android.h",
]
+ deps += [ "android:jni_headers" ]
}
}
diff --git a/components/gcm_driver/instance_id/android/BUILD.gn b/components/gcm_driver/instance_id/android/BUILD.gn
new file mode 100644
index 0000000..6168aff
--- /dev/null
+++ b/components/gcm_driver/instance_id/android/BUILD.gn
@@ -0,0 +1,26 @@
+# Copyright 2016 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.
+
+import("//build/config/android/rules.gni")
+
+# GYP version: components/gcm_driver.gypi:instance_id_driver_jni_headers
+generate_jni("jni_headers") {
+ sources = [
+ "java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java",
+ ]
+ jni_package = "components/gcm_driver/instance_id"
+}
+
+# GYP version: components/gcm_driver.gypi:instance_id_driver_java
+android_library("instance_id_driver_java") {
+ deps = [
+ "//base:base_java",
+ google_play_services_library,
+ ]
+
+ java_files = [
+ "java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java",
+ "java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDWithSubtype.java",
+ ]
+}
diff --git a/components/gcm_driver/instance_id/android/component_jni_registrar.cc b/components/gcm_driver/instance_id/android/component_jni_registrar.cc
new file mode 100644
index 0000000..de6705b
--- /dev/null
+++ b/components/gcm_driver/instance_id/android/component_jni_registrar.cc
@@ -0,0 +1,26 @@
+// Copyright 2016 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/gcm_driver/instance_id/android/component_jni_registrar.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_registrar.h"
+#include "base/macros.h"
+#include "components/gcm_driver/instance_id/instance_id_android.h"
+
+namespace instance_id {
+namespace android {
+
+static base::android::RegistrationMethod kInstanceIDRegisteredMethods[] = {
+ {"InstanceID", instance_id::InstanceIDAndroid::RegisterJni},
+};
+
+bool RegisterInstanceIDJni(JNIEnv* env) {
+ return base::android::RegisterNativeMethods(
+ env, kInstanceIDRegisteredMethods,
+ arraysize(kInstanceIDRegisteredMethods));
+}
+
+} // namespace android
+} // namespace instance_id
diff --git a/components/gcm_driver/instance_id/android/component_jni_registrar.h b/components/gcm_driver/instance_id/android/component_jni_registrar.h
new file mode 100644
index 0000000..dc40f9bc
--- /dev/null
+++ b/components/gcm_driver/instance_id/android/component_jni_registrar.h
@@ -0,0 +1,19 @@
+// Copyright 2016 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_GCM_DRIVER_INSTANCE_ID_ANDROID_COMPONENT_JNI_REGISTRAR_H_
+#define COMPONENTS_GCM_DRIVER_INSTANCE_ID_ANDROID_COMPONENT_JNI_REGISTRAR_H_
+
+#include <jni.h>
+
+namespace instance_id {
+namespace android {
+
+// Register all JNI bindings necessary for the gcm_driver/instance_id component.
+bool RegisterInstanceIDJni(JNIEnv* env);
+
+} // namespace android
+} // namespace instance_id
+
+#endif // COMPONENTS_GCM_DRIVER_INSTANCE_ID_ANDROID_COMPONENT_JNI_REGISTRAR_H_
diff --git a/components/gcm_driver/instance_id/android/java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java b/components/gcm_driver/instance_id/android/java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java
new file mode 100644
index 0000000..a984a24
--- /dev/null
+++ b/components/gcm_driver/instance_id/android/java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java
@@ -0,0 +1,146 @@
+// Copyright 2016 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.gcm_driver.instance_id;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+
+import com.google.android.gms.iid.InstanceID;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+
+import java.io.IOException;
+
+/**
+ * Wraps InstanceID and InstanceIDWithSubtype so they can be used over JNI.
+ * Performs disk/network operations on a background thread and replies asynchronously.
+ */
+@JNINamespace("instance_id")
+public class InstanceIDBridge {
+ /** Underlying InstanceID. May be shared by multiple InstanceIDBridges. */
+ private final InstanceID mInstanceID;
+ private long mNativeInstanceIDAndroid;
+
+ private InstanceIDBridge(
+ long nativeInstanceIDAndroid, Context context, String subtype) {
+ mInstanceID = InstanceIDWithSubtype.getInstance(context, subtype);
+ mNativeInstanceIDAndroid = nativeInstanceIDAndroid;
+ }
+
+ /**
+ * Returns a wrapped {@link InstanceIDWithSubtype}. Multiple InstanceIDBridge instances may
+ * share an underlying InstanceIDWithSubtype.
+ */
+ @CalledByNative
+ public static InstanceIDBridge create(
+ long nativeInstanceIDAndroid, Context context, String subtype) {
+ // TODO(johnme): This should also be async.
+ return new InstanceIDBridge(nativeInstanceIDAndroid, context, subtype);
+ }
+
+ /**
+ * Called when our C++ counterpart is destroyed. Clears the handle to our native C++ object,
+ * ensuring it's not called by pending async tasks.
+ */
+ @CalledByNative
+ private void destroy() {
+ mNativeInstanceIDAndroid = 0;
+ }
+
+ /** Wrapper for {@link InstanceID#getId}. */
+ @CalledByNative
+ public String getId() {
+ // TODO(johnme): This should also be async.
+ return mInstanceID.getId();
+ }
+
+ /** Wrapper for {@link InstanceID#getCreationTime}. */
+ @CalledByNative
+ public long getCreationTime() {
+ // TODO(johnme): This should also be async.
+ return mInstanceID.getCreationTime();
+ }
+
+ /** Async wrapper for {@link InstanceID#getToken(String, String, Bundle)}. */
+ @CalledByNative
+ private void getToken(final int requestId, final String authorizedEntity, final String scope,
+ String[] extrasStrings) {
+ final Bundle extras = new Bundle();
+ assert extrasStrings.length % 2 == 0;
+ for (int i = 0; i < extrasStrings.length; i += 2) {
+ extras.putString(extrasStrings[i], extrasStrings[i + 1]);
+ }
+ new AsyncTask<Void, Void, String>() {
+ @Override
+ protected String doInBackground(Void... params) {
+ try {
+ return mInstanceID.getToken(authorizedEntity, scope, extras);
+ } catch (IOException ex) {
+ return "";
+ }
+ }
+ @Override
+ protected void onPostExecute(String token) {
+ if (mNativeInstanceIDAndroid != 0) {
+ nativeDidGetToken(mNativeInstanceIDAndroid, requestId, token);
+ }
+ }
+ }.execute();
+ }
+
+ /** Async wrapper for {@link InstanceID#deleteToken(String, String)}. */
+ @CalledByNative
+ private void deleteToken(
+ final int requestId, final String authorizedEntity, final String scope) {
+ new AsyncTask<Void, Void, Boolean>() {
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ try {
+ mInstanceID.deleteToken(authorizedEntity, scope);
+ return true;
+ } catch (IOException ex) {
+ return false;
+ }
+ }
+ @Override
+ protected void onPostExecute(Boolean success) {
+ if (mNativeInstanceIDAndroid != 0) {
+ nativeDidDeleteToken(mNativeInstanceIDAndroid, requestId, success);
+ }
+ }
+ }.execute();
+ }
+
+ /** Async wrapper for {@link InstanceID#deleteInstanceID}. */
+ @CalledByNative
+ private void deleteInstanceID(final int requestId) {
+ new AsyncTask<Void, Void, Boolean>() {
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ try {
+ mInstanceID.deleteInstanceID();
+ return true;
+ } catch (IOException ex) {
+ return false;
+ }
+ }
+ @Override
+ protected void onPostExecute(Boolean success) {
+ if (mNativeInstanceIDAndroid != 0) {
+ nativeDidDeleteID(mNativeInstanceIDAndroid, requestId, success);
+ }
+ }
+ }.execute();
+ }
+
+ private native void nativeDidGetToken(
+ long nativeInstanceIDAndroid, int requestId, String token);
+ private native void nativeDidDeleteToken(
+ long nativeInstanceIDAndroid, int requestId, boolean success);
+ private native void nativeDidDeleteID(
+ long nativeInstanceIDAndroid, int requestId, boolean success);
+}
\ No newline at end of file
diff --git a/components/gcm_driver/instance_id/instance_id.cc b/components/gcm_driver/instance_id/instance_id.cc
index d89c997e..d48b5ca 100644
--- a/components/gcm_driver/instance_id/instance_id.cc
+++ b/components/gcm_driver/instance_id/instance_id.cc
@@ -6,14 +6,9 @@
namespace instance_id {
-InstanceID::InstanceID(const std::string& app_id,
- gcm::InstanceIDHandler* handler)
- : handler_(handler), app_id_(app_id) {
- DCHECK(handler_);
-}
+InstanceID::InstanceID(const std::string& app_id) : app_id_(app_id) {}
-InstanceID::~InstanceID() {
-}
+InstanceID::~InstanceID() {}
void InstanceID::SetTokenRefreshCallback(const TokenRefreshCallback& callback) {
token_refresh_callback_ = callback;
diff --git a/components/gcm_driver/instance_id/instance_id.h b/components/gcm_driver/instance_id/instance_id.h
index fb69a11..de9bc21 100644
--- a/components/gcm_driver/instance_id/instance_id.h
+++ b/components/gcm_driver/instance_id/instance_id.h
@@ -57,7 +57,7 @@
// Creator.
// |app_id|: identifies the application that uses the Instance ID.
// |handler|: provides the GCM functionality needed to support Instance ID.
- // Must outlive this class.
+ // Must outlive this class. On Android, this can be null instead.
static scoped_ptr<InstanceID> Create(const std::string& app_id,
gcm::InstanceIDHandler* handler);
@@ -106,17 +106,11 @@
std::string app_id() const { return app_id_; }
protected:
- InstanceID(const std::string& app_id, gcm::InstanceIDHandler* handler);
+ InstanceID(const std::string& app_id);
void NotifyTokenRefresh(bool update_id);
- gcm::InstanceIDHandler* handler() const { return handler_; }
-
private:
- // Owned by GCMProfileServiceFactory, which is a dependency of
- // InstanceIDProfileServiceFactory, which owns this.
- gcm::InstanceIDHandler* handler_;
-
std::string app_id_;
TokenRefreshCallback token_refresh_callback_;
diff --git a/components/gcm_driver/instance_id/instance_id_android.cc b/components/gcm_driver/instance_id/instance_id_android.cc
index 9611567..f2fbd21 100644
--- a/components/gcm_driver/instance_id/instance_id_android.cc
+++ b/components/gcm_driver/instance_id/instance_id_android.cc
@@ -4,49 +4,175 @@
#include "components/gcm_driver/instance_id/instance_id_android.h"
+#include <stdint.h>
+
+#include "base/android/context_utils.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "jni/InstanceIDBridge_jni.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertUTF8ToJavaString;
namespace instance_id {
// static
-scoped_ptr<InstanceID> InstanceID::Create(const std::string& app_id,
- gcm::InstanceIDHandler* handler) {
- return make_scoped_ptr(new InstanceIDAndroid(app_id, handler));
+bool InstanceIDAndroid::RegisterJni(JNIEnv* env) {
+ return RegisterNativesImpl(env);
}
-InstanceIDAndroid::InstanceIDAndroid(const std::string& app_id,
- gcm::InstanceIDHandler* handler)
- : InstanceID(app_id, handler) {}
+// static
+scoped_ptr<InstanceID> InstanceID::Create(const std::string& app_id,
+ gcm::InstanceIDHandler* unused) {
+ return make_scoped_ptr(new InstanceIDAndroid(app_id));
+}
+
+InstanceIDAndroid::InstanceIDAndroid(const std::string& app_id)
+ : InstanceID(app_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ DCHECK(!app_id.empty()) << "Empty app_id is not supported";
+ // The |app_id| is stored in GCM's category field by the desktop InstanceID
+ // implementation, but because the category is reserved for the app's package
+ // name on Android the subtype field is used instead.
+ std::string subtype = app_id;
+
+ JNIEnv* env = AttachCurrentThread();
+ java_ref_.Reset(Java_InstanceIDBridge_create(
+ env, reinterpret_cast<intptr_t>(this),
+ base::android::GetApplicationContext(),
+ ConvertUTF8ToJavaString(env, subtype).obj()));
+}
InstanceIDAndroid::~InstanceIDAndroid() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ JNIEnv* env = AttachCurrentThread();
+ Java_InstanceIDBridge_destroy(env, java_ref_.obj());
}
void InstanceIDAndroid::GetID(const GetIDCallback& callback) {
- NOTIMPLEMENTED();
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ JNIEnv* env = AttachCurrentThread();
+ std::string id = ConvertJavaStringToUTF8(
+ Java_InstanceIDBridge_getId(env, java_ref_.obj()));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback, id));
}
void InstanceIDAndroid::GetCreationTime(
const GetCreationTimeCallback& callback) {
- NOTIMPLEMENTED();
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ JNIEnv* env = AttachCurrentThread();
+ int64_t creation_time_unix_ms =
+ Java_InstanceIDBridge_getCreationTime(env, java_ref_.obj());
+ base::Time creation_time;
+ // If the InstanceID's getId, getToken and deleteToken methods have never been
+ // called, or deleteInstanceID has cleared it since, creation time will be 0.
+ if (creation_time_unix_ms) {
+ creation_time = base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(creation_time_unix_ms);
+ }
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, creation_time));
}
void InstanceIDAndroid::GetToken(
- const std::string& audience,
+ const std::string& authorized_entity,
const std::string& scope,
const std::map<std::string, std::string>& options,
const GetTokenCallback& callback) {
- NOTIMPLEMENTED();
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ int32_t request_id = get_token_callbacks_.Add(new GetTokenCallback(callback));
+
+ std::vector<std::string> options_strings;
+ for (const auto& entry : options) {
+ options_strings.push_back(entry.first);
+ options_strings.push_back(entry.second);
+ }
+
+ JNIEnv* env = AttachCurrentThread();
+ Java_InstanceIDBridge_getToken(
+ env, java_ref_.obj(), request_id,
+ ConvertUTF8ToJavaString(env, authorized_entity).obj(),
+ ConvertUTF8ToJavaString(env, scope).obj(),
+ base::android::ToJavaArrayOfStrings(env, options_strings).obj());
}
-void InstanceIDAndroid::DeleteToken(const std::string& audience,
+void InstanceIDAndroid::DeleteToken(const std::string& authorized_entity,
const std::string& scope,
const DeleteTokenCallback& callback) {
- NOTIMPLEMENTED();
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ int32_t request_id =
+ delete_token_callbacks_.Add(new DeleteTokenCallback(callback));
+
+ JNIEnv* env = AttachCurrentThread();
+ Java_InstanceIDBridge_deleteToken(
+ env, java_ref_.obj(), request_id,
+ ConvertUTF8ToJavaString(env, authorized_entity).obj(),
+ ConvertUTF8ToJavaString(env, scope).obj());
}
void InstanceIDAndroid::DeleteID(const DeleteIDCallback& callback) {
- NOTIMPLEMENTED();
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ int32_t request_id = delete_id_callbacks_.Add(new DeleteIDCallback(callback));
+
+ JNIEnv* env = AttachCurrentThread();
+ Java_InstanceIDBridge_deleteInstanceID(env, java_ref_.obj(), request_id);
+}
+
+void InstanceIDAndroid::DidGetToken(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint request_id,
+ const base::android::JavaParamRef<jstring>& jtoken) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ GetTokenCallback* callback = get_token_callbacks_.Lookup(request_id);
+ DCHECK(callback);
+ std::string token = ConvertJavaStringToUTF8(jtoken);
+ callback->Run(
+ token, token.empty() ? InstanceID::UNKNOWN_ERROR : InstanceID::SUCCESS);
+ get_token_callbacks_.Remove(request_id);
+}
+
+void InstanceIDAndroid::DidDeleteToken(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint request_id,
+ jboolean success) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ DeleteTokenCallback* callback = delete_token_callbacks_.Lookup(request_id);
+ DCHECK(callback);
+ callback->Run(success ? InstanceID::SUCCESS : InstanceID::UNKNOWN_ERROR);
+ delete_token_callbacks_.Remove(request_id);
+}
+
+void InstanceIDAndroid::DidDeleteID(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint request_id,
+ jboolean success) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ DeleteIDCallback* callback = delete_id_callbacks_.Lookup(request_id);
+ DCHECK(callback);
+ callback->Run(success ? InstanceID::SUCCESS : InstanceID::UNKNOWN_ERROR);
+ delete_id_callbacks_.Remove(request_id);
}
} // namespace instance_id
diff --git a/components/gcm_driver/instance_id/instance_id_android.h b/components/gcm_driver/instance_id/instance_id_android.h
index de0ff62d..a1152960 100644
--- a/components/gcm_driver/instance_id/instance_id_android.h
+++ b/components/gcm_driver/instance_id/instance_id_android.h
@@ -5,12 +5,17 @@
#ifndef COMPONENTS_GCM_DRIVER_INSTANCE_ID_INSTANCE_ID_ANDROID_H_
#define COMPONENTS_GCM_DRIVER_INSTANCE_ID_INSTANCE_ID_ANDROID_H_
+#include <jni.h>
+
#include <map>
#include <string>
+#include "base/android/scoped_java_ref.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/id_map.h"
#include "base/macros.h"
+#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "components/gcm_driver/instance_id/instance_id.h"
@@ -19,10 +24,13 @@
// InstanceID implementation for Android.
class InstanceIDAndroid : public InstanceID {
public:
- InstanceIDAndroid(const std::string& app_id, gcm::InstanceIDHandler* handler);
+ // Register JNI methods.
+ static bool RegisterJni(JNIEnv* env);
+
+ InstanceIDAndroid(const std::string& app_id);
~InstanceIDAndroid() override;
- // InstanceID:
+ // InstanceID implementation:
void GetID(const GetIDCallback& callback) override;
void GetCreationTime(const GetCreationTimeCallback& callback) override;
void GetToken(const std::string& audience,
@@ -34,7 +42,29 @@
const DeleteTokenCallback& callback) override;
void DeleteID(const DeleteIDCallback& callback) override;
+ // Methods called from Java via JNI:
+ void DidGetToken(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint request_id,
+ const base::android::JavaParamRef<jstring>& jtoken);
+ void DidDeleteToken(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint request_id,
+ jboolean success);
+ void DidDeleteID(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint request_id,
+ jboolean success);
+
private:
+ base::android::ScopedJavaGlobalRef<jobject> java_ref_;
+
+ IDMap<GetTokenCallback, IDMapOwnPointer> get_token_callbacks_;
+ IDMap<DeleteTokenCallback, IDMapOwnPointer> delete_token_callbacks_;
+ IDMap<DeleteIDCallback, IDMapOwnPointer> delete_id_callbacks_;
+
+ base::ThreadChecker thread_checker_;
+
DISALLOW_COPY_AND_ASSIGN(InstanceIDAndroid);
};
diff --git a/components/gcm_driver/instance_id/instance_id_driver.cc b/components/gcm_driver/instance_id/instance_id_driver.cc
index 374be22..937d77b 100644
--- a/components/gcm_driver/instance_id/instance_id_driver.cc
+++ b/components/gcm_driver/instance_id/instance_id_driver.cc
@@ -12,22 +12,15 @@
namespace instance_id {
namespace {
-#if !defined(OS_ANDROID)
const char kInstanceIDFieldTrialName[] = "InstanceID";
const char kInstanceIDFieldTrialEnabledGroupName[] = "Enabled";
-#endif // !defined(OS_ANDROID)
} // namespace
// static
bool InstanceIDDriver::IsInstanceIDEnabled() {
-#if defined(OS_ANDROID)
- // Not implemented yet.
- return false;
-#else
std::string group_name =
base::FieldTrialList::FindFullName(kInstanceIDFieldTrialName);
return group_name == kInstanceIDFieldTrialEnabledGroupName;
-#endif // defined(OS_ANDROID)
}
InstanceIDDriver::InstanceIDDriver(gcm::GCMDriver* gcm_driver)
diff --git a/components/gcm_driver/instance_id/instance_id_impl.cc b/components/gcm_driver/instance_id/instance_id_impl.cc
index ee1ea35..f7e5014 100644
--- a/components/gcm_driver/instance_id/instance_id_impl.cc
+++ b/components/gcm_driver/instance_id/instance_id_impl.cc
@@ -54,8 +54,9 @@
InstanceIDImpl::InstanceIDImpl(const std::string& app_id,
gcm::InstanceIDHandler* handler)
- : InstanceID(app_id, handler), weak_ptr_factory_(this) {
- handler->GetInstanceIDData(
+ : InstanceID(app_id), handler_(handler), weak_ptr_factory_(this) {
+ DCHECK(handler_);
+ handler_->GetInstanceIDData(
app_id, base::Bind(&InstanceIDImpl::GetInstanceIDDataCompleted,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -126,9 +127,9 @@
const GetTokenCallback& callback) {
EnsureIDGenerated();
- handler()->GetToken(app_id(), authorized_entity, scope, options,
- base::Bind(&InstanceIDImpl::OnGetTokenCompleted,
- weak_ptr_factory_.GetWeakPtr(), callback));
+ handler_->GetToken(app_id(), authorized_entity, scope, options,
+ base::Bind(&InstanceIDImpl::OnGetTokenCompleted,
+ weak_ptr_factory_.GetWeakPtr(), callback));
}
void InstanceIDImpl::DeleteToken(const std::string& authorized_entity,
@@ -160,9 +161,9 @@
return;
}
- handler()->DeleteToken(app_id(), authorized_entity, scope,
- base::Bind(&InstanceIDImpl::OnDeleteTokenCompleted,
- weak_ptr_factory_.GetWeakPtr(), callback));
+ handler_->DeleteToken(app_id(), authorized_entity, scope,
+ base::Bind(&InstanceIDImpl::OnDeleteTokenCompleted,
+ weak_ptr_factory_.GetWeakPtr(), callback));
}
void InstanceIDImpl::DeleteID(const DeleteIDCallback& callback) {
@@ -184,11 +185,11 @@
return;
}
- handler()->DeleteAllTokensForApp(
+ handler_->DeleteAllTokensForApp(
app_id(), base::Bind(&InstanceIDImpl::OnDeleteIDCompleted,
weak_ptr_factory_.GetWeakPtr(), callback));
- handler()->RemoveInstanceIDData(app_id());
+ handler_->RemoveInstanceIDData(app_id());
id_.clear();
creation_time_ = base::Time();
@@ -261,7 +262,7 @@
creation_time_ = base::Time::Now();
// Save to the persistent store.
- handler()->AddInstanceIDData(
+ handler_->AddInstanceIDData(
app_id(), id_, base::Int64ToString(creation_time_.ToInternalValue()));
}
diff --git a/components/gcm_driver/instance_id/instance_id_impl.h b/components/gcm_driver/instance_id/instance_id_impl.h
index dd4569a..d36264c3 100644
--- a/components/gcm_driver/instance_id/instance_id_impl.h
+++ b/components/gcm_driver/instance_id/instance_id_impl.h
@@ -66,6 +66,10 @@
const DeleteTokenCallback& callback);
void DoDeleteID(const DeleteIDCallback& callback);
+ // Owned by GCMProfileServiceFactory, which is a dependency of
+ // InstanceIDProfileServiceFactory, which owns this.
+ gcm::InstanceIDHandler* handler_;
+
gcm::GCMDelayedTaskController delayed_task_controller_;
// The generated Instance ID.