File: jni_callback.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (145 lines) | stat: -rw-r--r-- 5,030 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// 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::BindOnce(
               [](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)));
}

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;
  }
}

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_FOR_JniCallbackImpl()