/* 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; } }