Bug 1471408 - Move all top level Java classes into their own file. r=snorp draft
authorTudor-Gabriel Vîjială <tvijiala@mozilla.com>
Wed, 27 Jun 2018 00:02:01 +0100
changeset 811978 ba2f66b19a717eebc098d3a2afeb4afc36718440
parent 811977 6041c030780420b6205cf2d6640513606609884c
push id114438
push userbmo:tvijiala@mozilla.com
push dateThu, 28 Jun 2018 11:58:23 +0000
reviewerssnorp
bugs1471408
milestone63.0a1
Bug 1471408 - Move all top level Java classes into their own file. r=snorp MozReview-Commit-ID: 716FWeZ0q3B
mobile/android/app/build.gradle
mobile/android/app/lint.xml
mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java
mobile/android/base/java/org/mozilla/gecko/VirtualPresentation.java
mobile/android/base/java/org/mozilla/gecko/mdns/DiscoveryListener.java
mobile/android/base/java/org/mozilla/gecko/mdns/DummyMulticastDNSManager.java
mobile/android/base/java/org/mozilla/gecko/mdns/MulticastDNSEventManager.java
mobile/android/base/java/org/mozilla/gecko/mdns/MulticastDNSManager.java
mobile/android/base/java/org/mozilla/gecko/mdns/NsdMulticastDNSManager.java
mobile/android/base/java/org/mozilla/gecko/mdns/RegistrationListener.java
mobile/android/base/java/org/mozilla/gecko/mdns/ResolveListener.java
--- a/mobile/android/app/build.gradle
+++ b/mobile/android/app/build.gradle
@@ -127,16 +127,17 @@ android {
 
                 if (!mozconfig.substs.MOZ_NATIVE_DEVICES) {
                     exclude 'org/mozilla/gecko/ChromeCastDisplay.java'
                     exclude 'org/mozilla/gecko/ChromeCastPlayer.java'
                     exclude 'org/mozilla/gecko/GeckoMediaPlayer.java'
                     exclude 'org/mozilla/gecko/GeckoPresentationDisplay.java'
                     exclude 'org/mozilla/gecko/MediaPlayerManager.java'
                     exclude 'org/mozilla/gecko/RemotePresentationService.java'
+                    exclude 'org/mozilla/gecko/VirtualPresentation.java'
                 }
 
                 if (mozconfig.substs.MOZ_INSTALL_TRACKING) {
                     exclude 'org/mozilla/gecko/adjust/StubAdjustHelper.java'
                 } else {
                     exclude 'org/mozilla/gecko/adjust/AdjustHelper.java'
                 }
 
--- a/mobile/android/app/lint.xml
+++ b/mobile/android/app/lint.xml
@@ -48,16 +48,17 @@
     <issue id="NewApi" severity="error">
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/activitystream/ActivityStreamPreference.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadContentTelemetry.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/preferences/LocaleListPreference.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/media/MediaControlService.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/PrintHelper.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/animation/PropertyAnimator.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java"/>
+        <ignore path="**/mobile/android/base/java/org/mozilla/gecko/VirtualPresentation.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/db/SharedBrowserDatabaseProvider.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/tabs/TabPanelBackButton.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/toolbar/ToolbarEditText.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java"/>
         <ignore path="**/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java"/>
         <ignore path="**/media/webrtc/trunk/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioEffects.java"/>
         <ignore path="**/media/webrtc/trunk/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java"/>
         <ignore path="src/photon/res/values/styles.xml"/>
--- a/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java
@@ -1,45 +1,23 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * vim: ts=4 sw=4 expandtab:
  * 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/. */
 
 package org.mozilla.gecko;
 
-import org.mozilla.gecko.ScreenManagerHelper;
-import org.mozilla.geckoview.GeckoRuntime;
-import org.mozilla.geckoview.GeckoSession;
-import org.mozilla.geckoview.GeckoSessionSettings;
-import org.mozilla.geckoview.GeckoView;
-
-import com.google.android.gms.cast.CastMediaControlIntent;
 import com.google.android.gms.cast.CastPresentation;
 import com.google.android.gms.cast.CastRemoteDisplayLocalService;
-import com.google.android.gms.common.ConnectionResult;
-import com.google.android.gms.common.GooglePlayServicesUtil;
 
-import android.app.Activity;
-import android.content.Context;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v7.media.MediaControlIntent;
-import android.support.v7.media.MediaRouteSelector;
-import android.support.v7.media.MediaRouter.RouteInfo;
-import android.support.v7.media.MediaRouter;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Display;
-import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
-import android.widget.RelativeLayout;
-
-import java.util.HashMap;
-import java.util.Map;
 
 /*
  * Service to keep the remote display running even when the app goes into the background
  */
 public class RemotePresentationService extends CastRemoteDisplayLocalService {
 
     private static final String LOGTAG = "RemotePresentationService";
     private CastPresentation presentation;
@@ -93,55 +71,8 @@ public class RemotePresentationService e
         try {
             presentation.show();
         } catch (WindowManager.InvalidDisplayException ex) {
             Log.e(LOGTAG, "Unable to show presentation, display was removed.", ex);
             dismissPresentation();
         }
     }
 }
