910e62b5创建于 1月15日历史提交
// Copyright 2025 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/jni_callback.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "base/base_minimal_jni/JniCallbackImpl_jni.h"

namespace base::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<jlong>(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<jlong>(wrapped_callback_.release()));
  }
  JniRepeatingCallback(const JniRepeatingCallback&) = delete;
  const JniRepeatingCallback& operator=(const JniRepeatingCallback&) = delete;

 private:
  std::unique_ptr<JniRepeatingWrappedCallbackType> wrapped_callback_;
};
}  // namespace

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,
    base::OnceCallback<void()>&& callback) {
  return ToJniCallback(env, base::BindOnce(
                                [](base::OnceCallback<void()> 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::RepeatingCallback<void()>& callback) {
  return ToJniCallback(
      env, base::BindRepeating(
               [](const base::RepeatingCallback<void()>& 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)));
}

static void JNI_JniCallbackImpl_OnResult(
    JNIEnv* env,
    jboolean isRepeating,
    jlong callbackPtr,
    const jni_zero::JavaParamRef<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_Destroy(JNIEnv* env,
                                        jboolean isRepeating,
                                        jlong 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 base::android

DEFINE_JNI(JniCallbackImpl)