From c08786522e3fefdae91b6090d4ef132318872d72 Mon Sep 17 00:00:00 2001 From: Brad Lassey Date: Mon, 17 Jun 2013 17:09:09 -0400 Subject: [PATCH] bug 882196 - Android crash in nsXPCWrappedJS::AddRef, remove nsAppShell::NotifyObservers r=kats --- mobile/android/base/GeckoAppShell.java | 2 - .../base/GeckoConnectivityReceiver.java | 2 +- mobile/android/base/GeckoEvent.java | 16 ++++- mobile/android/base/MemoryMonitor.java | 4 +- mozglue/android/jni-stubs.inc | 38 ------------ widget/android/AndroidJNI.cpp | 24 -------- widget/android/AndroidJavaWrappers.cpp | 10 ++++ widget/android/AndroidJavaWrappers.h | 11 ++++ widget/android/nsAppShell.cpp | 58 ++++++++----------- widget/android/nsAppShell.h | 1 - 10 files changed, 64 insertions(+), 102 deletions(-) diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 5fdcb9bfb1e1..2a5e2335688b 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -171,12 +171,10 @@ public class GeckoAppShell // public static native void setSurfaceView(GeckoSurfaceView sv); public static native void setLayerClient(GeckoLayerClient client); public static native void onResume(); - public static native void onLowMemory(); public static void callObserver(String observerKey, String topic, String data) { sendEventToGecko(GeckoEvent.createCallObserverEvent(observerKey, topic, data)); } public static native void removeObserver(String observerKey); - public static native void onChangeNetworkLinkStatus(String status); public static native Message getNextMessageFromQueue(MessageQueue queue); public static native void onSurfaceTextureFrameAvailable(Object surfaceTexture, int id); diff --git a/mobile/android/base/GeckoConnectivityReceiver.java b/mobile/android/base/GeckoConnectivityReceiver.java index 24f37c7a57c9..8c9d1b19ca1a 100644 --- a/mobile/android/base/GeckoConnectivityReceiver.java +++ b/mobile/android/base/GeckoConnectivityReceiver.java @@ -76,7 +76,7 @@ public class GeckoConnectivityReceiver extends BroadcastReceiver { } if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) { - GeckoAppShell.onChangeNetworkLinkStatus(status); + GeckoAppShell.sendEventToGecko(GeckoEvent.createNetworkLinkChangeEvent(status)); } } } diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index 66fc3155f62f..710a6e9ce051 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -63,7 +63,9 @@ public class GeckoEvent { COMPOSITOR_RESUME(30), NATIVE_GESTURE_EVENT(31), IME_KEY_EVENT(32), - CALL_OBSERVER(33); + CALL_OBSERVER(33), + LOW_MEMORY(34), + NETWORK_LINK_CHANGE(35); public final int value; @@ -667,6 +669,18 @@ public class GeckoEvent { return event; } + public static GeckoEvent createLowMemoryEvent(int level) { + GeckoEvent event = new GeckoEvent(NativeGeckoEvent.LOW_MEMORY); + event.mMetaState = level; + return event; + } + + public static GeckoEvent createNetworkLinkChangeEvent(String status) { + GeckoEvent event = new GeckoEvent(NativeGeckoEvent.NETWORK_LINK_CHANGE); + event.mCharacters = status; + return event; + } + public void setAckNeeded(boolean ackNeeded) { mAckNeeded = ackNeeded; } diff --git a/mobile/android/base/MemoryMonitor.java b/mobile/android/base/MemoryMonitor.java index 313832c915ce..e728ac716261 100644 --- a/mobile/android/base/MemoryMonitor.java +++ b/mobile/android/base/MemoryMonitor.java @@ -39,6 +39,7 @@ class MemoryMonitor extends BroadcastReceiver { private static final String ACTION_MEMORY_DUMP = "org.mozilla.gecko.MEMORY_DUMP"; private static final String ACTION_FORCE_PRESSURE = "org.mozilla.gecko.FORCE_MEMORY_PRESSURE"; + // Memory pressue levels, keep in sync with those in AndroidJavaWrappers.h private static final int MEMORY_PRESSURE_NONE = 0; private static final int MEMORY_PRESSURE_CLEANUP = 1; private static final int MEMORY_PRESSURE_LOW = 2; @@ -148,8 +149,9 @@ class MemoryMonitor extends BroadcastReceiver { // TODO hook in memory-reduction stuff for different levels here if (level >= MEMORY_PRESSURE_MEDIUM) { + //Only send medium or higher events because that's all that is used right now if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) { - GeckoAppShell.onLowMemory(); + GeckoAppShell.sendEventToGecko(GeckoEvent.createLowMemoryEvent(level)); } Favicons.getInstance().clearMemCache(); diff --git a/mozglue/android/jni-stubs.inc b/mozglue/android/jni-stubs.inc index 14b7a92791dc..b425e6dfd5e2 100644 --- a/mozglue/android/jni-stubs.inc +++ b/mozglue/android/jni-stubs.inc @@ -58,25 +58,6 @@ Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv * arg0, jclass arg1) { #ifdef JNI_STUBS -typedef void (*Java_org_mozilla_gecko_GeckoAppShell_onLowMemory_t)(JNIEnv *, jclass); -static Java_org_mozilla_gecko_GeckoAppShell_onLowMemory_t f_Java_org_mozilla_gecko_GeckoAppShell_onLowMemory; -extern "C" NS_EXPORT void JNICALL -Java_org_mozilla_gecko_GeckoAppShell_onLowMemory(JNIEnv * arg0, jclass arg1) { - if (!f_Java_org_mozilla_gecko_GeckoAppShell_onLowMemory) { - arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"), - "JNI Function called before it was loaded"); - return ; - } - f_Java_org_mozilla_gecko_GeckoAppShell_onLowMemory(arg0, arg1); -} -#endif - -#ifdef JNI_BINDINGS - xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_onLowMemory", &f_Java_org_mozilla_gecko_GeckoAppShell_onLowMemory); -#endif - -#ifdef JNI_STUBS - typedef void (*Java_org_mozilla_gecko_GeckoAppShell_removeObserver_t)(JNIEnv *, jclass, jstring); static Java_org_mozilla_gecko_GeckoAppShell_removeObserver_t f_Java_org_mozilla_gecko_GeckoAppShell_removeObserver; extern "C" NS_EXPORT void JNICALL @@ -96,25 +77,6 @@ Java_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv * arg0, jclass arg1, #ifdef JNI_STUBS -typedef void (*Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus_t)(JNIEnv *, jclass, jstring); -static Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus_t f_Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus; -extern "C" NS_EXPORT void JNICALL -Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv * arg0, jclass arg1, jstring arg2) { - if (!f_Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus) { - arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"), - "JNI Function called before it was loaded"); - return ; - } - f_Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(arg0, arg1, arg2); -} -#endif - -#ifdef JNI_BINDINGS - xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus", &f_Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus); -#endif - -#ifdef JNI_STUBS - typedef jobject (*Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue_t)(JNIEnv *, jclass, jobject); static Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue_t f_Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue; extern "C" NS_EXPORT jobject JNICALL diff --git a/widget/android/AndroidJNI.cpp b/widget/android/AndroidJNI.cpp index a0c089ac8161..ccf3c26895fc 100644 --- a/widget/android/AndroidJNI.cpp +++ b/widget/android/AndroidJNI.cpp @@ -22,7 +22,6 @@ #include #include "nsIObserverService.h" #include "mozilla/Services.h" -#include "nsINetworkLinkService.h" #ifdef MOZ_CRASHREPORTER #include "nsICrashReporter.h" @@ -84,16 +83,6 @@ Java_org_mozilla_gecko_GeckoAppShell_setLayerClient(JNIEnv *jenv, jclass, jobjec AndroidBridge::Bridge()->SetLayerClient(jenv, obj); } -NS_EXPORT void JNICALL -Java_org_mozilla_gecko_GeckoAppShell_onLowMemory(JNIEnv *jenv, jclass jc) -{ - if (nsAppShell::gAppShell) { - nsAppShell::gAppShell->NotifyObservers(nullptr, - "memory-pressure", - NS_LITERAL_STRING("low-memory").get()); - } -} - NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *jenv, jclass jc) { @@ -115,19 +104,6 @@ Java_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv *jenv, jclass, jstrin nsAppShell::gAppShell->RemoveObserver(sObserverKey); } -NS_EXPORT void JNICALL -Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv *jenv, jclass, jstring jStatus) -{ - if (!nsAppShell::gAppShell) - return; - - nsJNIString sStatus(jStatus, jenv); - - nsAppShell::gAppShell->NotifyObservers(nullptr, - NS_NETWORK_LINK_TOPIC, - sStatus.get()); -} - NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *jenv, jclass, jstring jStackTrace) { diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index 20b182bef806..40276ced372c 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -690,6 +690,16 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) break; } + case LOW_MEMORY: { + mMetaState = jenv->GetIntField(jobj, jMetaStateField); + break; + } + + case NETWORK_LINK_CHANGE: { + ReadCharactersField(jenv); + break; + } + default: break; } diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index daee5c53eaad..751182f44dd6 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -707,9 +707,20 @@ public: NATIVE_GESTURE_EVENT = 31, IME_KEY_EVENT = 32, CALL_OBSERVER = 33, + LOW_MEMORY = 34, + NETWORK_LINK_CHANGE = 35, dummy_java_enum_list_end }; + enum { + // Memory pressue levels, keep in sync with those in MemoryMonitor.java + MEMORY_PRESSURE_NONE = 0, + MEMORY_PRESSURE_CLEANUP = 1, + MEMORY_PRESSURE_LOW = 2, + MEMORY_PRESSURE_MEDIUM = 3, + MEMORY_PRESSURE_HIGH = 4 + }; + enum { // Internal Gecko events IME_FLUSH_CHANGES = -2, diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp index 37325235fe3f..6e088feee411 100644 --- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -25,6 +25,7 @@ #include "nsIDOMWakeLockListener.h" #include "nsIPowerManagerService.h" #include "nsFrameManager.h" +#include "nsINetworkLinkService.h" #include "mozilla/Services.h" #include "mozilla/unused.h" @@ -522,6 +523,29 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait) CallObserver(curEvent->Characters(), curEvent->CharactersExtra(), curEvent->Data()); break; + case AndroidGeckoEvent::LOW_MEMORY: + // TODO hook in memory-reduction stuff for different levels here + if (curEvent->MetaState() >= AndroidGeckoEvent::MEMORY_PRESSURE_MEDIUM) { + nsCOMPtr os = mozilla::services::GetObserverService(); + if (os) { + os->NotifyObservers(nullptr, + "memory-pressure", + NS_LITERAL_STRING("low-memory").get()); + } + } + break; + + case AndroidGeckoEvent::NETWORK_LINK_CHANGE: + { + nsCOMPtr os = mozilla::services::GetObserverService(); + if (os) { + os->NotifyObservers(nullptr, + NS_NETWORK_LINK_TOPIC, + nsString(curEvent->Characters()).get()); + } + break; + } + case AndroidGeckoEvent::NOOP: break; @@ -736,40 +760,6 @@ nsAppShell::RemoveObserver(const nsAString &aObserverKey) mObserversHash.Remove(aObserverKey); } -// NotifyObservers support. NotifyObservers only works on main thread. - -class NotifyObserversCaller : public nsRunnable { -public: - NotifyObserversCaller(nsISupports *aSupports, - const char *aTopic, const PRUnichar *aData) : - mSupports(aSupports), mTopic(aTopic), mData(aData) { - } - - NS_IMETHOD Run() { - nsCOMPtr os = mozilla::services::GetObserverService(); - if (os) - os->NotifyObservers(mSupports, mTopic.get(), mData.get()); - - return NS_OK; - } - -private: - nsCOMPtr mSupports; - nsCString mTopic; - nsString mData; -}; - -void -nsAppShell::NotifyObservers(nsISupports *aSupports, - const char *aTopic, - const PRUnichar *aData) -{ - // This isn't main thread, so post this to main thread - nsCOMPtr caller = - new NotifyObserversCaller(aSupports, aTopic, aData); - NS_DispatchToMainThread(caller); -} - // Used by IPC code namespace mozilla { diff --git a/widget/android/nsAppShell.h b/widget/android/nsAppShell.h index d944e605f3cd..11451c690ab3 100644 --- a/widget/android/nsAppShell.h +++ b/widget/android/nsAppShell.h @@ -49,7 +49,6 @@ public: nsresult AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver); void CallObserver(const nsAString &aObserverKey, const nsAString &aTopic, const nsAString &aData); void RemoveObserver(const nsAString &aObserverKey); - void NotifyObservers(nsISupports *aSupports, const char *aTopic, const PRUnichar *aData); void ResendLastResizeEvent(nsWindow* aDest); void SetBrowserApp(nsIAndroidBrowserApp* aBrowserApp) {