summaryrefslogtreecommitdiffstats
path: root/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/modules/geckoview/GeckoViewRemoteDebugger.sys.mjs')
-rw-r--r--mobile/android/modules/geckoview/GeckoViewRemoteDebugger.sys.mjs141
1 files changed, 141 insertions, 0 deletions
diff --git a/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.sys.mjs b/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.sys.mjs
new file mode 100644
index 0000000000..c4d6bf7fb5
--- /dev/null
+++ b/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.sys.mjs
@@ -0,0 +1,141 @@
+/* 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/. */
+
+import { GeckoViewUtils } from "resource://gre/modules/GeckoViewUtils.sys.mjs";
+
+const lazy = {};
+
+ChromeUtils.defineLazyGetter(lazy, "require", () => {
+ const { require } = ChromeUtils.importESModule(
+ "resource://devtools/shared/loader/Loader.sys.mjs"
+ );
+ return require;
+});
+
+ChromeUtils.defineLazyGetter(lazy, "DevToolsServer", () => {
+ const { DevToolsServer } = lazy.require("devtools/server/devtools-server");
+ return DevToolsServer;
+});
+
+ChromeUtils.defineLazyGetter(lazy, "SocketListener", () => {
+ const { SocketListener } = lazy.require("devtools/shared/security/socket");
+ return SocketListener;
+});
+
+const { debug, warn } = GeckoViewUtils.initLogging("RemoteDebugger");
+
+export var GeckoViewRemoteDebugger = {
+ observe(aSubject, aTopic, aData) {
+ if (aTopic !== "nsPref:changed") {
+ return;
+ }
+
+ if (Services.prefs.getBoolPref(aData, false)) {
+ this.onEnable();
+ } else {
+ this.onDisable();
+ }
+ },
+
+ onInit() {
+ debug`onInit`;
+ this._isEnabled = false;
+ this._usbDebugger = new USBRemoteDebugger();
+ },
+
+ onEnable() {
+ if (this._isEnabled) {
+ return;
+ }
+
+ debug`onEnable`;
+ lazy.DevToolsServer.init();
+ lazy.DevToolsServer.registerAllActors();
+ const { createRootActor } = lazy.require(
+ "resource://gre/modules/dbg-browser-actors.js"
+ );
+ lazy.DevToolsServer.setRootActor(createRootActor);
+ lazy.DevToolsServer.allowChromeProcess = true;
+ lazy.DevToolsServer.chromeWindowType = "navigator:geckoview";
+ // Force the Server to stay alive even if there are no connections at the moment.
+ lazy.DevToolsServer.keepAlive = true;
+
+ // Socket address for USB remote debugger expects
+ // @ANDROID_PACKAGE_NAME/firefox-debugger-socket.
+ // In /proc/net/unix, it will be outputed as
+ // @org.mozilla.geckoview_example/firefox-debugger-socket
+ //
+ // If package name isn't available, it will be "@firefox-debugger-socket".
+
+ let packageName = Services.env.get("MOZ_ANDROID_PACKAGE_NAME");
+ if (packageName) {
+ packageName = packageName + "/";
+ } else {
+ warn`Missing env MOZ_ANDROID_PACKAGE_NAME. Unable to get package name`;
+ }
+
+ this._isEnabled = true;
+ this._usbDebugger.stop();
+
+ const portOrPath = packageName + "firefox-debugger-socket";
+ this._usbDebugger.start(portOrPath);
+ },
+
+ onDisable() {
+ if (!this._isEnabled) {
+ return;
+ }
+
+ debug`onDisable`;
+ this._isEnabled = false;
+ this._usbDebugger.stop();
+ },
+};
+
+class USBRemoteDebugger {
+ start(aPortOrPath) {
+ try {
+ const AuthenticatorType =
+ lazy.DevToolsServer.Authenticators.get("PROMPT");
+ const authenticator = new AuthenticatorType.Server();
+ authenticator.allowConnection = this.allowConnection.bind(this);
+ const socketOptions = {
+ authenticator,
+ portOrPath: aPortOrPath,
+ };
+ this._listener = new lazy.SocketListener(
+ lazy.DevToolsServer,
+ socketOptions
+ );
+ this._listener.open();
+ debug`USB remote debugger - listening on ${aPortOrPath}`;
+ } catch (e) {
+ warn`Unable to start USB debugger server: ${e}`;
+ }
+ }
+
+ stop() {
+ if (!this._listener) {
+ return;
+ }
+
+ try {
+ this._listener.close();
+ this._listener = null;
+ } catch (e) {
+ warn`Unable to stop USB debugger server: ${e}`;
+ }
+ }
+
+ allowConnection(aSession) {
+ if (!this._listener) {
+ return lazy.DevToolsServer.AuthenticationResult.DENY;
+ }
+
+ if (aSession.server.port) {
+ return lazy.DevToolsServer.AuthenticationResult.DENY;
+ }
+ return lazy.DevToolsServer.AuthenticationResult.ALLOW;
+ }
+}