Bug 1257319 - Add notifyObservers methods to GeckoAppShell; r=snorp
☠☠ backed out by 7970a7b7e8e9 ☠ ☠
authorJim Chen <nchen@mozilla.com>
Tue, 22 Mar 2016 22:24:31 -0400
changeset 290022 0b0b229e5968956b237f74013b44c54bd07d6a36
parent 290021 8ba88b6c9d7da8bd80b40811b051c8333c60a921
child 290023 bba3d09859d65d4123d912878b4a0d2ac776c252
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1257319
milestone48.0a1
Bug 1257319 - Add notifyObservers methods to GeckoAppShell; r=snorp Add notifyObservers and the synchronous syncNotifyObservers methods to GeckoAppShell to replace the BROADCAST event.
mobile/android/base/java/org/mozilla/gecko/GeckoAppShell.java
widget/android/nsAppShell.cpp
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoAppShell.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoAppShell.java
@@ -376,17 +376,35 @@ public class GeckoAppShell
 
         sendEventToGecko(GeckoEvent.createBroadcastEvent(request.getName(), request.getData()));
     }
 
     // Tell the Gecko event loop that an event is available.
     public static native void notifyGeckoOfEvent(GeckoEvent event);
 
     // Synchronously notify a Gecko observer; must be called from Gecko thread.
-    public static native void notifyGeckoObservers(String subject, String data);
+    @WrapForJNI
+    public static native void syncNotifyObservers(String topic, String data);
+
+    @WrapForJNI(stubName = "NotifyObservers")
+    private static native void nativeNotifyObservers(String topic, String data);
+
+    public static void notifyObservers(final String topic, final String data) {
+        notifyObservers(topic, data, GeckoThread.State.RUNNING);
+    }
+
+    public static void notifyObservers(final String topic, final String data, final GeckoThread.State state) {
+        if (GeckoThread.isStateAtLeast(state)) {
+            nativeNotifyObservers(topic, data);
+        } else {
+            GeckoThread.queueNativeCallUntil(
+                    state, GeckoAppShell.class, "nativeNotifyObservers",
+                    String.class, topic, String.class, data);
+        }
+    }
 
     /*
      *  The Gecko-side API: API methods that Gecko calls
      */
 
     @WrapForJNI(allowMultithread = true, noThrow = true)
     public static String handleUncaughtException(Throwable e) {
         if (AppConstants.MOZ_CRASHREPORTER) {
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -179,16 +179,54 @@ public:
         nsCOMPtr<nsIURI> uri = ResolveURI(uriStr->ToCString());
         if (!uri) {
             return;
         }
         specConn->SpeculativeConnect(uri, nullptr);
     }
 };
 
+class GeckoAppShellSupport final
+    : public widget::GeckoAppShell::Natives<GeckoAppShellSupport>
+    , public UsesGeckoThreadProxy
+{
+public:
+    template<typename Functor>
+    static void OnNativeCall(Functor&& aCall)
+    {
+        if (aCall.IsTarget(&SyncNotifyObservers)) {
+            aCall();
+            return;
+        }
+        return UsesGeckoThreadProxy::OnNativeCall(aCall);
+    }
+
+    static void SyncNotifyObservers(jni::String::Param aTopic,
+                                    jni::String::Param aData)
+    {
+        MOZ_RELEASE_ASSERT(NS_IsMainThread());
+        NotifyObservers(aTopic, aData);
+    }
+
+    static void NotifyObservers(jni::String::Param aTopic,
+                                jni::String::Param aData)
+    {
+        MOZ_ASSERT(NS_IsMainThread());
+        MOZ_ASSERT(aTopic);
+
+        nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
+        if (!obsServ) {
+            return;
+        }
+
+        obsServ->NotifyObservers(nullptr, aTopic->ToCString().get(),
+                                 aData ? aData->ToString().get() : nullptr);
+    }
+};
+
 nsAppShell::nsAppShell()
     : mSyncRunFinished(*(sAppShellLock = new Mutex("nsAppShell")),
                        "nsAppShell.SyncRun")
     , mSyncRunQuit(false)
 {
     {
         MutexAutoLock lock(*sAppShellLock);
         sAppShell = this;
@@ -196,16 +234,17 @@ nsAppShell::nsAppShell()
 
     if (!XRE_IsParentProcess()) {
         return;
     }
 
     if (jni::IsAvailable()) {
         // Initialize JNI and Set the corresponding state in GeckoThread.
         AndroidBridge::ConstructBridge();
+        GeckoAppShellSupport::Init();
         GeckoThreadNatives::Init();
         mozilla::ANRReporter::Init();
         mozilla::PrefsHelper::Init();
         nsWindow::InitNatives();
 
         widget::GeckoThread::SetState(widget::GeckoThread::State::JNI_READY());
     }