Bug 1116589 - Use templated JNI classes in generated bindings; r=snorp

This commit is contained in:
Jim Chen
2015-01-09 19:33:57 -05:00
parent 277ad8ae08
commit 60b2a7d4b1
59 changed files with 4728 additions and 4688 deletions

View File

@@ -46,8 +46,9 @@
#include "SurfaceTexture.h"
using namespace mozilla;
using namespace mozilla::widget::android;
using namespace mozilla::gfx;
using namespace mozilla::jni;
using namespace mozilla::widget;
AndroidBridge* AndroidBridge::sBridge;
pthread_t AndroidBridge::sJavaUiThread = -1;
@@ -66,22 +67,29 @@ static android::sp<AndroidRefable> (*android_SurfaceTexture_getNativeWindow)(JNI
jclass AndroidBridge::GetClassGlobalRef(JNIEnv* env, const char* className)
{
jobject classLocalRef = env->FindClass(className);
if (!classLocalRef) {
ALOG(">>> FATAL JNI ERROR! FindClass(className=\"%s\") failed. Did ProGuard optimize away something it shouldn't have?",
// First try the default class loader.
auto classRef = ClassObject::LocalRef::Adopt(
env, env->FindClass(className));
if (!classRef && sBridge && sBridge->mClassLoader) {
// If the default class loader failed but we have an app class loader, try that.
// Clear the pending exception from failed FindClass call above.
env->ExceptionClear();
classRef = ClassObject::LocalRef::Adopt(env,
env->CallObjectMethod(sBridge->mClassLoader.Get(),
sBridge->mClassLoaderLoadClass,
Param<String>::Type(className, env).Get()));
}
if (!classRef) {
ALOG(">>> FATAL JNI ERROR! FindClass(className=\"%s\") failed. "
"Did ProGuard optimize away something it shouldn't have?",
className);
env->ExceptionDescribe();
MOZ_CRASH();
}
jobject classGlobalRef = env->NewGlobalRef(classLocalRef);
if (!classGlobalRef) {
env->ExceptionDescribe();
MOZ_CRASH();
}
// Local ref no longer necessary because we have a global ref.
env->DeleteLocalRef(classLocalRef);
classLocalRef = nullptr;
return static_cast<jclass>(classGlobalRef);
return ClassObject::GlobalRef(env, classRef).Forget();
}
jmethodID AndroidBridge::GetMethodID(JNIEnv* env, jclass jClass,
@@ -141,7 +149,7 @@ jfieldID AndroidBridge::GetStaticFieldID(JNIEnv* env, jclass jClass,
}
void
AndroidBridge::ConstructBridge(JNIEnv *jEnv)
AndroidBridge::ConstructBridge(JNIEnv *jEnv, Object::Param clsLoader)
{
/* NSS hack -- bionic doesn't handle recursive unloads correctly,
* because library finalizer functions are called with the dynamic
@@ -154,14 +162,14 @@ AndroidBridge::ConstructBridge(JNIEnv *jEnv)
PR_NewThreadPrivateIndex(&sJavaEnvThreadIndex, JavaThreadDetachFunc);
AndroidBridge *bridge = new AndroidBridge();
if (!bridge->Init(jEnv)) {
if (!bridge->Init(jEnv, clsLoader)) {
delete bridge;
}
sBridge = bridge;
}
bool
AndroidBridge::Init(JNIEnv *jEnv)
AndroidBridge::Init(JNIEnv *jEnv, Object::Param clsLoader)
{
ALOG_BRIDGE("AndroidBridge::Init");
jEnv->GetJavaVM(&mJavaVM);
@@ -171,6 +179,11 @@ AndroidBridge::Init(JNIEnv *jEnv)
AutoLocalJNIFrame jniFrame(jEnv);
mClassLoader = Object::GlobalRef(jEnv, clsLoader);
mClassLoaderLoadClass = GetMethodID(
jEnv, jEnv->GetObjectClass(clsLoader.Get()),
"loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
mJNIEnv = nullptr;
mThread = -1;
mGLControllerObj = nullptr;
@@ -228,14 +241,6 @@ AndroidBridge::Init(JNIEnv *jEnv)
InitAndroidJavaWrappers(jEnv);
if (mAPIVersion >= 16 /* Jelly Bean */) {
sdk::InitMediaCodecStubs(jEnv);
}
if (mAPIVersion >= 14 /* ICS */) {
sdk::InitSurfaceTextureStubs(jEnv);
}
// jEnv should NOT be cached here by anything -- the jEnv here
// is not valid for the real gecko main thread, which is set
// at SetMainThread time.
@@ -434,20 +439,17 @@ AndroidBridge::GetHandlersForMimeType(const nsAString& aMimeType,
{
ALOG_BRIDGE("AndroidBridge::GetHandlersForMimeType");
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jobjectArray arr =
mozilla::widget::android::GeckoAppShell::GetHandlersForMimeTypeWrapper(aMimeType, aAction);
auto arr = GeckoAppShell::GetHandlersForMimeTypeWrapper(aMimeType, aAction);
if (!arr)
return false;
jsize len = env->GetArrayLength(arr);
JNIEnv* const env = arr.Env();
jsize len = env->GetArrayLength(arr.Get());
if (!aHandlersArray)
return len > 0;
getHandlersFromStringArray(env, arr, len, aHandlersArray,
getHandlersFromStringArray(env, arr.Get(), len, aHandlersArray,
aDefaultApp, aAction,
NS_ConvertUTF16toUTF8(aMimeType));
return true;
@@ -461,19 +463,17 @@ AndroidBridge::GetHandlersForURL(const nsAString& aURL,
{
ALOG_BRIDGE("AndroidBridge::GetHandlersForURL");
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jobjectArray arr = mozilla::widget::android::GeckoAppShell::GetHandlersForURLWrapper(aURL, aAction);
auto arr = GeckoAppShell::GetHandlersForURLWrapper(aURL, aAction);
if (!arr)
return false;
jsize len = env->GetArrayLength(arr);
JNIEnv* const env = arr.Env();
jsize len = env->GetArrayLength(arr.Get());
if (!aHandlersArray)
return len > 0;
getHandlersFromStringArray(env, arr, len, aHandlersArray,
getHandlersFromStringArray(env, arr.Get(), len, aHandlersArray,
aDefaultApp, aAction);
return true;
}
@@ -483,16 +483,11 @@ AndroidBridge::GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString&
{
ALOG_BRIDGE("AndroidBridge::GetMimeTypeFromExtensions");
JNIEnv *env = GetJNIEnv();
auto jstrType = GeckoAppShell::GetMimeTypeFromExtensionsWrapper(aFileExt);
AutoLocalJNIFrame jniFrame(env, 1);
jstring jstrType = mozilla::widget::android::GeckoAppShell::GetMimeTypeFromExtensionsWrapper
(NS_ConvertUTF8toUTF16(aFileExt));
if (!jstrType) {
return;
if (jstrType) {
aMimeType = jstrType;
}
nsJNIString jniStr(jstrType, env);
CopyUTF16toUTF8(jniStr.get(), aMimeType);
}
void
@@ -500,16 +495,11 @@ AndroidBridge::GetExtensionFromMimeType(const nsACString& aMimeType, nsACString&
{
ALOG_BRIDGE("AndroidBridge::GetExtensionFromMimeType");
JNIEnv *env = GetJNIEnv();
auto jstrExt = GeckoAppShell::GetExtensionFromMimeTypeWrapper(aMimeType);
AutoLocalJNIFrame jniFrame(env, 1);
jstring jstrExt = mozilla::widget::android::GeckoAppShell::GetExtensionFromMimeTypeWrapper
(NS_ConvertUTF8toUTF16(aMimeType));
if (!jstrExt) {
return;
if (jstrExt) {
aFileExt = nsCString(jstrExt);
}
nsJNIString jniStr(jstrExt, env);
CopyUTF16toUTF8(jniStr.get(), aFileExt);
}
bool
@@ -517,16 +507,12 @@ AndroidBridge::GetClipboardText(nsAString& aText)
{
ALOG_BRIDGE("AndroidBridge::GetClipboardText");
JNIEnv *env = GetJNIEnv();
auto text = Clipboard::GetClipboardTextWrapper();
AutoLocalJNIFrame jniFrame(env, 1);
jstring result = Clipboard::GetClipboardTextWrapper();
if (!result)
return false;
nsJNIString jniStr(result, env);
aText.Assign(jniStr);
return true;
if (text) {
aText = nsString(text);
}
return !!text;
}
void
@@ -542,7 +528,7 @@ AndroidBridge::ShowAlertNotification(const nsAString& aImageUrl,
nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeAddObserver(aAlertName, aAlertListener));
}
mozilla::widget::android::GeckoAppShell::ShowAlertNotificationWrapper
GeckoAppShell::ShowAlertNotificationWrapper
(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, aAlertName);
}
@@ -555,7 +541,7 @@ AndroidBridge::GetDPI()
const int DEFAULT_DPI = 160;
sDPI = mozilla::widget::android::GeckoAppShell::GetDpiWrapper();
sDPI = GeckoAppShell::GetDpiWrapper();
if (!sDPI) {
return DEFAULT_DPI;
}
@@ -575,7 +561,7 @@ AndroidBridge::GetScreenDepth()
const int DEFAULT_DEPTH = 16;
if (HasEnv()) {
sDepth = mozilla::widget::android::GeckoAppShell::GetScreenDepthWrapper();
sDepth = GeckoAppShell::GetScreenDepthWrapper();
}
if (!sDepth)
return DEFAULT_DEPTH;
@@ -593,10 +579,6 @@ AndroidBridge::Vibrate(const nsTArray<uint32_t>& aPattern)
return;
}
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
// It's clear if this worth special-casing, but it creates less
// java junk, so dodges the GC.
if (len == 1) {
@@ -605,13 +587,16 @@ AndroidBridge::Vibrate(const nsTArray<uint32_t>& aPattern)
ALOG_BRIDGE(" invalid vibration duration < 0");
return;
}
mozilla::widget::android::GeckoAppShell::Vibrate1(d);
GeckoAppShell::Vibrate1(d);
return;
}
// First element of the array vibrate() expects is how long to wait
// *before* vibrating. For us, this is always 0.
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jlongArray array = env->NewLongArray(len + 1);
if (!array) {
ALOG_BRIDGE(" failed to allocate array");
@@ -631,7 +616,7 @@ AndroidBridge::Vibrate(const nsTArray<uint32_t>& aPattern)
}
env->ReleaseLongArrayElements(array, elts, 0);
mozilla::widget::android::GeckoAppShell::VibrateA(array, -1/*don't repeat*/);
GeckoAppShell::VibrateA(LongArray::Ref::From(array), -1 /* don't repeat */);
}
void
@@ -642,16 +627,13 @@ AndroidBridge::GetSystemColors(AndroidSystemColors *aColors)
if (!aColors)
return;
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jintArray arr = mozilla::widget::android::GeckoAppShell::GetSystemColoursWrapper();
auto arr = GeckoAppShell::GetSystemColoursWrapper();
if (!arr)
return;
uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
jint *elements = env->GetIntArrayElements(arr, 0);
JNIEnv* const env = arr.Env();
uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr.Get()));
jint *elements = env->GetIntArrayElements(arr.Get(), 0);
uint32_t colorsCount = sizeof(AndroidSystemColors) / sizeof(nscolor);
if (len < colorsCount)
@@ -667,7 +649,7 @@ AndroidBridge::GetSystemColors(AndroidSystemColors *aColors)
colors[i] = (androidColor & 0xff00ff00) | (b << 16) | r;
}
env->ReleaseIntArrayElements(arr, elements, 0);
env->ReleaseIntArrayElements(arr.Get(), elements, 0);
}
void
@@ -678,30 +660,27 @@ AndroidBridge::GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSiz
if (!aBuf)
return;
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jbyteArray arr = mozilla::widget::android::GeckoAppShell::GetIconForExtensionWrapper
auto arr = GeckoAppShell::GetIconForExtensionWrapper
(NS_ConvertUTF8toUTF16(aFileExt), aIconSize);
NS_ASSERTION(arr != nullptr, "AndroidBridge::GetIconForExtension: Returned pixels array is null!");
if (!arr)
return;
uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
jbyte *elements = env->GetByteArrayElements(arr, 0);
JNIEnv* const env = arr.Env();
uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr.Get()));
jbyte *elements = env->GetByteArrayElements(arr.Get(), 0);
uint32_t bufSize = aIconSize * aIconSize * 4;
NS_ASSERTION(len == bufSize, "AndroidBridge::GetIconForExtension: Pixels array is incomplete!");
if (len == bufSize)
memcpy(aBuf, elements, bufSize);
env->ReleaseByteArrayElements(arr, elements, 0);
env->ReleaseByteArrayElements(arr.Get(), elements, 0);
}
void
AndroidBridge::SetLayerClient(JNIEnv* env, jobject jobj)
AndroidBridge::SetLayerClient(GeckoLayerClient::Param jobj)
{
// if resetting is true, that means Android destroyed our GeckoApp activity
// and we had to recreate it, but all the Gecko-side things were not destroyed.
@@ -709,13 +688,7 @@ AndroidBridge::SetLayerClient(JNIEnv* env, jobject jobj)
// we do here.
bool resetting = (mLayerClient != nullptr);
if (resetting) {
// clear out the old layer client
delete mLayerClient;
mLayerClient = nullptr;
}
mLayerClient = mozilla::widget::android::GeckoLayerClient::Wrap(jobj);
mLayerClient = jobj;
if (resetting) {
// since we are re-linking the new java objects to Gecko, we need to get
@@ -728,17 +701,13 @@ AndroidBridge::SetLayerClient(JNIEnv* env, jobject jobj)
void
AndroidBridge::RegisterCompositor(JNIEnv *env)
{
if (mGLControllerObj != nullptr && !mGLControllerObj->isNull()) {
if (mGLControllerObj != nullptr) {
// we already have this set up, no need to do it again
return;
}
jobject glController = LayerView::RegisterCompositorWrapper();
if (!glController) {
return;
}
mGLControllerObj = GLController::Wrap(glController);
mGLControllerObj = GLController::LocalRef(
LayerView::RegisterCompositorWrapper());
}
EGLSurface
@@ -749,15 +718,14 @@ AndroidBridge::CreateEGLSurfaceForCompositor()
}
MOZ_ASSERT(mGLControllerObj, "AndroidBridge::CreateEGLSurfaceForCompositor called with a null GL controller ref");
JNIEnv* env = GetJNIForThread(); // called on the compositor thread
AutoLocalJNIFrame jniFrame(env, 1);
jobject eglSurface = mGLControllerObj->CreateEGLSurfaceForCompositorWrapper();
if (!eglSurface)
auto eglSurface = mGLControllerObj->CreateEGLSurfaceForCompositorWrapper();
if (!eglSurface) {
return nullptr;
}
EGLSurface ret = reinterpret_cast<EGLSurface>(env->GetIntField(eglSurface, jEGLSurfacePointerField));
return ret;
JNIEnv* const env = GetJNIForThread(); // called on the compositor thread
return reinterpret_cast<EGLSurface>(
env->GetIntField(eglSurface.Get(), jEGLSurfacePointerField));
}
bool
@@ -1007,16 +975,14 @@ AndroidBridge::ValidateBitmap(jobject bitmap, int width, int height)
bool
AndroidBridge::InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps)
{
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jintArray arr = mozilla::widget::android::GeckoAppShell::InitCameraWrapper
auto arr = GeckoAppShell::InitCameraWrapper
(NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) *width, (int32_t) *height);
if (!arr)
return false;
jint *elements = env->GetIntArrayElements(arr, 0);
JNIEnv* const env = arr.Env();
jint *elements = env->GetIntArrayElements(arr.Get(), 0);
*width = elements[1];
*height = elements[2];
@@ -1024,7 +990,7 @@ AndroidBridge::InitCamera(const nsCString& contentType, uint32_t camera, uint32_
bool res = elements[0] == 1;
env->ReleaseIntArrayElements(arr, elements, 0);
env->ReleaseIntArrayElements(arr.Get(), elements, 0);
return res;
}
@@ -1034,24 +1000,22 @@ AndroidBridge::GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInf
{
ALOG_BRIDGE("AndroidBridge::GetCurrentBatteryInformation");
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
// To prevent calling too many methods through JNI, the Java method returns
// an array of double even if we actually want a double and a boolean.
jdoubleArray arr = mozilla::widget::android::GeckoAppShell::GetCurrentBatteryInformationWrapper();
if (!arr || env->GetArrayLength(arr) != 3) {
auto arr = GeckoAppShell::GetCurrentBatteryInformationWrapper();
JNIEnv* const env = arr.Env();
if (!arr || env->GetArrayLength(arr.Get()) != 3) {
return;
}
jdouble* info = env->GetDoubleArrayElements(arr, 0);
jdouble* info = env->GetDoubleArrayElements(arr.Get(), 0);
aBatteryInfo->level() = info[0];
aBatteryInfo->charging() = info[1] == 1.0f;
aBatteryInfo->remainingTime() = info[2];
env->ReleaseDoubleArrayElements(arr, info, 0);
env->ReleaseDoubleArrayElements(arr.Get(), info, 0);
}
void
@@ -1060,9 +1024,8 @@ AndroidBridge::HandleGeckoMessage(JSContext* cx, JS::HandleObject object)
ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
JNIEnv* const env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
const jobject message =
mozilla::widget::CreateNativeJSContainer(env, cx, object);
auto message = Object::LocalRef::Adopt(env,
mozilla::widget::CreateNativeJSContainer(env, cx, object));
GeckoAppShell::HandleGeckoMessageWrapper(message);
}
@@ -1118,7 +1081,7 @@ AndroidBridge::SendMessage(const nsAString& aNumber,
if (!QueueSmsRequest(aRequest, &requestId))
return;
mozilla::widget::android::GeckoAppShell::SendMessageWrapper(aNumber, aMessage, requestId);
GeckoAppShell::SendMessageWrapper(aNumber, aMessage, requestId);
}
void
@@ -1130,7 +1093,7 @@ AndroidBridge::GetMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest
if (!QueueSmsRequest(aRequest, &requestId))
return;
mozilla::widget::android::GeckoAppShell::GetMessageWrapper(aMessageId, requestId);
GeckoAppShell::GetMessageWrapper(aMessageId, requestId);
}
void
@@ -1142,7 +1105,7 @@ AndroidBridge::DeleteMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequ
if (!QueueSmsRequest(aRequest, &requestId))
return;
mozilla::widget::android::GeckoAppShell::DeleteMessageWrapper(aMessageId, requestId);
GeckoAppShell::DeleteMessageWrapper(aMessageId, requestId);
}
void
@@ -1173,7 +1136,8 @@ AndroidBridge::CreateMessageList(const dom::mobilemessage::SmsFilterData& aFilte
int64_t startDate = aFilter.hasStartDate() ? aFilter.startDate() : -1;
int64_t endDate = aFilter.hasEndDate() ? aFilter.endDate() : -1;
GeckoAppShell::CreateMessageListWrapper(startDate, endDate,
numbers, aFilter.numbers().Length(),
ObjectArray::Ref::From(numbers),
aFilter.numbers().Length(),
aFilter.delivery(),
aFilter.hasRead(), aFilter.read(),
aFilter.threadId(),
@@ -1189,7 +1153,7 @@ AndroidBridge::GetNextMessageInList(int32_t aListId, nsIMobileMessageCallback* a
if (!QueueSmsRequest(aRequest, &requestId))
return;
mozilla::widget::android::GeckoAppShell::GetNextMessageInListWrapper(aListId, requestId);
GeckoAppShell::GetNextMessageInListWrapper(aListId, requestId);
}
bool
@@ -1232,25 +1196,23 @@ AndroidBridge::GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInf
{
ALOG_BRIDGE("AndroidBridge::GetCurrentNetworkInformation");
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
// To prevent calling too many methods through JNI, the Java method returns
// an array of double even if we actually want an integer, a boolean, and an integer.
jdoubleArray arr = mozilla::widget::android::GeckoAppShell::GetCurrentNetworkInformationWrapper();
if (!arr || env->GetArrayLength(arr) != 3) {
auto arr = GeckoAppShell::GetCurrentNetworkInformationWrapper();
JNIEnv* const env = arr.Env();
if (!arr || env->GetArrayLength(arr.Get()) != 3) {
return;
}
jdouble* info = env->GetDoubleArrayElements(arr, 0);
jdouble* info = env->GetDoubleArrayElements(arr.Get(), 0);
aNetworkInfo->type() = info[0];
aNetworkInfo->isWifi() = info[1] == 1.0f;
aNetworkInfo->dhcpGateway() = info[2];
env->ReleaseDoubleArrayElements(arr, info, 0);
env->ReleaseDoubleArrayElements(arr.Get(), info, 0);
}
void *
@@ -1258,8 +1220,6 @@ AndroidBridge::LockBitmap(jobject bitmap)
{
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 0);
int err;
void *buf;
@@ -1276,8 +1236,6 @@ AndroidBridge::UnlockBitmap(jobject bitmap)
{
JNIEnv *env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 0);
int err;
if ((err = AndroidBitmap_unlockPixels(env, bitmap)) != 0)
@@ -1420,37 +1378,37 @@ AndroidBridge::LockWindow(void *window, unsigned char **bits, int *width, int *h
jobject
AndroidBridge::GetGlobalContextRef() {
if (sGlobalContext == nullptr) {
JNIEnv *env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 4);
jobject context = mozilla::widget::android::GeckoAppShell::GetContext();
if (!context) {
ALOG_BRIDGE("%s: Could not GetContext()", __FUNCTION__);
return 0;
}
jclass contextClass = env->FindClass("android/content/Context");
if (!contextClass) {
ALOG_BRIDGE("%s: Could not find Context class.", __FUNCTION__);
return 0;
}
jmethodID mid = env->GetMethodID(contextClass, "getApplicationContext",
"()Landroid/content/Context;");
if (!mid) {
ALOG_BRIDGE("%s: Could not find getApplicationContext.", __FUNCTION__);
return 0;
}
jobject appContext = env->CallObjectMethod(context, mid);
if (!appContext) {
ALOG_BRIDGE("%s: getApplicationContext failed.", __FUNCTION__);
return 0;
}
sGlobalContext = env->NewGlobalRef(appContext);
MOZ_ASSERT(sGlobalContext);
if (sGlobalContext) {
return sGlobalContext;
}
JNIEnv* const env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 4);
auto context = GeckoAppShell::GetContext();
if (!context) {
ALOG_BRIDGE("%s: Could not GetContext()", __FUNCTION__);
return 0;
}
jclass contextClass = env->FindClass("android/content/Context");
if (!contextClass) {
ALOG_BRIDGE("%s: Could not find Context class.", __FUNCTION__);
return 0;
}
jmethodID mid = env->GetMethodID(contextClass, "getApplicationContext",
"()Landroid/content/Context;");
if (!mid) {
ALOG_BRIDGE("%s: Could not find getApplicationContext.", __FUNCTION__);
return 0;
}
jobject appContext = env->CallObjectMethod(context.Get(), mid);
if (!appContext) {
ALOG_BRIDGE("%s: getApplicationContext failed.", __FUNCTION__);
return 0;
}
sGlobalContext = env->NewGlobalRef(appContext);
MOZ_ASSERT(sGlobalContext);
return sGlobalContext;
}
@@ -1476,22 +1434,23 @@ AndroidBridge::UnlockWindow(void* window)
void
AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect)
{
mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
if (!client)
if (!mLayerClient) {
return;
}
client->SetFirstPaintViewport((float)aOffset.x, (float)aOffset.y, aZoom.scale,
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
mLayerClient->SetFirstPaintViewport(float(aOffset.x), float(aOffset.y), aZoom.scale,
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
}
void
AndroidBridge::SetPageRect(const CSSRect& aCssPageRect)
{
mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
if (!client)
if (!mLayerClient) {
return;
}
client->SetPageRect(aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
mLayerClient->SetPageRect(aCssPageRect.x, aCssPageRect.y,
aCssPageRect.XMost(), aCssPageRect.YMost());
}
void
@@ -1499,39 +1458,33 @@ AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLay
bool aLayersUpdated, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aScale,
LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
{
mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
if (!client) {
if (!mLayerClient) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
jobject viewTransformJObj = client->SyncViewportInfo(aDisplayPort.x, aDisplayPort.y,
aDisplayPort.width, aDisplayPort.height,
aDisplayResolution.scale, aLayersUpdated);
NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
ViewTransform::LocalRef viewTransform = mLayerClient->SyncViewportInfo(
aDisplayPort.x, aDisplayPort.y,
aDisplayPort.width, aDisplayPort.height,
aDisplayResolution.scale, aLayersUpdated);
if (!viewTransformJObj) {
return;
}
NS_ABORT_IF_FALSE(viewTransform, "No view transform object!");
ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj);
aScrollOffset = ParentLayerPoint(viewTransform->getx(), viewTransform->gety());
aScale.scale = viewTransform->getscale();
aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop();
aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight();
aFixedLayerMargins.bottom = viewTransform->getfixedLayerMarginBottom();
aFixedLayerMargins.left = viewTransform->getfixedLayerMarginLeft();
aOffset.x = viewTransform->getoffsetX();
aOffset.y = viewTransform->getoffsetY();
delete viewTransform;
aScrollOffset = ParentLayerPoint(viewTransform->X(), viewTransform->Y());
aScale.scale = viewTransform->Scale();
aFixedLayerMargins.top = viewTransform->FixedLayerMarginTop();
aFixedLayerMargins.right = viewTransform->FixedLayerMarginRight();
aFixedLayerMargins.bottom = viewTransform->FixedLayerMarginBottom();
aFixedLayerMargins.left = viewTransform->FixedLayerMarginLeft();
aOffset.x = viewTransform->OffsetX();
aOffset.y = viewTransform->OffsetY();
}
void AndroidBridge::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
{
mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
if (!client) {
if (!mLayerClient) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
@@ -1541,26 +1494,21 @@ void AndroidBridge::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, floa
dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset.ToUnknownPoint());
LayerIntRect dp = gfx::RoundedToInt(dpUnrounded);
jobject viewTransformJObj = client->SyncFrameMetrics(aScrollOffset.x, aScrollOffset.y, aZoom,
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale,
aIsFirstPaint);
ViewTransform::LocalRef viewTransform = mLayerClient->SyncFrameMetrics(
aScrollOffset.x, aScrollOffset.y, aZoom,
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale,
aIsFirstPaint);
NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
if (!viewTransformJObj) {
return;
}
ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj);
NS_ABORT_IF_FALSE(viewTransform, "No view transform object!");
aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop();
aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight();
aFixedLayerMargins.bottom = viewTransform->getfixedLayerMarginBottom();
aFixedLayerMargins.left = viewTransform->getfixedLayerMarginLeft();
aFixedLayerMargins.top = viewTransform->FixedLayerMarginTop();
aFixedLayerMargins.right = viewTransform->FixedLayerMarginRight();
aFixedLayerMargins.bottom = viewTransform->FixedLayerMarginBottom();
aFixedLayerMargins.left = viewTransform->FixedLayerMarginLeft();
aOffset.x = viewTransform->getoffsetX();
aOffset.y = viewTransform->getoffsetY();
delete viewTransform;
aOffset.x = viewTransform->OffsetX();
aOffset.y = viewTransform->OffsetY();
}
AndroidBridge::AndroidBridge()
@@ -1664,7 +1612,7 @@ AndroidBridge::GetScreenOrientation()
{
ALOG_BRIDGE("AndroidBridge::GetScreenOrientation");
int16_t orientation = mozilla::widget::android::GeckoAppShell::GetScreenOrientationWrapper();
int16_t orientation = GeckoAppShell::GetScreenOrientationWrapper();
if (!orientation)
return dom::eScreenOrientation_None;
@@ -1688,20 +1636,13 @@ AndroidBridge::GetProxyForURI(const nsACString & aSpec,
if (!HasEnv()) {
return NS_ERROR_FAILURE;
}
JNIEnv* env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
jstring jstrRet =
mozilla::widget::android::GeckoAppShell::GetProxyForURIWrapper(NS_ConvertUTF8toUTF16(aSpec),
NS_ConvertUTF8toUTF16(aScheme),
NS_ConvertUTF8toUTF16(aHost),
aPort);
auto jstrRet = GeckoAppShell::GetProxyForURIWrapper(aSpec, aScheme, aHost, aPort);
if (!jstrRet)
return NS_ERROR_FAILURE;
nsJNIString jniStr(jstrRet, env);
CopyUTF16toUTF8(jniStr, aResult);
aResult = nsCString(jstrRet);
return NS_OK;
}
@@ -1728,8 +1669,8 @@ AndroidBridge::AddPluginView(jobject view, const LayoutDeviceRect& rect, bool is
return;
CSSRect cssRect = rect / win->GetDefaultScale();
mozilla::widget::android::GeckoAppShell::AddPluginViewWrapper(view, cssRect.x, cssRect.y,
cssRect.width, cssRect.height, isFullScreen);
GeckoAppShell::AddPluginViewWrapper(Object::Ref::From(view), cssRect.x, cssRect.y,
cssRect.width, cssRect.height, isFullScreen);
}
extern "C"
@@ -1740,18 +1681,12 @@ Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, j
bool
AndroidBridge::GetThreadNameJavaProfiling(uint32_t aThreadId, nsCString & aResult)
{
JNIEnv* env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 1);
jstring jstrThreadName =
mozilla::widget::android::GeckoJavaSampler::GetThreadNameJavaProfilingWrapper(aThreadId);
auto jstrThreadName = GeckoJavaSampler::GetThreadNameJavaProfilingWrapper(aThreadId);
if (!jstrThreadName)
return false;
nsJNIString jniStr(jstrThreadName, env);
CopyUTF16toUTF8(jniStr.get(), aResult);
aResult = nsCString(jstrThreadName);
return true;
}
@@ -1759,22 +1694,17 @@ bool
AndroidBridge::GetFrameNameJavaProfiling(uint32_t aThreadId, uint32_t aSampleId,
uint32_t aFrameId, nsCString & aResult)
{
JNIEnv* env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 1);
jstring jstrSampleName = mozilla::widget::android::GeckoJavaSampler::GetFrameNameJavaProfilingWrapper
(aThreadId, aSampleId, aFrameId);
auto jstrSampleName = GeckoJavaSampler::GetFrameNameJavaProfilingWrapper
(aThreadId, aSampleId, aFrameId);
if (!jstrSampleName)
return false;
nsJNIString jniStr(jstrSampleName, env);
CopyUTF16toUTF8(jniStr.get(), aResult);
aResult = nsCString(jstrSampleName);
return true;
}
nsresult AndroidBridge::CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, jobject buffer, bool &shouldStore)
nsresult AndroidBridge::CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, Object::Param buffer, bool &shouldStore)
{
nsresult rv;
float scale = 1.0;
@@ -1848,7 +1778,7 @@ nsresult AndroidBridge::CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int
bool is24bit = (GetScreenDepth() == 24);
uint32_t stride = bufW * (is24bit ? 4 : 2);
uint8_t* data = static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
uint8_t* data = static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer.Get()));
if (!data)
return NS_ERROR_FAILURE;
@@ -1882,13 +1812,13 @@ AndroidBridge::GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDispla
{
ALOG_BRIDGE("Enter: %s", __PRETTY_FUNCTION__);
JNIEnv* env = GetJNIEnv();
if (!mLayerClient || mLayerClient->isNull()) {
if (!mLayerClient) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
AutoLocalJNIFrame jniFrame(env, 0);
JNIEnv* const env = GetJNIEnv();
AutoLocalJNIFrame jniFrame(env, 1);
float x, y, width, height,
pageLeft, pageTop, pageRight, pageBottom,
@@ -1908,34 +1838,26 @@ AndroidBridge::GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDispla
metrics->GetCssPageBottom(&cssPageBottom);
metrics->GetZoom(&zoom);
ImmutableViewportMetrics jmetrics = ImmutableViewportMetrics(pageLeft, pageTop, pageRight, pageBottom,
cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
x, y, x + width, y + height,
zoom);
auto jmetrics = ImmutableViewportMetrics::New(
pageLeft, pageTop, pageRight, pageBottom,
cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
x, y, x + width, y + height,
zoom);
jobject jobj = mLayerClient->GetDisplayPort(aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, jmetrics.wrappedObject());
if (!jobj) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
DisplayPortMetrics* displayPortMetrics = DisplayPortMetrics::Wrap(jobj);
DisplayPortMetrics::LocalRef displayPortMetrics = mLayerClient->GetDisplayPort(
aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, jmetrics);
AndroidRectF rect(env, displayPortMetrics->getMPosition());
if (jniFrame.CheckForException()) {
if (!displayPortMetrics) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
float resolution = displayPortMetrics->getResolution();
if (jniFrame.CheckForException()) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return;
}
AndroidRectF rect(env, displayPortMetrics->MPosition().Get());
float resolution = displayPortMetrics->Resolution();
*displayPort = new nsAndroidDisplayport(rect, resolution);
(*displayPort)->AddRef();
delete displayPortMetrics;
ALOG_BRIDGE("Exit: %s", __PRETTY_FUNCTION__);
}
@@ -1958,35 +1880,30 @@ AndroidBridge::IsContentDocumentDisplayed()
}
bool
AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution,
bool aDrawingCritical, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aZoom)
AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
const LayerRect& aDisplayPort, float aDisplayResolution,
bool aDrawingCritical, ParentLayerPoint& aScrollOffset,
CSSToParentLayerScale& aZoom)
{
mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
if (!client) {
if (!mLayerClient) {
ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
return false;
}
jobject progressiveUpdateDataJObj = client->ProgressiveUpdateCallback(aHasPendingNewThebesContent,
(float)aDisplayPort.x,
(float)aDisplayPort.y,
(float)aDisplayPort.width,
(float)aDisplayPort.height,
aDisplayResolution,
!aDrawingCritical);
ProgressiveUpdateData::LocalRef progressiveUpdateData =
mLayerClient->ProgressiveUpdateCallback(aHasPendingNewThebesContent,
(float)aDisplayPort.x,
(float)aDisplayPort.y,
(float)aDisplayPort.width,
(float)aDisplayPort.height,
aDisplayResolution,
!aDrawingCritical);
NS_ABORT_IF_FALSE(progressiveUpdateDataJObj, "No progressive update data!");
aScrollOffset.x = progressiveUpdateData->X();
aScrollOffset.y = progressiveUpdateData->Y();
aZoom.scale = progressiveUpdateData->Scale();
ProgressiveUpdateData* progressiveUpdateData = ProgressiveUpdateData::Wrap(progressiveUpdateDataJObj);
aScrollOffset.x = progressiveUpdateData->getx();
aScrollOffset.y = progressiveUpdateData->gety();
aZoom.scale = progressiveUpdateData->getscale();
bool ret = progressiveUpdateData->getabort();
delete progressiveUpdateData;
return ret;
return progressiveUpdateData->Abort();
}
void
@@ -2040,30 +1957,31 @@ AndroidBridge::RunDelayedUiThreadTasks()
return -1;
}
jobject AndroidBridge::ChannelCreate(jobject stream) {
JNIEnv *env = GetJNIForThread();
env->PushLocalFrame(1);
jobject channel = env->CallStaticObjectMethod(sBridge->jReadableByteChannel, sBridge->jChannelCreate, stream);
return env->PopLocalFrame(channel);
Object::LocalRef AndroidBridge::ChannelCreate(Object::Param stream) {
JNIEnv* const env = GetJNIForThread();
auto rv = Object::LocalRef::Adopt(env, env->CallStaticObjectMethod(
sBridge->jReadableByteChannel, sBridge->jChannelCreate, stream.Get()));
HandleUncaughtException(env);
return rv;
}
void AndroidBridge::InputStreamClose(jobject obj) {
JNIEnv *env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 1);
env->CallVoidMethod(obj, sBridge->jClose);
void AndroidBridge::InputStreamClose(Object::Param obj) {
JNIEnv* const env = GetJNIForThread();
env->CallVoidMethod(obj.Get(), sBridge->jClose);
HandleUncaughtException(env);
}
uint32_t AndroidBridge::InputStreamAvailable(jobject obj) {
JNIEnv *env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 1);
return env->CallIntMethod(obj, sBridge->jAvailable);
uint32_t AndroidBridge::InputStreamAvailable(Object::Param obj) {
JNIEnv* const env = GetJNIForThread();
auto rv = env->CallIntMethod(obj.Get(), sBridge->jAvailable);
HandleUncaughtException(env);
return rv;
}
nsresult AndroidBridge::InputStreamRead(jobject obj, char *aBuf, uint32_t aCount, uint32_t *aRead) {
JNIEnv *env = GetJNIForThread();
AutoLocalJNIFrame jniFrame(env, 1);
jobject arr = env->NewDirectByteBuffer(aBuf, aCount);
jint read = env->CallIntMethod(obj, sBridge->jByteBufferRead, arr);
nsresult AndroidBridge::InputStreamRead(Object::Param obj, char *aBuf, uint32_t aCount, uint32_t *aRead) {
JNIEnv* const env = GetJNIForThread();
auto arr = Object::LocalRef::Adopt(env, env->NewDirectByteBuffer(aBuf, aCount));
jint read = env->CallIntMethod(obj.Get(), sBridge->jByteBufferRead, arr.Get());
if (env->ExceptionCheck()) {
env->ExceptionClear();
@@ -2079,12 +1997,10 @@ nsresult AndroidBridge::InputStreamRead(jobject obj, char *aBuf, uint32_t aCount
}
nsresult AndroidBridge::GetExternalPublicDirectory(const nsAString& aType, nsAString& aPath) {
AutoLocalJNIFrame frame(1);
const jstring path = GeckoAppShell::GetExternalPublicDirectory(aType);
auto path = GeckoAppShell::GetExternalPublicDirectory(aType);
if (!path) {
return NS_ERROR_NOT_AVAILABLE;
}
nsJNIString pathStr(path, frame.GetEnv());
aPath.Assign(pathStr);
aPath = nsString(path);
return NS_OK;
}