summaryrefslogtreecommitdiffstats
path: root/widget/android/AndroidBridge.h
diff options
context:
space:
mode:
Diffstat (limited to 'widget/android/AndroidBridge.h')
-rw-r--r--widget/android/AndroidBridge.h275
1 files changed, 275 insertions, 0 deletions
diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h
new file mode 100644
index 0000000000..f2070ef31a
--- /dev/null
+++ b/widget/android/AndroidBridge.h
@@ -0,0 +1,275 @@
+/* -*- Mode: c++; c-basic-offset: 2; 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/. */
+
+#ifndef AndroidBridge_h__
+#define AndroidBridge_h__
+
+#include <unistd.h> // for gettid
+
+#include "nsCOMPtr.h"
+
+#include "mozilla/jni/Refs.h"
+
+#include "nsIMutableArray.h"
+#include "nsIMIMEInfo.h"
+
+#include "nsIAndroidBridge.h"
+
+#include "mozilla/jni/Utils.h"
+#include "nsTHashMap.h"
+
+// Some debug #defines
+// #define DEBUG_ANDROID_EVENTS
+// #define DEBUG_ANDROID_WIDGET
+
+namespace mozilla {
+
+class AutoLocalJNIFrame;
+
+namespace hal {
+class BatteryInformation;
+class NetworkInformation;
+enum class ScreenOrientation : uint32_t;
+} // namespace hal
+
+class AndroidBridge final {
+ public:
+ static bool IsJavaUiThread() {
+ return mozilla::jni::GetUIThreadId() == gettid();
+ }
+
+ static void ConstructBridge();
+ static void DeconstructBridge();
+
+ static AndroidBridge* Bridge() { return sBridge; }
+
+ bool GetHandlersForURL(const nsAString& aURL,
+ nsIMutableArray* handlersArray = nullptr,
+ nsIHandlerApp** aDefaultApp = nullptr,
+ const nsAString& aAction = u""_ns);
+
+ bool GetHandlersForMimeType(const nsAString& aMimeType,
+ nsIMutableArray* handlersArray = nullptr,
+ nsIHandlerApp** aDefaultApp = nullptr,
+ const nsAString& aAction = u""_ns);
+
+ void GetMimeTypeFromExtensions(const nsACString& aFileExt,
+ nsCString& aMimeType);
+ void GetExtensionFromMimeType(const nsACString& aMimeType,
+ nsACString& aFileExt);
+
+ void Vibrate(const nsTArray<uint32_t>& aPattern);
+
+ void GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSize,
+ uint8_t* const aBuf);
+
+ // Returns a global reference to the Context for Fennec's Activity. The
+ // caller is responsible for ensuring this doesn't leak by calling
+ // DeleteGlobalRef() when the context is no longer needed.
+ jobject GetGlobalContextRef(void);
+
+ void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo);
+
+ void GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo);
+
+ hal::ScreenOrientation GetScreenOrientation();
+ uint16_t GetScreenAngle();
+
+ nsresult GetProxyForURI(const nsACString& aSpec, const nsACString& aScheme,
+ const nsACString& aHost, const int32_t aPort,
+ nsACString& aResult);
+
+ bool PumpMessageLoop();
+
+ // Utility methods.
+ static jfieldID GetFieldID(JNIEnv* env, jclass jClass, const char* fieldName,
+ const char* fieldType);
+ static jfieldID GetStaticFieldID(JNIEnv* env, jclass jClass,
+ const char* fieldName,
+ const char* fieldType);
+ static jmethodID GetMethodID(JNIEnv* env, jclass jClass,
+ const char* methodName, const char* methodType);
+ static jmethodID GetStaticMethodID(JNIEnv* env, jclass jClass,
+ const char* methodName,
+ const char* methodType);
+
+ static jni::Object::LocalRef ChannelCreate(jni::Object::Param);
+
+ static void InputStreamClose(jni::Object::Param obj);
+ static uint32_t InputStreamAvailable(jni::Object::Param obj);
+ static nsresult InputStreamRead(jni::Object::Param obj, char* aBuf,
+ uint32_t aCount, uint32_t* aRead);
+
+ protected:
+ static nsTHashMap<nsStringHashKey, nsString> sStoragePaths;
+
+ static AndroidBridge* sBridge;
+
+ AndroidBridge();
+ ~AndroidBridge();
+
+ jni::Object::GlobalRef mMessageQueue;
+ jfieldID mMessageQueueMessages;
+ jmethodID mMessageQueueNext;
+};
+
+class AutoJNIClass {
+ private:
+ JNIEnv* const mEnv;
+ const jclass mClass;
+
+ public:
+ AutoJNIClass(JNIEnv* jEnv, const char* name)
+ : mEnv(jEnv), mClass(jni::GetClassRef(jEnv, name)) {}
+
+ ~AutoJNIClass() { mEnv->DeleteLocalRef(mClass); }
+
+ jclass getRawRef() const { return mClass; }
+
+ jclass getGlobalRef() const {
+ return static_cast<jclass>(mEnv->NewGlobalRef(mClass));
+ }
+
+ jfieldID getField(const char* name, const char* type) const {
+ return AndroidBridge::GetFieldID(mEnv, mClass, name, type);
+ }
+
+ jfieldID getStaticField(const char* name, const char* type) const {
+ return AndroidBridge::GetStaticFieldID(mEnv, mClass, name, type);
+ }
+
+ jmethodID getMethod(const char* name, const char* type) const {
+ return AndroidBridge::GetMethodID(mEnv, mClass, name, type);
+ }
+
+ jmethodID getStaticMethod(const char* name, const char* type) const {
+ return AndroidBridge::GetStaticMethodID(mEnv, mClass, name, type);
+ }
+};
+
+class AutoJObject {
+ public:
+ explicit AutoJObject(JNIEnv* aJNIEnv = nullptr) : mObject(nullptr) {
+ mJNIEnv = aJNIEnv ? aJNIEnv : jni::GetGeckoThreadEnv();
+ }
+
+ AutoJObject(JNIEnv* aJNIEnv, jobject aObject) {
+ mJNIEnv = aJNIEnv ? aJNIEnv : jni::GetGeckoThreadEnv();
+ mObject = aObject;
+ }
+
+ ~AutoJObject() {
+ if (mObject) mJNIEnv->DeleteLocalRef(mObject);
+ }
+
+ jobject operator=(jobject aObject) {
+ if (mObject) {
+ mJNIEnv->DeleteLocalRef(mObject);
+ }
+ return mObject = aObject;
+ }
+
+ operator jobject() { return mObject; }
+
+ private:
+ JNIEnv* mJNIEnv;
+ jobject mObject;
+};
+
+class AutoLocalJNIFrame {
+ public:
+ explicit AutoLocalJNIFrame(int nEntries = 15)
+ : mEntries(nEntries),
+ mJNIEnv(jni::GetGeckoThreadEnv()),
+ mHasFrameBeenPushed(false) {
+ MOZ_ASSERT(mJNIEnv);
+ Push();
+ }
+
+ explicit AutoLocalJNIFrame(JNIEnv* aJNIEnv, int nEntries = 15)
+ : mEntries(nEntries),
+ mJNIEnv(aJNIEnv ? aJNIEnv : jni::GetGeckoThreadEnv()),
+ mHasFrameBeenPushed(false) {
+ MOZ_ASSERT(mJNIEnv);
+ Push();
+ }
+
+ ~AutoLocalJNIFrame() {
+ if (mHasFrameBeenPushed) {
+ Pop();
+ }
+ }
+
+ JNIEnv* GetEnv() { return mJNIEnv; }
+
+ bool CheckForException() {
+ if (mJNIEnv->ExceptionCheck()) {
+ MOZ_CATCH_JNI_EXCEPTION(mJNIEnv);
+ return true;
+ }
+ return false;
+ }
+
+ // Note! Calling Purge makes all previous local refs created in
+ // the AutoLocalJNIFrame's scope INVALID; be sure that you locked down
+ // any local refs that you need to keep around in global refs!
+ void Purge() {
+ Pop();
+ Push();
+ }
+
+ template <typename ReturnType = jobject>
+ ReturnType Pop(ReturnType aResult = nullptr) {
+ MOZ_ASSERT(mHasFrameBeenPushed);
+ mHasFrameBeenPushed = false;
+ return static_cast<ReturnType>(
+ mJNIEnv->PopLocalFrame(static_cast<jobject>(aResult)));
+ }
+
+ private:
+ void Push() {
+ MOZ_ASSERT(!mHasFrameBeenPushed);
+ // Make sure there is enough space to store a local ref to the
+ // exception. I am not completely sure this is needed, but does
+ // not hurt.
+ if (mJNIEnv->PushLocalFrame(mEntries + 1) != 0) {
+ CheckForException();
+ return;
+ }
+ mHasFrameBeenPushed = true;
+ }
+
+ const int mEntries;
+ JNIEnv* const mJNIEnv;
+ bool mHasFrameBeenPushed;
+};
+
+} // namespace mozilla
+
+#define NS_ANDROIDBRIDGE_CID \
+ { \
+ 0x0FE2321D, 0xEBD9, 0x467D, { \
+ 0xA7, 0x43, 0x03, 0xA6, 0x8D, 0x40, 0x59, 0x9E \
+ } \
+ }
+
+class nsAndroidBridge final : public nsIAndroidBridge {
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIANDROIDBRIDGE
+
+ NS_FORWARD_SAFE_NSIANDROIDEVENTDISPATCHER(mEventDispatcher)
+
+ nsAndroidBridge();
+
+ private:
+ ~nsAndroidBridge();
+
+ nsCOMPtr<nsIAndroidEventDispatcher> mEventDispatcher;
+
+ protected:
+};
+
+#endif /* AndroidBridge_h__ */