| // Copyright 2015 The Chromium Authors | |
| // 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/instance_id_android.h" | |
| #include <stdint.h> | |
| #include <memory> | |
| #include <numeric> | |
| #include "base/android/jni_android.h" | |
| #include "base/android/jni_string.h" | |
| #include "base/functional/bind.h" | |
| #include "base/location.h" | |
| #include "base/logging.h" | |
| #include "base/task/single_thread_task_runner.h" | |
| #include "base/time/time.h" | |
| // Must come after all headers that specialize FromJniType() / ToJniType(). | |
| #include "components/gcm_driver/instance_id/android/jni_headers/InstanceIDBridge_jni.h" | |
| using base::android::AttachCurrentThread; | |
| namespace instance_id { | |
| InstanceIDAndroid::ScopedBlockOnAsyncTasksForTesting:: | |
| ScopedBlockOnAsyncTasksForTesting() { | |
| JNIEnv* env = AttachCurrentThread(); | |
| previous_value_ = | |
| Java_InstanceIDBridge_setBlockOnAsyncTasksForTesting(env, true); | |
| } | |
| InstanceIDAndroid::ScopedBlockOnAsyncTasksForTesting:: | |
| ~ScopedBlockOnAsyncTasksForTesting() { | |
| JNIEnv* env = AttachCurrentThread(); | |
| Java_InstanceIDBridge_setBlockOnAsyncTasksForTesting(env, previous_value_); | |
| } | |
| // static | |
| std::unique_ptr<InstanceID> InstanceID::CreateInternal( | |
| const std::string& app_id, | |
| gcm::GCMDriver* gcm_driver) { | |
| return std::make_unique<InstanceIDAndroid>(app_id, gcm_driver); | |
| } | |
| InstanceIDAndroid::InstanceIDAndroid(const std::string& app_id, | |
| gcm::GCMDriver* gcm_driver) | |
| : InstanceID(app_id, gcm_driver) { | |
| 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), subtype)); | |
| } | |
| InstanceIDAndroid::~InstanceIDAndroid() { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| JNIEnv* env = AttachCurrentThread(); | |
| Java_InstanceIDBridge_destroy(env, java_ref_); | |
| } | |
| void InstanceIDAndroid::GetID(GetIDCallback callback) { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| int32_t request_id = get_id_callbacks_.Add( | |
| std::make_unique<GetIDCallback>(std::move(callback))); | |
| JNIEnv* env = AttachCurrentThread(); | |
| Java_InstanceIDBridge_getId(env, java_ref_, request_id); | |
| } | |
| void InstanceIDAndroid::GetCreationTime(GetCreationTimeCallback callback) { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| int32_t request_id = get_creation_time_callbacks_.Add( | |
| std::make_unique<GetCreationTimeCallback>(std::move(callback))); | |
| JNIEnv* env = AttachCurrentThread(); | |
| Java_InstanceIDBridge_getCreationTime(env, java_ref_, request_id); | |
| } | |
| void InstanceIDAndroid::GetToken( | |
| const std::string& authorized_entity, | |
| const std::string& scope, | |
| base::TimeDelta time_to_live, | |
| std::set<Flags> flags, | |
| GetTokenCallback callback) { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| if (!time_to_live.is_zero()) { | |
| LOG(WARNING) << "Non-zero TTL requested for InstanceID token, while TTLs" | |
| " are not supported by Android Firebase IID API."; | |
| } | |
| int32_t request_id = get_token_callbacks_.Add( | |
| std::make_unique<GetTokenCallback>(std::move(callback))); | |
| int java_flags = std::accumulate( | |
| flags.begin(), flags.end(), 0, | |
| [](int sum, Flags flag) { return sum + static_cast<int>(flag); }); | |
| JNIEnv* env = AttachCurrentThread(); | |
| Java_InstanceIDBridge_getToken(env, java_ref_, request_id, authorized_entity, | |
| scope, java_flags); | |
| } | |
| void InstanceIDAndroid::ValidateToken(const std::string& authorized_entity, | |
| const std::string& scope, | |
| const std::string& token, | |
| ValidateTokenCallback callback) { | |
| // gcm_driver doesn't store tokens on Android, so assume it's valid. | |
| base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( | |
| FROM_HERE, base::BindOnce(std::move(callback), true /* is_valid */)); | |
| } | |
| void InstanceIDAndroid::DeleteTokenImpl(const std::string& authorized_entity, | |
| const std::string& scope, | |
| DeleteTokenCallback callback) { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| int32_t request_id = delete_token_callbacks_.Add( | |
| std::make_unique<DeleteTokenCallback>(std::move(callback))); | |
| JNIEnv* env = AttachCurrentThread(); | |
| Java_InstanceIDBridge_deleteToken(env, java_ref_, request_id, | |
| authorized_entity, scope); | |
| } | |
| void InstanceIDAndroid::DeleteIDImpl(DeleteIDCallback callback) { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| int32_t request_id = delete_id_callbacks_.Add( | |
| std::make_unique<DeleteIDCallback>(std::move(callback))); | |
| JNIEnv* env = AttachCurrentThread(); | |
| Java_InstanceIDBridge_deleteInstanceID(env, java_ref_, request_id); | |
| } | |
| void InstanceIDAndroid::DidGetID(JNIEnv* env, | |
| int32_t request_id, | |
| const std::string& id) { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| GetIDCallback* callback = get_id_callbacks_.Lookup(request_id); | |
| DCHECK(callback); | |
| std::move(*callback).Run(id); | |
| get_id_callbacks_.Remove(request_id); | |
| } | |
| void InstanceIDAndroid::DidGetCreationTime(JNIEnv* env, | |
| int32_t request_id, | |
| int64_t creation_time_unix_ms) { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| 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::Milliseconds(creation_time_unix_ms); | |
| } | |
| GetCreationTimeCallback* callback = | |
| get_creation_time_callbacks_.Lookup(request_id); | |
| DCHECK(callback); | |
| std::move(*callback).Run(creation_time); | |
| get_creation_time_callbacks_.Remove(request_id); | |
| } | |
| void InstanceIDAndroid::DidGetToken(JNIEnv* env, | |
| int32_t request_id, | |
| const std::string& token) { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| GetTokenCallback* callback = get_token_callbacks_.Lookup(request_id); | |
| DCHECK(callback); | |
| std::move(*callback).Run( | |
| token, token.empty() ? InstanceID::UNKNOWN_ERROR : InstanceID::SUCCESS); | |
| get_token_callbacks_.Remove(request_id); | |
| } | |
| void InstanceIDAndroid::DidDeleteToken(JNIEnv* env, | |
| int32_t request_id, | |
| bool success) { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| DeleteTokenCallback* callback = delete_token_callbacks_.Lookup(request_id); | |
| DCHECK(callback); | |
| std::move(*callback).Run(success ? InstanceID::SUCCESS | |
| : InstanceID::UNKNOWN_ERROR); | |
| delete_token_callbacks_.Remove(request_id); | |
| } | |
| void InstanceIDAndroid::DidDeleteID(JNIEnv* env, | |
| int32_t request_id, | |
| bool success) { | |
| DCHECK(thread_checker_.CalledOnValidThread()); | |
| DeleteIDCallback* callback = delete_id_callbacks_.Lookup(request_id); | |
| DCHECK(callback); | |
| std::move(*callback).Run(success ? InstanceID::SUCCESS | |
| : InstanceID::UNKNOWN_ERROR); | |
| delete_id_callbacks_.Remove(request_id); | |
| } | |
| } // namespace instance_id | |
| DEFINE_JNI(InstanceIDBridge) |