diff options
Diffstat (limited to '')
-rw-r--r-- | widget/android/AndroidBridge.h | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h new file mode 100644 index 0000000000..3183de5ae6 --- /dev/null +++ b/widget/android/AndroidBridge.h @@ -0,0 +1,362 @@ +/* -*- 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 <jni.h> +#include <android/log.h> +#include <cstdlib> +#include <unistd.h> + +#include "APKOpen.h" + +#include "nsCOMPtr.h" +#include "nsCOMArray.h" + +#include "js/RootingAPI.h" +#include "js/Value.h" +#include "mozilla/jni/Refs.h" + +#include "nsIMutableArray.h" +#include "nsIMIMEInfo.h" +#include "nsColor.h" +#include "gfxRect.h" + +#include "nsIAndroidBridge.h" + +#include "mozilla/Likely.h" +#include "mozilla/Mutex.h" +#include "mozilla/Types.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/jni/Utils.h" +#include "nsDataHashtable.h" + +#include "Units.h" + +// Some debug #defines +// #define DEBUG_ANDROID_EVENTS +// #define DEBUG_ANDROID_WIDGET + +class nsPIDOMWindowOuter; + +typedef void* EGLSurface; +class nsIRunnable; + +namespace mozilla { + +class AutoLocalJNIFrame; + +namespace hal { +class BatteryInformation; +class NetworkInformation; +} // namespace hal + +// The order and number of the members in this structure must correspond +// to the attrsAppearance array in GeckoAppShell.getSystemColors() +typedef struct AndroidSystemColors { + nscolor textColorPrimary; + nscolor textColorPrimaryInverse; + nscolor textColorSecondary; + nscolor textColorSecondaryInverse; + nscolor textColorTertiary; + nscolor textColorTertiaryInverse; + nscolor textColorHighlight; + nscolor colorForeground; + nscolor colorBackground; + nscolor panelColorForeground; + nscolor panelColorBackground; +} AndroidSystemColors; + +class AndroidBridge final { + public: + enum { + // Values for NotifyIME, in addition to values from the Gecko + // IMEMessage enum; use negative values here to prevent conflict + NOTIFY_IME_OPEN_VKB = -2, + NOTIFY_IME_REPLY_EVENT = -1, + }; + + enum { + LAYER_CLIENT_TYPE_NONE = 0, + LAYER_CLIENT_TYPE_GL = 2 // AndroidGeckoGLLayerClient + }; + + static bool IsJavaUiThread() { + return mozilla::jni::GetUIThreadId() == gettid(); + } + + static void ConstructBridge(); + static void DeconstructBridge(); + + static AndroidBridge* Bridge() { return sBridge; } + + void ContentDocumentChanged(mozIDOMWindowProxy* aDOMWindow); + bool IsContentDocumentDisplayed(mozIDOMWindowProxy* aDOMWindow); + + 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); + + bool HasHWVP8Encoder(); + bool HasHWVP8Decoder(); + bool HasHWH264(); + + void GetMimeTypeFromExtensions(const nsACString& aFileExt, + nsCString& aMimeType); + void GetExtensionFromMimeType(const nsACString& aMimeType, + nsACString& aFileExt); + + gfx::Rect getScreenSize(); + int GetScreenDepth(); + + void Vibrate(const nsTArray<uint32_t>& aPattern); + + void GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSize, + uint8_t* const aBuf); + + bool GetStaticStringField(const char* classID, const char* field, + nsAString& result, JNIEnv* env = nullptr); + + bool GetStaticIntField(const char* className, const char* fieldName, + int32_t* aInt, JNIEnv* env = nullptr); + + // 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); + + // These methods don't use a ScreenOrientation because it's an + // enum and that would require including the header which requires + // include IPC headers which requires including basictypes.h which + // requires a lot of changes... + uint32_t GetScreenOrientation(); + uint16_t GetScreenAngle(); + + int GetAPIVersion() { return mAPIVersion; } + + 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 nsDataHashtable<nsStringHashKey, nsString> sStoragePaths; + + static AndroidBridge* sBridge; + + AndroidBridge(); + ~AndroidBridge(); + + int mAPIVersion; + + // intput stream + jclass jReadableByteChannel; + jclass jChannels; + jmethodID jChannelCreate; + jmethodID jByteBufferRead; + + jclass jInputStream; + jmethodID jClose; + jmethodID jAvailable; + + jmethodID jCalculateLength; + + // some convinient types to have around + jclass jStringClass; + + 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__ */ |