From 1bcd51a8b8a12febccc6333cedfb19ebbfd779f4 Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Fri, 4 Apr 2014 12:33:49 -0400 Subject: [PATCH] Bug 989046 - a. Convert Gecko side messaging to use NativeJSContainer; r=blassey --- mobile/android/base/GeckoAppShell.java | 6 ++- widget/android/AndroidBridge.cpp | 49 ++++++++++++++++++++++--- widget/android/AndroidBridge.h | 4 +- widget/android/GeneratedJNIWrappers.cpp | 8 ++-- widget/android/GeneratedJNIWrappers.h | 2 +- widget/android/nsIAndroidBridge.idl | 4 +- 6 files changed, 55 insertions(+), 18 deletions(-) diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index e405b49a029c..559e017cbb3b 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -45,6 +45,7 @@ import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI; import org.mozilla.gecko.prompts.PromptService; import org.mozilla.gecko.util.GeckoEventListener; import org.mozilla.gecko.util.HardwareUtils; +import org.mozilla.gecko.util.NativeJSContainer; import org.mozilla.gecko.util.ProxySelector; import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.gecko.webapp.Allocator; @@ -2287,8 +2288,9 @@ public class GeckoAppShell } @WrapElementForJNI(stubName = "HandleGeckoMessageWrapper") - public static void handleGeckoMessage(String message) { - sEventDispatcher.dispatchEvent(message); + public static void handleGeckoMessage(final NativeJSContainer message) { + sEventDispatcher.dispatchEvent(message.toString()); + message.dispose(); } @WrapElementForJNI diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index 410c6f5fe919..4541ce369944 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -37,6 +37,9 @@ #include "StrongPointer.h" #include "mozilla/ClearOnShutdown.h" #include "nsPrintfCString.h" +#include "NativeJSContainer.h" +#include "nsContentUtils.h" +#include "nsIScriptError.h" using namespace mozilla; using namespace mozilla::widget::android; @@ -967,14 +970,15 @@ AndroidBridge::GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInf } void -AndroidBridge::HandleGeckoMessage(const nsAString &aMessage) +AndroidBridge::HandleGeckoMessage(JSContext* cx, JS::HandleObject object) { ALOG_BRIDGE("%s", __PRETTY_FUNCTION__); - JNIEnv *env = GetJNIEnv(); - + JNIEnv* const env = GetJNIEnv(); AutoLocalJNIFrame jniFrame(env, 1); - mozilla::widget::android::GeckoAppShell::HandleGeckoMessageWrapper(aMessage); + const jobject message = + mozilla::widget::CreateNativeJSContainer(env, cx, object); + GeckoAppShell::HandleGeckoMessageWrapper(message); } nsresult @@ -1494,9 +1498,42 @@ nsAndroidBridge::~nsAndroidBridge() } /* void handleGeckoEvent (in AString message); */ -NS_IMETHODIMP nsAndroidBridge::HandleGeckoMessage(const nsAString & message) +NS_IMETHODIMP nsAndroidBridge::HandleGeckoMessage(JS::HandleValue val, + JSContext *cx) { - AndroidBridge::Bridge()->HandleGeckoMessage(message); + if (val.isObject()) { + JS::RootedObject object(cx, &val.toObject()); + AndroidBridge::Bridge()->HandleGeckoMessage(cx, object); + return NS_OK; + } + + // Now handle legacy JSON messages. + if (!val.isString()) { + return NS_ERROR_INVALID_ARG; + } + JS::RootedString jsonStr(cx, val.toString()); + + size_t strLen = 0; + const jschar* strChar = JS_GetStringCharsAndLength(cx, jsonStr, &strLen); + if (!strChar) { + return NS_ERROR_UNEXPECTED; + } + + JS::RootedValue jsonVal(cx); + if (!JS_ParseJSON(cx, strChar, strLen, &jsonVal) || !jsonVal.isObject()) { + return NS_ERROR_INVALID_ARG; + } + + // Spit out a warning before sending the message. + nsContentUtils::ReportToConsoleNonLocalized( + NS_LITERAL_STRING("Use of JSON is deprecated. " + "Please pass Javascript objects directly to handleGeckoMessage."), + nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("nsIAndroidBridge"), + nullptr); + + JS::RootedObject object(cx, &jsonVal.toObject()); + AndroidBridge::Bridge()->HandleGeckoMessage(cx, object); return NS_OK; } diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 4154b58f5ecb..437455321cda 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -279,8 +279,8 @@ public: bool LockWindow(void *window, unsigned char **bits, int *width, int *height, int *format, int *stride); bool UnlockWindow(void *window); - - void HandleGeckoMessage(const nsAString& message); + + void HandleGeckoMessage(JSContext* cx, JS::HandleObject message); bool InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps); diff --git a/widget/android/GeneratedJNIWrappers.cpp b/widget/android/GeneratedJNIWrappers.cpp index 6d0cbe5a0c0e..6159272b0875 100644 --- a/widget/android/GeneratedJNIWrappers.cpp +++ b/widget/android/GeneratedJNIWrappers.cpp @@ -129,7 +129,7 @@ void GeckoAppShell::InitStubs(JNIEnv *jEnv) { jGetScreenOrientationWrapper = getStaticMethod("getScreenOrientation", "()S"); jGetShowPasswordSetting = getStaticMethod("getShowPasswordSetting", "()Z"); jGetSystemColoursWrapper = getStaticMethod("getSystemColors", "()[I"); - jHandleGeckoMessageWrapper = getStaticMethod("handleGeckoMessage", "(Ljava/lang/String;)V"); + jHandleGeckoMessageWrapper = getStaticMethod("handleGeckoMessage", "(Lorg/mozilla/gecko/util/NativeJSContainer;)V"); jHandleUncaughtException = getStaticMethod("handleUncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V"); jHideProgressDialog = getStaticMethod("hideProgressDialog", "()V"); jInitCameraWrapper = getStaticMethod("initCamera", "(Ljava/lang/String;III)[I"); @@ -697,16 +697,14 @@ jintArray GeckoAppShell::GetSystemColoursWrapper() { return ret; } -void GeckoAppShell::HandleGeckoMessageWrapper(const nsAString& a0) { +void GeckoAppShell::HandleGeckoMessageWrapper(jobject a0) { JNIEnv *env = AndroidBridge::GetJNIEnv(); if (env->PushLocalFrame(1) != 0) { AndroidBridge::HandleUncaughtException(env); MOZ_ASSUME_UNREACHABLE("Exception should have caused crash."); } - jstring j0 = AndroidBridge::NewJavaString(env, a0); - - env->CallStaticVoidMethod(mGeckoAppShellClass, jHandleGeckoMessageWrapper, j0); + env->CallStaticVoidMethod(mGeckoAppShellClass, jHandleGeckoMessageWrapper, a0); AndroidBridge::HandleUncaughtException(env); env->PopLocalFrame(nullptr); } diff --git a/widget/android/GeneratedJNIWrappers.h b/widget/android/GeneratedJNIWrappers.h index fe3e28e37f84..79ecd2c066bc 100644 --- a/widget/android/GeneratedJNIWrappers.h +++ b/widget/android/GeneratedJNIWrappers.h @@ -57,7 +57,7 @@ public: static int16_t GetScreenOrientationWrapper(); static bool GetShowPasswordSetting(); static jintArray GetSystemColoursWrapper(); - static void HandleGeckoMessageWrapper(const nsAString& a0); + static void HandleGeckoMessageWrapper(jobject a0); static void HandleUncaughtException(jobject a0, jthrowable a1); static void HideProgressDialog(); static jintArray InitCameraWrapper(const nsAString& a0, int32_t a1, int32_t a2, int32_t a3); diff --git a/widget/android/nsIAndroidBridge.idl b/widget/android/nsIAndroidBridge.idl index 82bbd89c3dc6..ae84a842db35 100644 --- a/widget/android/nsIAndroidBridge.idl +++ b/widget/android/nsIAndroidBridge.idl @@ -63,10 +63,10 @@ interface nsIAndroidDisplayport : nsISupports { attribute float resolution; }; -[scriptable, uuid(2af84552-4f74-480d-b637-ce2bcd7148fc)] +[scriptable, uuid(1beb70d3-70f3-4742-98cc-a3d301b26c0c)] interface nsIAndroidBridge : nsISupports { - void handleGeckoMessage(in AString message); + [implicit_jscontext] void handleGeckoMessage(in jsval message); attribute nsIAndroidBrowserApp browserApp; nsIAndroidDisplayport getDisplayPort(in boolean aPageSizeUpdate, in boolean isBrowserContentDisplayed, in int32_t tabId, in nsIAndroidViewport metrics); void contentDocumentChanged();