Source code

Revision control

Copy as Markdown

Other Tools

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