Bug 1401002 - [2.2] Enable GeckoView remote debugging. r=snorp,jchen
authorEugen Sawin <esawin@mozilla.com>
Mon, 18 Sep 2017 14:44:20 +0200
changeset 383198 cbc29f3fed8860014a4bd9b77a0f4a68202c3457
parent 383197 505c1e22424aa59809ccf33cec9bf1d20d784c2a
child 383199 f5249f8de8da6e80cf442ffa04c3a71d42fa4111
push id52137
push userarchaeopteryx@coole-files.de
push dateWed, 27 Sep 2017 09:50:17 +0000
treeherderautoland@f4c8f9555488 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp, jchen
bugs1401002
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1401002 - [2.2] Enable GeckoView remote debugging. r=snorp,jchen
mobile/android/chrome/geckoview/geckoview.js
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewSettings.java
mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
mobile/android/installer/package-manifest.in
mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
mobile/android/modules/geckoview/GeckoViewTab.jsm
mobile/android/modules/geckoview/moz.build
--- a/mobile/android/chrome/geckoview/geckoview.js
+++ b/mobile/android/chrome/geckoview/geckoview.js
@@ -59,13 +59,15 @@ function startup() {
   ModuleManager.add("resource://gre/modules/GeckoViewContent.jsm",
                     "GeckoViewContent");
   ModuleManager.add("resource://gre/modules/GeckoViewProgress.jsm",
                     "GeckoViewProgress");
   ModuleManager.add("resource://gre/modules/GeckoViewScroll.jsm",
                     "GeckoViewScroll");
   ModuleManager.add("resource://gre/modules/GeckoViewTab.jsm",
                     "GeckoViewTab");
+  ModuleManager.add("resource://gre/modules/GeckoViewRemoteDebugger.jsm",
+                    "GeckoViewRemoteDebugger");
 
   // Move focus to the content window at the end of startup,
   // so things like text selection can work properly.
   document.getElementById("content").focus();
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewSettings.java
@@ -60,32 +60,35 @@ public final class GeckoViewSettings {
         new Key<Boolean>("useMultiprocess");
 
     /*
      * Key to specify which display-mode we should use
      */
     public static final Key<Integer> DISPLAY_MODE =
         new Key<Integer>("displayMode");
 
+    public static final Key<Boolean> USE_REMOTE_DEBUGGER =
+        new Key<Boolean>("useRemoteDebugger");
 
     private final EventDispatcher mEventDispatcher;
     private final GeckoBundle mBundle;
 
     public GeckoViewSettings() {
         this(null);
     }
 
     /* package */ GeckoViewSettings(EventDispatcher eventDispatcher) {
         mEventDispatcher = eventDispatcher;
         mBundle = new GeckoBundle();
 
         setBoolean(USE_TRACKING_PROTECTION, false);
         setBoolean(USE_PRIVATE_MODE, false);
         setBoolean(USE_MULTIPROCESS, true);
         setInt(DISPLAY_MODE, DisplayMode.BROWSER.value());
+        setBoolean(USE_REMOTE_DEBUGGER, false);
     }
 
     /* package */ GeckoViewSettings(GeckoViewSettings settings, EventDispatcher eventDispatcher) {
         mBundle = new GeckoBundle(settings.mBundle);
         mEventDispatcher = eventDispatcher;
     }
 
     public void setBoolean(final Key<Boolean> key, boolean value) {
--- a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
+++ b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
@@ -21,16 +21,17 @@ import java.util.Locale;
 import org.mozilla.gecko.GeckoView;
 import org.mozilla.gecko.GeckoViewSettings;
 import org.mozilla.gecko.util.GeckoBundle;
 
 public class GeckoViewActivity extends Activity {
     private static final String LOGTAG = "GeckoViewActivity";
     private static final String DEFAULT_URL = "https://mozilla.org";
     private static final String USE_MULTIPROCESS_EXTRA = "use_multiprocess";
+    private static final String USE_REMOTE_DEBUGGER_EXTRA = "use_remote_debugger";
 
     /* package */ static final int REQUEST_FILE_PICKER = 1;
     private static final int REQUEST_PERMISSIONS = 2;
 
     private GeckoView mGeckoView;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -90,16 +91,19 @@ public class GeckoViewActivity extends A
         final Uri uri = intent.getData();
         mGeckoView.loadUri(uri != null ? uri.toString() : DEFAULT_URL);
     }
 
     private void loadSettings(final Intent intent) {
         mGeckoView.getSettings().setBoolean(
             GeckoViewSettings.USE_MULTIPROCESS,
             intent.getBooleanExtra(USE_MULTIPROCESS_EXTRA, true));
+        mGeckoView.getSettings().setBoolean(
+            GeckoViewSettings.USE_REMOTE_DEBUGGER,
+            intent.getBooleanExtra(USE_REMOTE_DEBUGGER_EXTRA, false));
     }
 
     @Override
     protected void onActivityResult(final int requestCode, final int resultCode,
                                     final Intent data) {
         if (requestCode == REQUEST_FILE_PICKER) {
             final BasicGeckoViewPrompt prompt = (BasicGeckoViewPrompt)
                     mGeckoView.getPromptDelegate();
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -438,20 +438,18 @@
 @BINPATH@/components/extensions-toolkit.manifest
 @BINPATH@/components/extensions-mobile.manifest
 @BINPATH@/components/extension-process-script.js
 
 ; Features
 @BINPATH@/features/*
 
 ; DevTools
-#ifndef MOZ_GECKOVIEW_JAR
 @BINPATH@/chrome/devtools@JAREXT@
 @BINPATH@/chrome/devtools.manifest
-#endif
 
 ; [Default Preferences]
 ; All the pref files must be part of base to prevent migration bugs
 @BINPATH@/@PREF_DIR@/mobile.js
 @BINPATH@/@PREF_DIR@/channel-prefs.js
 @BINPATH@/ua-update.json
 @BINPATH@/greprefs.js
 @BINPATH@/defaults/autoconfig/prefcalls.js
new file mode 100644
--- /dev/null
+++ b/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
@@ -0,0 +1,111 @@
+/* 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/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["GeckoViewRemoteDebugger"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+Cu.import("resource://gre/modules/GeckoViewModule.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+  Cu.import("resource://gre/modules/AndroidLog.jsm", {})
+    .AndroidLog.d.bind(null, "ViewRemoteDebugger"));
+
+XPCOMUtils.defineLazyGetter(this, "DebuggerServer", () => {
+  const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
+  const { DebuggerServer } = require("devtools/server/main");
+  return DebuggerServer;
+});
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
+class GeckoViewRemoteDebugger extends GeckoViewModule {
+  init() {
+    this._isEnabled = false;
+    this._usbDebugger = new USBRemoteDebugger();
+  }
+
+  onSettingsUpdate() {
+    let enabled = this.settings.useRemoteDebugger;
+
+    if (enabled && !this._isEnabled) {
+      this.register();
+    } else if (!enabled) {
+      this.unregister();
+    }
+  }
+
+  register() {
+    if (!DebuggerServer.initialized) {
+      DebuggerServer.init();
+      DebuggerServer.addBrowserActors("navigator:geckoview");
+      DebuggerServer.registerModule(
+        "resource://gre/modules/dbg-browser-actors.js");
+      DebuggerServer.allowChromeProcess = true;
+    }
+    this._isEnabled = true;
+    this._usbDebugger.stop();
+
+    let windowId = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
+                              .getInterface(Ci.nsIDOMWindowUtils)
+                              .outerWindowID;
+    let portOrPath = this.settings.debuggerSocketDir +
+                     "/firefox-debugger-socket-" +
+                     windowId;
+    this._usbDebugger.start(portOrPath);
+  }
+
+  unregister() {
+    this._isEnabled = false;
+    this._usbDebugger.stop();
+  }
+}
+
+class USBRemoteDebugger {
+  start(aPortOrPath) {
+    try {
+      let AuthenticatorType = DebuggerServer.Authenticators.get("PROMPT");
+      let authenticator = new AuthenticatorType.Server();
+      authenticator.allowConnection = this.allowConnection.bind(this);
+      this._listener = DebuggerServer.createListener();
+      this._listener.portOrPath = aPortOrPath;
+      this._listener.authenticator = authenticator;
+      this._listener.open();
+      debug(`USB remote debugger - listening on ${aPortOrPath}`);
+    } catch (e) {
+      debug("Unable to start USB debugger server: " + e);
+    }
+  }
+
+  stop() {
+    if (!this._listener) {
+      return;
+    }
+
+    try {
+      this._listener.close();
+      this._listener = null;
+    } catch (e) {
+      debug("Unable to stop USB debugger server: " + e);
+    }
+  }
+
+  allowConnection(aSession) {
+    if (!this._listener) {
+      return DebuggerServer.AuthenticationResult.DENY;
+    }
+
+    if (aSession.server.port) {
+      return DebuggerServer.AuthenticationResult.DENY;
+    } else {
+      return DebuggerServer.AuthenticationResult.ALLOW;
+    }
+  }
+}
--- a/mobile/android/modules/geckoview/GeckoViewTab.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewTab.jsm
@@ -17,19 +17,20 @@ XPCOMUtils.defineLazyGetter(this, "dump"
 
 function debug(aMsg) {
   // dump(aMsg);
 }
 
 // Stub BrowserApp implementation for WebExtensions support.
 class GeckoViewTab extends GeckoViewModule {
   init() {
-    this.browser.tab = { id: 0 };
+    this.browser.tab = { id: 0, browser: this.browser };
 
-    this.window.BrowserApp = {
+    this.window.gBrowser = this.window.BrowserApp = {
+      selectedBrowser: this.browser,
       tabs: [this.browser.tab],
       selectedTab: this.browser.tab,
 
       getTabForId: function(aId) {
         return this.selectedTab;
       },
 
       getTabForBrowser: function(aBrowser) {
--- a/mobile/android/modules/geckoview/moz.build
+++ b/mobile/android/modules/geckoview/moz.build
@@ -6,14 +6,15 @@
 
 EXTRA_JS_MODULES += [
     'AndroidLog.jsm',
     'GeckoViewContent.jsm',
     'GeckoViewContentModule.jsm',
     'GeckoViewModule.jsm',
     'GeckoViewNavigation.jsm',
     'GeckoViewProgress.jsm',
+    'GeckoViewRemoteDebugger.jsm',
     'GeckoViewScroll.jsm',
     'GeckoViewSettings.jsm',
     'GeckoViewTab.jsm',
     'GeckoViewUtils.jsm',
     'Messaging.jsm',
 ]