-
-class VirtualPresentation extends CastPresentation {
-    private static final String LOGTAG = "VirtualPresentation";
-    private static final String PRESENTATION_VIEW_URI = "chrome://browser/content/PresentationView.xul";
-
-    private RelativeLayout layout;
-    private GeckoView view;
-    private String deviceId;
-    private int screenId;
-
-    public VirtualPresentation(Context context, Display display) {
-        super(context, display);
-    }
-
-    public void setDeviceId(String deviceId) { this.deviceId = deviceId; }
-    public void setScreenId(int screenId) { this.screenId = screenId; }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        /*
-         * NOTICE: The context get from getContext() is different to the context
-         * of the application. Presentaion has its own context to get correct
-         * resources.
-         */
-
-        final GeckoSession session = new GeckoSession();
-        session.getSettings().setString(GeckoSessionSettings.CHROME_URI,
-                                        PRESENTATION_VIEW_URI + "#" + deviceId);
-        session.getSettings().setInt(GeckoSessionSettings.SCREEN_ID, screenId);
-
-        // Create new GeckoView
-        view = new GeckoView(getContext());
-        view.setSession(session, GeckoApplication.ensureRuntime(getContext()));
-        view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
-                                              LayoutParams.MATCH_PARENT));
-
-        // Create new layout to put the GeckoView
-        layout = new RelativeLayout(getContext());
-        layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
-                                                LayoutParams.MATCH_PARENT));
-        layout.addView(view);
-
-        setContentView(layout);
-    }
-}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/VirtualPresentation.java
@@ -0,0 +1,67 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * vim: ts=4 sw=4 expandtab:
+ * 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/. */
+
+package org.mozilla.gecko;
+
+import org.mozilla.geckoview.GeckoSession;
+import org.mozilla.geckoview.GeckoSessionSettings;
+import org.mozilla.geckoview.GeckoView;
+
+import com.google.android.gms.cast.CastPresentation;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.RelativeLayout;
+
+
+class VirtualPresentation extends CastPresentation {
+    private static final String LOGTAG = "VirtualPresentation";
+    private static final String PRESENTATION_VIEW_URI = "chrome://browser/content/PresentationView.xul";
+
+    private RelativeLayout layout;
+    private GeckoView view;
+    private String deviceId;
+    private int screenId;
+
+    public VirtualPresentation(Context context, Display display) {
+        super(context, display);
+    }
+
+    public void setDeviceId(String deviceId) { this.deviceId = deviceId; }
+    public void setScreenId(int screenId) { this.screenId = screenId; }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        /*
+         * NOTICE: The context get from getContext() is different to the context
+         * of the application. Presentaion has its own context to get correct
+         * resources.
+         */
+
+        final GeckoSession session = new GeckoSession();
+        session.getSettings().setString(GeckoSessionSettings.CHROME_URI,
+                PRESENTATION_VIEW_URI + "#" + deviceId);
+        session.getSettings().setInt(GeckoSessionSettings.SCREEN_ID, screenId);
+
+        // Create new GeckoView
+        view = new GeckoView(getContext());
+        view.setSession(session, GeckoApplication.ensureRuntime(getContext()));
+        view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT));
+
+        // Create new layout to put the GeckoView
+        layout = new RelativeLayout(getContext());
+        layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT));
+        layout.addView(view);
+
+        setContentView(layout);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/mdns/DiscoveryListener.java
@@ -0,0 +1,127 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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/. */
+
+package org.mozilla.gecko.mdns;
+
+import org.mozilla.gecko.EventDispatcher;
+import org.mozilla.gecko.util.EventCallback;
+
+import android.annotation.TargetApi;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.util.Log;
+
+@TargetApi(16)
+class DiscoveryListener implements NsdManager.DiscoveryListener {
+    private static final boolean DEBUG = false;
+    private static final String LOGTAG = "GeckoMDNSManager";
+    private final NsdManager nsdManager;
+
+    // Callbacks are called from different thread, and every callback can be called only once.
+    private EventCallback mStartCallback = null;
+    private EventCallback mStopCallback = null;
+
+    DiscoveryListener(final NsdManager nsdManager) {
+        this.nsdManager = nsdManager;
+    }
+
+    public void discoverServices(final String serviceType, final EventCallback callback) {
+        synchronized (this) {
+            mStartCallback = callback;
+        }
+        nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, this);
+    }
+
+    public void stopServiceDiscovery(final EventCallback callback) {
+        synchronized (this) {
+            mStopCallback = callback;
+        }
+        nsdManager.stopServiceDiscovery(this);
+    }
+
+    @Override
+    public synchronized void onDiscoveryStarted(final String serviceType) {
+        if (DEBUG) {
+            Log.d(LOGTAG, "onDiscoveryStarted: " + serviceType);
+        }
+
+        EventCallback callback;
+        synchronized (this) {
+            callback = mStartCallback;
+        }
+
+        if (callback == null) {
+            return;
+        }
+
+        callback.sendSuccess(serviceType);
+    }
+
+    @Override
+    public synchronized void onStartDiscoveryFailed(final String serviceType, final int errorCode) {
+        Log.e(LOGTAG, "onStartDiscoveryFailed: " + serviceType + "(" + errorCode + ")");
+
+        EventCallback callback;
+        synchronized (this) {
+            callback = mStartCallback;
+        }
+
+        callback.sendError(errorCode);
+    }
+
+    @Override
+    public synchronized void onDiscoveryStopped(final String serviceType) {
+        if (DEBUG) {
+            Log.d(LOGTAG, "onDiscoveryStopped: " + serviceType);
+        }
+
+        EventCallback callback;
+        synchronized (this) {
+            callback = mStopCallback;
+        }
+
+        if (callback == null) {
+            return;
+        }
+
+        callback.sendSuccess(serviceType);
+    }
+
+    @Override
+    public synchronized void onStopDiscoveryFailed(final String serviceType, final int errorCode) {
+        Log.e(LOGTAG, "onStopDiscoveryFailed: " + serviceType + "(" + errorCode + ")");
+
+        EventCallback callback;
+        synchronized (this) {
+            callback = mStopCallback;
+        }
+
+        if (callback == null) {
+            return;
+        }
+
+        callback.sendError(errorCode);
+    }
+
+    @Override
+    public void onServiceFound(final NsdServiceInfo serviceInfo) {
+        if (DEBUG) {
+            Log.d(LOGTAG, "onServiceFound: " + serviceInfo.getServiceName());
+        }
+
+        EventDispatcher.getInstance().dispatch(
+                "NsdManager:ServiceFound", NsdMulticastDNSManager.toBundle(serviceInfo));
+    }
+
+    @Override
+    public void onServiceLost(final NsdServiceInfo serviceInfo) {
+        if (DEBUG) {
+            Log.d(LOGTAG, "onServiceLost: " + serviceInfo.getServiceName());
+        }
+
+        EventDispatcher.getInstance().dispatch(
+                "NdManager:ServiceLost", NsdMulticastDNSManager.toBundle(serviceInfo));
+    }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/mdns/DummyMulticastDNSManager.java
@@ -0,0 +1,40 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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/. */
+
+package org.mozilla.gecko.mdns;
+
+import org.mozilla.gecko.util.EventCallback;
+import org.mozilla.gecko.util.GeckoBundle;
+import org.mozilla.gecko.util.BundleEventListener;
+
+import android.util.Log;
+
+class DummyMulticastDNSManager extends MulticastDNSManager implements BundleEventListener {
+    static final int FAILURE_UNSUPPORTED = -65544;
+    private final MulticastDNSEventManager mEventManager;
+
+    public DummyMulticastDNSManager() {
+        mEventManager = new MulticastDNSEventManager(this);
+    }
+
+    @Override
+    public void init() {
+        mEventManager.init();
+    }
+
+    @Override
+    public void tearDown() {
+        mEventManager.tearDown();
+    }
+
+    @Override // BundleEventListener
+    public void handleMessage(final String event, final GeckoBundle message,
+                              final EventCallback callback) {
+        if (DEBUG) {
+            Log.v(LOGTAG, "handleMessage: " + event);
+        }
+        callback.sendError(FAILURE_UNSUPPORTED);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/mdns/MulticastDNSEventManager.java
@@ -0,0 +1,66 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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/. */
+
+package org.mozilla.gecko.mdns;
+
+import org.mozilla.gecko.EventDispatcher;
+import org.mozilla.gecko.util.BundleEventListener;
+import org.mozilla.gecko.util.ThreadUtils;
+
+import android.support.annotation.UiThread;
+
+/**
+ * Mix-in class for MulticastDNSManagers to call EventDispatcher.
+ */
+class MulticastDNSEventManager {
+    private BundleEventListener mListener = null;
+    private boolean mEventsRegistered = false;
+
+    MulticastDNSEventManager(final BundleEventListener listener) {
+        mListener = listener;
+    }
+
+    @UiThread
+    public void init() {
+        ThreadUtils.assertOnUiThread();
+
+        if (mEventsRegistered || mListener == null) {
+            return;
+        }
+
+        registerEvents();
+        mEventsRegistered = true;
+    }
+
+    @UiThread
+    public void tearDown() {
+        ThreadUtils.assertOnUiThread();
+
+        if (!mEventsRegistered || mListener == null) {
+            return;
+        }
+
+        unregisterEvents();
+        mEventsRegistered = false;
+    }
+
+    private void registerEvents() {
+        EventDispatcher.getInstance().registerGeckoThreadListener(mListener,
+                "NsdManager:DiscoverServices",
+                "NsdManager:StopServiceDiscovery",
+                "NsdManager:RegisterService",
+                "NsdManager:UnregisterService",
+                "NsdManager:ResolveService");
+    }
+
+    private void unregisterEvents() {
+        EventDispatcher.getInstance().unregisterGeckoThreadListener(mListener,
+                "NsdManager:DiscoverServices",
+                "NsdManager:StopServiceDiscovery",
+                "NsdManager:RegisterService",
+                "NsdManager:UnregisterService",
+                "NsdManager:ResolveService");
+    }
+}
\ No newline at end of file
--- a/mobile/android/base/java/org/mozilla/gecko/mdns/MulticastDNSManager.java
+++ b/mobile/android/base/java/org/mozilla/gecko/mdns/MulticastDNSManager.java
@@ -1,33 +1,16 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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/. */
 
 package org.mozilla.gecko.mdns;
 
-import org.mozilla.gecko.AppConstants.Versions;
-import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.util.EventCallback;
-import org.mozilla.gecko.util.GeckoBundle;
-import org.mozilla.gecko.util.BundleEventListener;
-import org.mozilla.gecko.util.ThreadUtils;
-
-import android.annotation.TargetApi;
 import android.content.Context;
-import android.net.nsd.NsdManager;
-import android.net.nsd.NsdServiceInfo;
-import android.support.annotation.UiThread;
-import android.util.Log;
-
-import java.net.InetAddress;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This class is the bridge between XPCOM mDNS module and NsdManager.
  *
  * @See nsIDNSServiceDiscovery.idl
  */
 public abstract class MulticastDNSManager {
     protected static final boolean DEBUG = false;
@@ -39,491 +22,8 @@ public abstract class MulticastDNSManage
             instance = new DummyMulticastDNSManager();
         }
         return instance;
     }
 
     public abstract void init();
     public abstract void tearDown();
 }
