summaryrefslogtreecommitdiffstats
path: root/widget/android/AndroidJNIWrapper.cpp
blob: e549c6fc7ca53e85be1dc857f3aacd87706d6ad0 (plain)
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
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <android/log.h>
#include <dlfcn.h>
#include <prthread.h>

#include "mozilla/DebugOnly.h"
#include "mozilla/Assertions.h"
#include "mozilla/SyncRunnable.h"
#include "nsThreadUtils.h"
#include "AndroidBridge.h"

extern "C" {
  jclass __jsjni_GetGlobalClassRef(const char *className);
}

class GetGlobalClassRefRunnable : public mozilla::Runnable {
  public:
    GetGlobalClassRefRunnable(const char *className, jclass *foundClass) :
        mClassName(className), mResult(foundClass) {}
    NS_IMETHOD Run() override {
        *mResult = __jsjni_GetGlobalClassRef(mClassName);
        return NS_OK;
    }
  private:
    const char *mClassName;
    jclass *mResult;
};

extern "C" {
  __attribute__ ((visibility("default")))
  jclass
  jsjni_FindClass(const char *className) {
    // FindClass outside the main thread will run into problems due
    // to missing the classpath
    MOZ_ASSERT(NS_IsMainThread());
    JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
    return env->FindClass(className);
  }

  jclass
  __jsjni_GetGlobalClassRef(const char *className) {
    // root class globally
    JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
    jclass globalRef = static_cast<jclass>(env->NewGlobalRef(env->FindClass(className)));
    if (!globalRef)
      return nullptr;

    // return the newly create global reference
    return globalRef;
  }

  __attribute__ ((visibility("default")))
  jclass
  jsjni_GetGlobalClassRef(const char *className) {
    if (NS_IsMainThread()) {
      return __jsjni_GetGlobalClassRef(className);
    }

    nsCOMPtr<nsIThread> mainThread;
    mozilla::DebugOnly<nsresult> rv = NS_GetMainThread(getter_AddRefs(mainThread));
    MOZ_ASSERT(NS_SUCCEEDED(rv));

    jclass foundClass;
    nsCOMPtr<nsIRunnable> runnable_ref(new GetGlobalClassRefRunnable(className,
                                                                     &foundClass));
    RefPtr<mozilla::SyncRunnable> sr = new mozilla::SyncRunnable(runnable_ref);
    sr->DispatchToThread(mainThread);
    if (!foundClass)
      return nullptr;

    return foundClass;
  }

  __attribute__ ((visibility("default")))
  jmethodID
  jsjni_GetStaticMethodID(jclass methodClass,
                          const char *methodName,
                          const char *signature) {
    JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
    return env->GetStaticMethodID(methodClass, methodName, signature);
  }

  __attribute__ ((visibility("default")))
  bool
  jsjni_ExceptionCheck() {
    JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();
    return env->ExceptionCheck();
  }

  __attribute__ ((visibility("default")))
  void
  jsjni_CallStaticVoidMethodA(jclass cls,
                              jmethodID method,
                              jvalue *values) {
    JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();

    mozilla::AutoLocalJNIFrame jniFrame(env);
    env->CallStaticVoidMethodA(cls, method, values);
  }

  __attribute__ ((visibility("default")))
  int
  jsjni_CallStaticIntMethodA(jclass cls,
                             jmethodID method,
                             jvalue *values) {
    JNIEnv *env = mozilla::jni::GetGeckoThreadEnv();

    mozilla::AutoLocalJNIFrame jniFrame(env);
    return env->CallStaticIntMethodA(cls, method, values);
  }

  __attribute__ ((visibility("default")))
  jobject jsjni_GetGlobalContextRef() {
    return mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
  }

  __attribute__ ((visibility("default")))
  JavaVM* jsjni_GetVM() {
    JavaVM* jvm;
    JNIEnv* const env = mozilla::jni::GetGeckoThreadEnv();
    MOZ_ALWAYS_TRUE(!env->GetJavaVM(&jvm));
    return jvm;
  }

  __attribute__ ((visibility("default")))
  JNIEnv* jsjni_GetJNIForThread() {
    return mozilla::jni::GetEnvForThread();
  }

  // For compatibility with JNI.jsm; some addons bundle their own JNI.jsm,
  // so we cannot just change the function name used in JNI.jsm.
  __attribute__ ((visibility("default")))
  JNIEnv* GetJNIForThread() {
    return mozilla::jni::GetEnvForThread();
  }
}