summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/remote-debugging/adb/adb-process.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/remote-debugging/adb/adb-process.js')
-rw-r--r--devtools/client/shared/remote-debugging/adb/adb-process.js155
1 files changed, 155 insertions, 0 deletions
diff --git a/devtools/client/shared/remote-debugging/adb/adb-process.js b/devtools/client/shared/remote-debugging/adb/adb-process.js
new file mode 100644
index 0000000000..ade509125e
--- /dev/null
+++ b/devtools/client/shared/remote-debugging/adb/adb-process.js
@@ -0,0 +1,155 @@
+/* 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";
+
+const { dumpn } = require("resource://devtools/shared/DevToolsUtils.js");
+const EventEmitter = require("resource://devtools/shared/event-emitter.js");
+const {
+ getFileForBinary,
+} = require("resource://devtools/client/shared/remote-debugging/adb/adb-binary.js");
+const { setTimeout } = ChromeUtils.importESModule(
+ "resource://gre/modules/Timer.sys.mjs"
+);
+
+loader.lazyRequireGetter(
+ this,
+ "runCommand",
+ "resource://devtools/client/shared/remote-debugging/adb/commands/index.js",
+ true
+);
+loader.lazyRequireGetter(
+ this,
+ "check",
+ "resource://devtools/client/shared/remote-debugging/adb/adb-running-checker.js",
+ true
+);
+
+// Waits until a predicate returns true or re-tries the predicate calls
+// |retry| times, we wait for 100ms between each calls.
+async function waitUntil(predicate, retry = 20) {
+ let count = 0;
+ while (count++ < retry) {
+ if (await predicate()) {
+ return true;
+ }
+ // Wait for 100 milliseconds.
+ await new Promise(resolve => setTimeout(resolve, 100));
+ }
+ // Timed out after trying too many times.
+ return false;
+}
+
+// Class representing the ADB process.
+class AdbProcess extends EventEmitter {
+ constructor() {
+ super();
+
+ this._ready = false;
+ this._didRunInitially = false;
+ }
+
+ get ready() {
+ return this._ready;
+ }
+
+ _getAdbFile() {
+ if (this._adbFilePromise) {
+ return this._adbFilePromise;
+ }
+ this._adbFilePromise = getFileForBinary();
+ return this._adbFilePromise;
+ }
+
+ async _runProcess(process, params) {
+ return new Promise((resolve, reject) => {
+ process.runAsync(
+ params,
+ params.length,
+ {
+ observe(subject, topic, data) {
+ switch (topic) {
+ case "process-finished":
+ resolve();
+ break;
+ case "process-failed":
+ reject();
+ break;
+ }
+ },
+ },
+ false
+ );
+ });
+ }
+
+ // We startup by launching adb in server mode, and setting
+ // the tcp socket preference to |true|
+ async start() {
+ const onSuccessfulStart = () => {
+ this._ready = true;
+ this.emit("adb-ready");
+ };
+
+ const isAdbRunning = await check();
+ if (isAdbRunning) {
+ dumpn("Found ADB process running, not restarting");
+ onSuccessfulStart();
+ return;
+ }
+ dumpn("Didn't find ADB process running, restarting");
+
+ this._didRunInitially = true;
+ const process = Cc["@mozilla.org/process/util;1"].createInstance(
+ Ci.nsIProcess
+ );
+
+ // FIXME: Bug 1481691 - We should avoid extracting files every time.
+ const adbFile = await this._getAdbFile();
+ process.init(adbFile);
+ // Hide command prompt window on Windows
+ process.startHidden = true;
+ process.noShell = true;
+ const params = ["start-server"];
+ let isStarted = false;
+ try {
+ await this._runProcess(process, params);
+ isStarted = await waitUntil(check);
+ } catch (e) {}
+
+ if (isStarted) {
+ onSuccessfulStart();
+ } else {
+ this._ready = false;
+ throw new Error("ADB Process didn't start");
+ }
+ }
+
+ /**
+ * Stop the ADB server, but only if we started it. If it was started before
+ * us, we return immediately.
+ */
+ async stop() {
+ if (!this._didRunInitially) {
+ return; // We didn't start the server, nothing to do
+ }
+ await this.kill();
+ }
+
+ /**
+ * Kill the ADB server.
+ */
+ async kill() {
+ try {
+ await runCommand("host:kill");
+ } catch (e) {
+ dumpn("Failed to send host:kill command");
+ }
+ dumpn("adb server was terminated by host:kill");
+ this._ready = false;
+ this._didRunInitially = false;
+ }
+}
+
+exports.adbProcess = new AdbProcess();