-
-/**
- * Mix-in class for MulticastDNSManagers to call EventDispatcher.
- */
-class MulticastDNSEventManager {
-    private BundleEventListener mListener = null;
-    private boolean mEventsRegistered = false;
-
-    MulticastDNSEventManager(final BundleEventListener listener) {
-        mListener = listener;
-    }
-
-    @UiThread
-    public void init() {
-        ThreadUtils.assertOnUiThread();
-
-        if (mEventsRegistered || mListener == null) {
-            return;
-        }
-
-        registerEvents();
-        mEventsRegistered = true;
-    }
-
-    @UiThread
-    public void tearDown() {
-        ThreadUtils.assertOnUiThread();
-
-        if (!mEventsRegistered || mListener == null) {
-            return;
-        }
-
-        unregisterEvents();
-        mEventsRegistered = false;
-    }
-
-    private void registerEvents() {
-        EventDispatcher.getInstance().registerGeckoThreadListener(mListener,
-                "NsdManager:DiscoverServices",
-                "NsdManager:StopServiceDiscovery",
-                "NsdManager:RegisterService",
-                "NsdManager:UnregisterService",
-                "NsdManager:ResolveService");
-    }
-
-    private void unregisterEvents() {
-        EventDispatcher.getInstance().unregisterGeckoThreadListener(mListener,
-                "NsdManager:DiscoverServices",
-                "NsdManager:StopServiceDiscovery",
-                "NsdManager:RegisterService",
-                "NsdManager:UnregisterService",
-                "NsdManager:ResolveService");
-    }
-}
-
-class NsdMulticastDNSManager extends MulticastDNSManager implements BundleEventListener {
-    private final NsdManager nsdManager;
-    private final MulticastDNSEventManager mEventManager;
-    private Map<String, DiscoveryListener> mDiscoveryListeners = null;
-    private Map<String, RegistrationListener> mRegistrationListeners = null;
-
-    @TargetApi(16)
-    public NsdMulticastDNSManager(final Context context) {
-        nsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
-        mEventManager = new MulticastDNSEventManager(this);
-        mDiscoveryListeners = new ConcurrentHashMap<String, DiscoveryListener>();
-        mRegistrationListeners = new ConcurrentHashMap<String, RegistrationListener>();
-    }
-
-    @Override
-    public void init() {
-        mEventManager.init();
-    }
-
-    @Override
-    public void tearDown() {
-        mDiscoveryListeners.clear();
-        mRegistrationListeners.clear();
-
-        mEventManager.tearDown();
-    }
-
-    @Override // BundleEventListener
-    public void handleMessage(final String event, final GeckoBundle message,
-                              final EventCallback callback) {
-        if (DEBUG) {
-            Log.v(LOGTAG, "handleMessage: " + event);
-        }
-
-        switch (event) {
-            case "NsdManager:DiscoverServices": {
-                DiscoveryListener listener = new DiscoveryListener(nsdManager);
-                listener.discoverServices(message.getString("serviceType"), callback);
-                mDiscoveryListeners.put(message.getString("uniqueId"), listener);
-                break;
-            }
-            case "NsdManager:StopServiceDiscovery": {
-                String uuid = message.getString("uniqueId");
-                DiscoveryListener listener = mDiscoveryListeners.remove(uuid);
-                if (listener == null) {
-                    Log.e(LOGTAG, "DiscoveryListener " + uuid + " was not found.");
-                    return;
-                }
-                listener.stopServiceDiscovery(callback);
-                break;
-            }
-            case "NsdManager:RegisterService": {
-                RegistrationListener listener = new RegistrationListener(nsdManager);
-                listener.registerService(message.getInt("port"),
-                        message.getString("serviceName", android.os.Build.MODEL),
-                        message.getString("serviceType"),
-                        parseAttributes(message.getBundleArray("attributes")),
-                        callback);
-                mRegistrationListeners.put(message.getString("uniqueId"), listener);
-                break;
-            }
-            case "NsdManager:UnregisterService": {
-                String uuid = message.getString("uniqueId");
-                RegistrationListener listener = mRegistrationListeners.remove(uuid);
-                if (listener == null) {
-                    Log.e(LOGTAG, "RegistrationListener " + uuid + " was not found.");
-                    return;
-                }
-                listener.unregisterService(callback);
-                break;
-            }
-            case "NsdManager:ResolveService": {
-                (new ResolveListener(nsdManager)).resolveService(message.getString("serviceName"),
-                        message.getString("serviceType"),
-                        callback);
-                break;
-            }
-        }
-    }
-
-    private Map<String, String> parseAttributes(final GeckoBundle[] jsobjs) {
-        if (jsobjs == null || jsobjs.length == 0 || !Versions.feature21Plus) {
-            return null;
-        }
-
-        final Map<String, String> attributes = new HashMap<>(jsobjs.length);
-        for (final GeckoBundle obj : jsobjs) {
-            attributes.put(obj.getString("name"), obj.getString("value"));
-        }
-
-        return attributes;
-    }
-
-    @TargetApi(16)
-    public static GeckoBundle toBundle(final NsdServiceInfo serviceInfo) {
-        final GeckoBundle obj = new GeckoBundle();
-
-        final InetAddress host = serviceInfo.getHost();
-        if (host != null) {
-            obj.putString("host", host.getCanonicalHostName());
-            obj.putString("address", host.getHostAddress());
-        }
-
-        int port = serviceInfo.getPort();
-        if (port != 0) {
-            obj.putInt("port", port);
-        }
-
-        final String serviceName = serviceInfo.getServiceName();
-        if (serviceName != null) {
-            obj.putString("serviceName", serviceName);
-        }
-
-        final String serviceType = serviceInfo.getServiceType();
-        if (serviceType != null) {
-            obj.putString("serviceType", serviceType);
-        }
-
-        return obj;
-    }
-}
-
-class DummyMulticastDNSManager extends MulticastDNSManager implements BundleEventListener {
-    static final int FAILURE_UNSUPPORTED = -65544;
-    private final MulticastDNSEventManager mEventManager;
-
-    public DummyMulticastDNSManager() {
-        mEventManager = new MulticastDNSEventManager(this);
-    }
-
-    @Override
-    public void init() {
-        mEventManager.init();
-    }
-
-    @Override
-    public void tearDown() {
-        mEventManager.tearDown();
-    }
-
-    @Override // BundleEventListener
-    public void handleMessage(final String event, final GeckoBundle message,
-                              final EventCallback callback) {
-        if (DEBUG) {
-            Log.v(LOGTAG, "handleMessage: " + event);
-        }
-        callback.sendError(FAILURE_UNSUPPORTED);
-    }
-}
-
-@TargetApi(16)
-class DiscoveryListener implements NsdManager.DiscoveryListener {
-    private static final boolean DEBUG = false;
-    private static final String LOGTAG = "GeckoMDNSManager";
-    private final NsdManager nsdManager;
-
-    // Callbacks are called from different thread, and every callback can be called only once.
-    private EventCallback mStartCallback = null;
-    private EventCallback mStopCallback = null;
-
-    DiscoveryListener(final NsdManager nsdManager) {
-        this.nsdManager = nsdManager;
-    }
-
-    public void discoverServices(final String serviceType, final EventCallback callback) {
-        synchronized (this) {
-            mStartCallback = callback;
-        }
-        nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, this);
-    }
-
-    public void stopServiceDiscovery(final EventCallback callback) {
-        synchronized (this) {
-            mStopCallback = callback;
-        }
-        nsdManager.stopServiceDiscovery(this);
-    }
-
-    @Override
-    public synchronized void onDiscoveryStarted(final String serviceType) {
-        if (DEBUG) {
-            Log.d(LOGTAG, "onDiscoveryStarted: " + serviceType);
-        }
-
-        EventCallback callback;
-        synchronized (this) {
-            callback = mStartCallback;
-        }
-
-        if (callback == null) {
-            return;
-        }
-
-        callback.sendSuccess(serviceType);
-    }
-
-    @Override
-    public synchronized void onStartDiscoveryFailed(final String serviceType, final int errorCode) {
-        Log.e(LOGTAG, "onStartDiscoveryFailed: " + serviceType + "(" + errorCode + ")");
-
-        EventCallback callback;
-        synchronized (this) {
-            callback = mStartCallback;
-        }
-
-        callback.sendError(errorCode);
-    }
-
-    @Override
-    public synchronized void onDiscoveryStopped(final String serviceType) {
-        if (DEBUG) {
-            Log.d(LOGTAG, "onDiscoveryStopped: " + serviceType);
-        }
-
-        EventCallback callback;
-        synchronized (this) {
-            callback = mStopCallback;
-        }
-
-        if (callback == null) {
-            return;
-        }
-
-        callback.sendSuccess(serviceType);
-    }
-
-    @Override
-    public synchronized void onStopDiscoveryFailed(final String serviceType, final int errorCode) {
-        Log.e(LOGTAG, "onStopDiscoveryFailed: " + serviceType + "(" + errorCode + ")");
-
-        EventCallback callback;
-        synchronized (this) {
-            callback = mStopCallback;
-        }
-
-        if (callback == null) {
-            return;
-        }
-
-        callback.sendError(errorCode);
-    }
-
-    @Override
-    public void onServiceFound(final NsdServiceInfo serviceInfo) {
-        if (DEBUG) {
-            Log.d(LOGTAG, "onServiceFound: " + serviceInfo.getServiceName());
-        }
-
-        EventDispatcher.getInstance().dispatch(
-                "NsdManager:ServiceFound", NsdMulticastDNSManager.toBundle(serviceInfo));
-    }
-
-    @Override
-    public void onServiceLost(final NsdServiceInfo serviceInfo) {
-        if (DEBUG) {
-            Log.d(LOGTAG, "onServiceLost: " + serviceInfo.getServiceName());
-        }
-
-        EventDispatcher.getInstance().dispatch(
-                "NdManager:ServiceLost", NsdMulticastDNSManager.toBundle(serviceInfo));
-    }
-}
-
-@TargetApi(16)
-class RegistrationListener implements NsdManager.RegistrationListener {
-    private static final boolean DEBUG = false;
-    private static final String LOGTAG = "GeckoMDNSManager";
-    private final NsdManager nsdManager;
-
-    // Callbacks are called from different thread, and every callback can be called only once.
-    private EventCallback mStartCallback = null;
-    private EventCallback mStopCallback = null;
-
-    RegistrationListener(final NsdManager nsdManager) {
-        this.nsdManager = nsdManager;
-    }
-
-    public void registerService(final int port, final String serviceName, final String serviceType,
-                                final Map<String, String> attributes, final EventCallback callback) {
-        if (DEBUG) {
-            Log.d(LOGTAG, "registerService: " + serviceName + "." + serviceType + ":" + port);
-        }
-
-        NsdServiceInfo serviceInfo = new NsdServiceInfo();
-        serviceInfo.setPort(port);
-        serviceInfo.setServiceName(serviceName);
-        serviceInfo.setServiceType(serviceType);
-        setAttributes(serviceInfo, attributes);
-
-        synchronized (this) {
-            mStartCallback = callback;
-        }
-        nsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, this);
-    }
-
-    @TargetApi(21)
-    private void setAttributes(final NsdServiceInfo serviceInfo, final Map<String, String> attributes) {
-        if (attributes == null || !Versions.feature21Plus) {
-            return;
-        }
-
-        for (Map.Entry<String, String> entry : attributes.entrySet()) {
-            serviceInfo.setAttribute(entry.getKey(), entry.getValue());
-        }
-    }
-
-    public void unregisterService(final EventCallback callback) {
-        if (DEBUG) {
-            Log.d(LOGTAG, "unregisterService");
-        }
-        synchronized (this) {
-            mStopCallback = callback;
-        }
-
-        nsdManager.unregisterService(this);
-    }
-
-    @Override
-    public synchronized void onServiceRegistered(final NsdServiceInfo serviceInfo) {
-        if (DEBUG) {
-            Log.d(LOGTAG, "onServiceRegistered: " + serviceInfo.getServiceName());
-        }
-
-        EventCallback callback;
-        synchronized (this) {
-            callback = mStartCallback;
-        }
-
-        if (callback == null) {
-            return;
-        }
-
-        callback.sendSuccess(NsdMulticastDNSManager.toBundle(serviceInfo));
-    }
-
-    @Override
-    public synchronized void onRegistrationFailed(final NsdServiceInfo serviceInfo, final int errorCode) {
-        Log.e(LOGTAG, "onRegistrationFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")");
-
-        EventCallback callback;
-        synchronized (this) {
-            callback = mStartCallback;
-        }
-
-        callback.sendError(errorCode);
-    }
-
-    @Override
-    public synchronized void onServiceUnregistered(final NsdServiceInfo serviceInfo) {
-        if (DEBUG) {
-            Log.d(LOGTAG, "onServiceUnregistered: " + serviceInfo.getServiceName());
-        }
-
-        EventCallback callback;
-        synchronized (this) {
-            callback = mStopCallback;
-        }
-
-        if (callback == null) {
-            return;
-        }
-
-        callback.sendSuccess(NsdMulticastDNSManager.toBundle(serviceInfo));
-    }
-
-    @Override
-    public synchronized void onUnregistrationFailed(final NsdServiceInfo serviceInfo, final int errorCode) {
-        Log.e(LOGTAG, "onUnregistrationFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")");
-
-        EventCallback callback;
-        synchronized (this) {
-            callback = mStopCallback;
-        }
-
-        if (callback == null) {
-            return;
-        }
-
-        callback.sendError(errorCode);
-    }
-}
-
-@TargetApi(16)
-class ResolveListener implements NsdManager.ResolveListener {
-    private static final boolean DEBUG = false;
-    private static final String LOGTAG = "GeckoMDNSManager";
-    private final NsdManager nsdManager;
-
-    // Callback is called from different thread, and the callback can be called only once.
-    private EventCallback mCallback = null;
-
-    public ResolveListener(final NsdManager nsdManager) {
-        this.nsdManager = nsdManager;
-    }
-
-    public void resolveService(final String serviceName, final String serviceType, final EventCallback callback) {
-        NsdServiceInfo serviceInfo = new NsdServiceInfo();
-        serviceInfo.setServiceName(serviceName);
-        serviceInfo.setServiceType(serviceType);
-
-        mCallback = callback;
-        nsdManager.resolveService(serviceInfo, this);
-    }
-
-
-    @Override
-    public synchronized void onResolveFailed(final NsdServiceInfo serviceInfo, final int errorCode) {
-        Log.e(LOGTAG, "onResolveFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")");
-
-        if (mCallback == null) {
-            return;
-        }
-        mCallback.sendError(errorCode);
-    }
-
-    @Override
-    public synchronized void onServiceResolved(final NsdServiceInfo serviceInfo) {
-        if (DEBUG) {
-            Log.d(LOGTAG, "onServiceResolved: " + serviceInfo.getServiceName());
-        }
-
-        if (mCallback == null) {
-            return;
-        }
-
-        mCallback.sendSuccess(NsdMulticastDNSManager.toBundle(serviceInfo));
-    }
-}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/mdns/NsdMulticastDNSManager.java
@@ -0,0 +1,145 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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/. */
+
+package org.mozilla.gecko.mdns;
+
+import org.mozilla.gecko.AppConstants.Versions;
+import org.mozilla.gecko.util.EventCallback;
+import org.mozilla.gecko.util.GeckoBundle;
+import org.mozilla.gecko.util.BundleEventListener;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+class NsdMulticastDNSManager extends MulticastDNSManager implements BundleEventListener {
+    private final NsdManager nsdManager;
+    private final MulticastDNSEventManager mEventManager;
+    private Map<String, DiscoveryListener> mDiscoveryListeners = null;
+    private Map<String, RegistrationListener> mRegistrationListeners = null;
+
+    @TargetApi(16)
+    public NsdMulticastDNSManager(final Context context) {
+        nsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
+        mEventManager = new MulticastDNSEventManager(this);
+        mDiscoveryListeners = new ConcurrentHashMap<String, DiscoveryListener>();
+        mRegistrationListeners = new ConcurrentHashMap<String, RegistrationListener>();
+    }
+
+    @Override
+    public void init() {
+        mEventManager.init();
+    }
+
+    @Override
+    public void tearDown() {
+        mDiscoveryListeners.clear();
+        mRegistrationListeners.clear();
+
+        mEventManager.tearDown();
+    }
+
+    @Override // BundleEventListener
+    public void handleMessage(final String event, final GeckoBundle message,
+                              final EventCallback callback) {
+        if (DEBUG) {
+            Log.v(LOGTAG, "handleMessage: " + event);
+        }
+
+        switch (event) {
+            case "NsdManager:DiscoverServices": {
+                DiscoveryListener listener = new DiscoveryListener(nsdManager);
+                listener.discoverServices(message.getString("serviceType"), callback);
+                mDiscoveryListeners.put(message.getString("uniqueId"), listener);
+                break;
+            }
+            case "NsdManager:StopServiceDiscovery": {
+                String uuid = message.getString("uniqueId");
+                DiscoveryListener listener = mDiscoveryListeners.remove(uuid);
+                if (listener == null) {
+                    Log.e(LOGTAG, "DiscoveryListener " + uuid + " was not found.");
+                    return;
+                }
+                listener.stopServiceDiscovery(callback);
+                break;
+            }
+            case "NsdManager:RegisterService": {
+                RegistrationListener listener = new RegistrationListener(nsdManager);
+                listener.registerService(message.getInt("port"),
+                        message.getString("serviceName", android.os.Build.MODEL),
+                        message.getString("serviceType"),
+                        parseAttributes(message.getBundleArray("attributes")),
+                        callback);
+                mRegistrationListeners.put(message.getString("uniqueId"), listener);
+                break;
+            }
+            case "NsdManager:UnregisterService": {
+                String uuid = message.getString("uniqueId");
+                RegistrationListener listener = mRegistrationListeners.remove(uuid);
+                if (listener == null) {
+                    Log.e(LOGTAG, "RegistrationListener " + uuid + " was not found.");
+                    return;
+                }
+                listener.unregisterService(callback);
+                break;
+            }
+            case "NsdManager:ResolveService": {
+                (new ResolveListener(nsdManager)).resolveService(message.getString("serviceName"),
+                        message.getString("serviceType"),
+                        callback);
+                break;
+            }
+        }
+    }
+
+    private Map<String, String> parseAttributes(final GeckoBundle[] jsobjs) {
+        if (jsobjs == null || jsobjs.length == 0 || !Versions.feature21Plus) {
+            return null;
+        }
+
+        final Map<String, String> attributes = new HashMap<>(jsobjs.length);
+        for (final GeckoBundle obj : jsobjs) {
+            attributes.put(obj.getString("name"), obj.getString("value"));
+        }
+
+        return attributes;
+    }
+
+    @TargetApi(16)
+    public static GeckoBundle toBundle(final NsdServiceInfo serviceInfo) {
+        final GeckoBundle obj = new GeckoBundle();
+
+        final InetAddress host = serviceInfo.getHost();
+        if (host != null) {
+            obj.putString("host", host.getCanonicalHostName());
+            obj.putString("address", host.getHostAddress());
+        }
+
+        int port = serviceInfo.getPort();
+        if (port != 0) {
+            obj.putInt("port", port);
+        }
+
+        final String serviceName = serviceInfo.getServiceName();
+        if (serviceName != null) {
+            obj.putString("serviceName", serviceName);
+        }
+
+        final String serviceType = serviceInfo.getServiceType();
+        if (serviceType != null) {
+            obj.putString("serviceType", serviceType);
+        }
+
+        return obj;
+    }
+}
+
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/mdns/RegistrationListener.java
@@ -0,0 +1,136 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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/. */
+
+package org.mozilla.gecko.mdns;
+
+import org.mozilla.gecko.AppConstants.Versions;
+
+import org.mozilla.gecko.util.EventCallback;
+
+import android.annotation.TargetApi;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.util.Log;
+
+import java.util.Map;
+
+@TargetApi(16)
+class RegistrationListener implements NsdManager.RegistrationListener {
+    private static final boolean DEBUG = false;
+    private static final String LOGTAG = "GeckoMDNSManager";
+    private final NsdManager nsdManager;
+
+    // Callbacks are called from different thread, and every callback can be called only once.
+    private EventCallback mStartCallback = null;
+    private EventCallback mStopCallback = null;
+
+    RegistrationListener(final NsdManager nsdManager) {
+        this.nsdManager = nsdManager;
+    }
+
+    public void registerService(final int port, final String serviceName, final String serviceType,
+                                final Map<String, String> attributes, final EventCallback callback) {
+        if (DEBUG) {
+            Log.d(LOGTAG, "registerService: " + serviceName + "." + serviceType + ":" + port);
+        }
+
+        NsdServiceInfo serviceInfo = new NsdServiceInfo();
+        serviceInfo.setPort(port);
+        serviceInfo.setServiceName(serviceName);
+        serviceInfo.setServiceType(serviceType);
+        setAttributes(serviceInfo, attributes);
+
+        synchronized (this) {
+            mStartCallback = callback;
+        }
+        nsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, this);
+    }
+
+    @TargetApi(21)
+    private void setAttributes(final NsdServiceInfo serviceInfo, final Map<String, String> attributes) {
+        if (attributes == null || !Versions.feature21Plus) {
+            return;
+        }
+
+        for (Map.Entry<String, String> entry : attributes.entrySet()) {
+            serviceInfo.setAttribute(entry.getKey(), entry.getValue());
+        }
+    }
+
+    public void unregisterService(final EventCallback callback) {
+        if (DEBUG) {
+            Log.d(LOGTAG, "unregisterService");
+        }
+        synchronized (this) {
+            mStopCallback = callback;
+        }
+
+        nsdManager.unregisterService(this);
+    }
+
+    @Override
+    public synchronized void onServiceRegistered(final NsdServiceInfo serviceInfo) {
+        if (DEBUG) {
+            Log.d(LOGTAG, "onServiceRegistered: " + serviceInfo.getServiceName());
+        }
+
+        EventCallback callback;
+        synchronized (this) {
+            callback = mStartCallback;
+        }
+
+        if (callback == null) {
+            return;
+        }
+
+        callback.sendSuccess(NsdMulticastDNSManager.toBundle(serviceInfo));
+    }
+
+    @Override
+    public synchronized void onRegistrationFailed(final NsdServiceInfo serviceInfo, final int errorCode) {
+        Log.e(LOGTAG, "onRegistrationFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")");
+
+        EventCallback callback;
+        synchronized (this) {
+            callback = mStartCallback;
+        }
+
+        callback.sendError(errorCode);
+    }
+
+    @Override
+    public synchronized void onServiceUnregistered(final NsdServiceInfo serviceInfo) {
+        if (DEBUG) {
+            Log.d(LOGTAG, "onServiceUnregistered: " + serviceInfo.getServiceName());
+        }
+
+        EventCallback callback;
+        synchronized (this) {
+            callback = mStopCallback;
+        }
+
+        if (callback == null) {
+            return;
+        }
+
+        callback.sendSuccess(NsdMulticastDNSManager.toBundle(serviceInfo));
+    }
+
+    @Override
+    public synchronized void onUnregistrationFailed(final NsdServiceInfo serviceInfo, final int errorCode) {
+        Log.e(LOGTAG, "onUnregistrationFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")");
+
+        EventCallback callback;
+        synchronized (this) {
+            callback = mStopCallback;
+        }
+
+        if (callback == null) {
+            return;
+        }
+
+        callback.sendError(errorCode);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/mdns/ResolveListener.java
@@ -0,0 +1,60 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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/. */
+
+package org.mozilla.gecko.mdns;
+
+import org.mozilla.gecko.util.EventCallback;
+
+import android.annotation.TargetApi;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.util.Log;
+
+@TargetApi(16)
+class ResolveListener implements NsdManager.ResolveListener {
+    private static final boolean DEBUG = false;
+    private static final String LOGTAG = "GeckoMDNSManager";
+    private final NsdManager nsdManager;
+
+    // Callback is called from different thread, and the callback can be called only once.
+    private EventCallback mCallback = null;
+
+    public ResolveListener(final NsdManager nsdManager) {
+        this.nsdManager = nsdManager;
+    }
+
+    public void resolveService(final String serviceName, final String serviceType, final EventCallback callback) {
+        NsdServiceInfo serviceInfo = new NsdServiceInfo();
+        serviceInfo.setServiceName(serviceName);
+        serviceInfo.setServiceType(serviceType);
+
+        mCallback = callback;
+        nsdManager.resolveService(serviceInfo, this);
+    }
+
+
+    @Override
+    public synchronized void onResolveFailed(final NsdServiceInfo serviceInfo, final int errorCode) {
+        Log.e(LOGTAG, "onResolveFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")");
+
+        if (mCallback == null) {
+            return;
+        }
+        mCallback.sendError(errorCode);
+    }
+
+    @Override
+    public synchronized void onServiceResolved(final NsdServiceInfo serviceInfo) {
+        if (DEBUG) {
+            Log.d(LOGTAG, "onServiceResolved: " + serviceInfo.getServiceName());
+        }
+
+        if (mCallback == null) {
+            return;
+        }
+
+        mCallback.sendSuccess(NsdMulticastDNSManager.toBundle(serviceInfo));
+    }
+}