blob: 2238ee2a05cf0516faef74fc3aeeb6b73e919f33 [file]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/android/callback_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/time/time.h"
#include "base/types/optional_ref.h"
// Must come after all headers that specialize FromJniType() / ToJniType().
#include "base/callback_jni/Callback2_jni.h"
#include "base/callback_jni/Callback_jni.h"
#include "base/jni_callback_jni/JniCallbackImpl_jni.h"
namespace base {
namespace android {
namespace {
class JniOnceCallback {
public:
explicit JniOnceCallback(JniOnceWrappedCallbackType&& on_complete)
: wrapped_callback_(std::make_unique<JniOnceWrappedCallbackType>(
std::move(on_complete))) {}
~JniOnceCallback() = default;
JniOnceCallback(const JniOnceCallback&) = delete;
const JniOnceCallback& operator=(const JniOnceCallback&) = delete;
jni_zero::ScopedJavaLocalRef<jobject> TransferToJava(JNIEnv* env) && {
CHECK(wrapped_callback_);
CHECK(!wrapped_callback_->is_null());
bool is_repeating = false;
return Java_JniCallbackImpl_Constructor(
env, is_repeating,
reinterpret_cast<int64_t>(wrapped_callback_.release()));
}
private:
std::unique_ptr<JniOnceWrappedCallbackType> wrapped_callback_;
};
class JniRepeatingCallback {
public:
explicit JniRepeatingCallback(
const JniRepeatingWrappedCallbackType& on_complete)
: wrapped_callback_(
std::make_unique<JniRepeatingWrappedCallbackType>(on_complete)) {}
explicit JniRepeatingCallback(JniRepeatingWrappedCallbackType&& on_complete)
: wrapped_callback_(std::make_unique<JniRepeatingWrappedCallbackType>(
std::move(on_complete))) {}
~JniRepeatingCallback() = default;
jni_zero::ScopedJavaLocalRef<jobject> TransferToJava(JNIEnv* env) && {
CHECK(wrapped_callback_);
CHECK(!wrapped_callback_->is_null());
bool is_repeating = true;
return Java_JniCallbackImpl_Constructor(
env, is_repeating,
reinterpret_cast<int64_t>(wrapped_callback_.release()));
}
JniRepeatingCallback(const JniRepeatingCallback&) = delete;
const JniRepeatingCallback& operator=(const JniRepeatingCallback&) = delete;
private:
std::unique_ptr<JniRepeatingWrappedCallbackType> wrapped_callback_;
};
class JniOnceCallback2 {
public:
explicit JniOnceCallback2(JniOnceWrappedCallback2Type&& on_complete)
: wrapped_callback_(std::make_unique<JniOnceWrappedCallback2Type>(
std::move(on_complete))) {}
~JniOnceCallback2() = default;
JniOnceCallback2(const JniOnceCallback2&) = delete;
const JniOnceCallback2& operator=(const JniOnceCallback2&) = delete;
jni_zero::ScopedJavaLocalRef<jobject> TransferToJava(JNIEnv* env) && {
CHECK(wrapped_callback_);
CHECK(!wrapped_callback_->is_null());
bool is_repeating = false;
return Java_JniCallbackImpl_Constructor(
env, is_repeating,
reinterpret_cast<int64_t>(wrapped_callback_.release()));
}
private:
std::unique_ptr<JniOnceWrappedCallback2Type> wrapped_callback_;
};
class JniRepeatingCallback2 {
public:
explicit JniRepeatingCallback2(
const JniRepeatingWrappedCallback2Type& on_complete)
: wrapped_callback_(
std::make_unique<JniRepeatingWrappedCallback2Type>(on_complete)) {}
explicit JniRepeatingCallback2(JniRepeatingWrappedCallback2Type&& on_complete)
: wrapped_callback_(std::make_unique<JniRepeatingWrappedCallback2Type>(
std::move(on_complete))) {}
~JniRepeatingCallback2() = default;
jni_zero::ScopedJavaLocalRef<jobject> TransferToJava(JNIEnv* env) && {
CHECK(wrapped_callback_);
CHECK(!wrapped_callback_->is_null());
bool is_repeating = true;
return Java_JniCallbackImpl_Constructor(
env, is_repeating,
reinterpret_cast<int64_t>(wrapped_callback_.release()));
}
JniRepeatingCallback2(const JniRepeatingCallback2&) = delete;
const JniRepeatingCallback2& operator=(const JniRepeatingCallback2&) = delete;
private:
std::unique_ptr<JniRepeatingWrappedCallback2Type> wrapped_callback_;
};
} // namespace
void RunObjectCallbackAndroid(const JavaRef<jobject>& callback,
const JavaRef<jobject>& arg) {
Java_Helper_onObjectResultFromNative(AttachCurrentThread(), callback, arg);
}
void RunObjectCallbackAndroid2(const JavaRef<jobject>& callback,
const JavaRef<jobject>& arg1,
const JavaRef<jobject>& arg2) {
Java_JniHelper_onResultFromNative(AttachCurrentThread(), callback, arg1,
arg2);
}
void RunBooleanCallbackAndroid(const JavaRef<jobject>& callback, bool arg) {
Java_Helper_onBooleanResultFromNative(AttachCurrentThread(), callback, arg);
}
void RunIntCallbackAndroid(const JavaRef<jobject>& callback, int32_t arg) {
Java_Helper_onIntResultFromNative(AttachCurrentThread(), callback, arg);
}
void RunLongCallbackAndroid(const JavaRef<jobject>& callback, int64_t arg) {
Java_Helper_onLongResultFromNative(AttachCurrentThread(), callback, arg);
}
void RunTimeCallbackAndroid(const JavaRef<jobject>& callback, base::Time time) {
RunLongCallbackAndroid(callback, time.InMillisecondsSinceUnixEpoch());
}
void RunStringCallbackAndroid(const JavaRef<jobject>& callback,
const std::string& arg) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> java_string = ConvertUTF8ToJavaString(env, arg);
Java_Helper_onObjectResultFromNative(env, callback, java_string);
}
void RunOptionalStringCallbackAndroid(
const JavaRef<jobject>& callback,
base::optional_ref<const std::string> optional_string_arg) {
JNIEnv* env = AttachCurrentThread();
RunObjectCallbackAndroid(
callback, optional_string_arg
? ConvertUTF8ToJavaString(env, optional_string_arg.value())
: nullptr);
}
void RunByteArrayCallbackAndroid(const JavaRef<jobject>& callback,
const std::vector<uint8_t>& arg) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jbyteArray> j_bytes = ToJavaByteArray(env, arg);
Java_Helper_onObjectResultFromNative(env, callback, j_bytes);
}
ScopedJavaLocalRef<jobject> ToJniCallback(JNIEnv* env,
base::OnceClosure&& callback) {
if (callback.is_null()) {
return nullptr;
}
return ToJniCallback(env, base::BindOnce(
[](base::OnceClosure captured_callback,
const jni_zero::JavaRef<jobject>& j_null) {
// For callbacks with no parameters, the
// parameter from Java should be null.
CHECK(!j_null);
std::move(captured_callback).Run();
},
std::move(callback)));
}
ScopedJavaLocalRef<jobject> ToJniCallback(
JNIEnv* env,
const base::RepeatingClosure& callback) {
if (callback.is_null()) {
return nullptr;
}
return ToJniCallback(env,
base::BindRepeating(
[](const base::RepeatingClosure& captured_callback,
const jni_zero::JavaRef<jobject>& j_null) {
// For callbacks with no parameters, the parameter
// from Java should be null.
CHECK(!j_null);
captured_callback.Run();
},
callback));
}
ScopedJavaLocalRef<jobject> ToJniCallback(JNIEnv* env,
base::RepeatingClosure&& callback) {
if (callback.is_null()) {
return nullptr;
}
return ToJniCallback(env, base::BindRepeating(
[](base::RepeatingClosure captured_callback,
const jni_zero::JavaRef<jobject>& j_null) {
// For callbacks with no parameters, the
// parameter from Java should be null.
CHECK(!j_null);
captured_callback.Run();
},
std::move(callback)));
}
ScopedJavaLocalRef<jobject> ToJniCallback(
JNIEnv* env,
JniOnceWrappedCallbackType&& callback) {
return JniOnceCallback(std::move(callback)).TransferToJava(env);
}
ScopedJavaLocalRef<jobject> ToJniCallback(
JNIEnv* env,
JniRepeatingWrappedCallbackType&& callback) {
return JniRepeatingCallback(std::move(callback)).TransferToJava(env);
}
ScopedJavaLocalRef<jobject> ToJniCallback(
JNIEnv* env,
const JniRepeatingWrappedCallbackType& callback) {
return JniRepeatingCallback(callback).TransferToJava(env);
}
ScopedJavaLocalRef<jobject> ToJniCallback(
JNIEnv* env,
JniOnceWrappedCallback2Type&& callback) {
return JniOnceCallback2(std::move(callback)).TransferToJava(env);
}
ScopedJavaLocalRef<jobject> ToJniCallback(
JNIEnv* env,
JniRepeatingWrappedCallback2Type&& callback) {
return JniRepeatingCallback2(std::move(callback)).TransferToJava(env);
}
ScopedJavaLocalRef<jobject> ToJniCallback(
JNIEnv* env,
const JniRepeatingWrappedCallback2Type& callback) {
return JniRepeatingCallback2(callback).TransferToJava(env);
}
static void JNI_JniCallbackImpl_OnResult(
JNIEnv* env,
bool isRepeating,
int64_t callbackPtr,
const jni_zero::JavaRef<jobject>& j_result) {
if (isRepeating) {
auto* callback =
reinterpret_cast<JniRepeatingWrappedCallbackType*>(callbackPtr);
callback->Run(j_result);
} else {
auto* callback = reinterpret_cast<JniOnceWrappedCallbackType*>(callbackPtr);
std::move(*callback).Run(j_result);
delete callback;
}
}
static void JNI_JniCallbackImpl_OnResult2(
JNIEnv* env,
bool isRepeating,
int64_t callbackPtr,
const jni_zero::JavaRef<jobject>& j_result1,
const jni_zero::JavaRef<jobject>& j_result2) {
if (isRepeating) {
auto* callback =
reinterpret_cast<JniRepeatingWrappedCallback2Type*>(callbackPtr);
callback->Run(j_result1, j_result2);
} else {
auto* callback =
reinterpret_cast<JniOnceWrappedCallback2Type*>(callbackPtr);
std::move(*callback).Run(j_result1, j_result2);
delete callback;
}
}
static void JNI_JniCallbackImpl_Destroy(JNIEnv* env,
bool isRepeating,
int64_t callbackPtr) {
if (isRepeating) {
auto* callback =
reinterpret_cast<JniRepeatingWrappedCallbackType*>(callbackPtr);
// Call Reset to ensure all accidental use-after-frees fail loudly.
callback->Reset();
delete callback;
} else {
auto* callback = reinterpret_cast<JniOnceWrappedCallbackType*>(callbackPtr);
// Call Reset to ensure all accidental use-after-frees fail loudly.
callback->Reset();
delete callback;
}
}
} // namespace android
} // namespace base
DEFINE_JNI(Callback)
DEFINE_JNI(JniCallbackImpl)