mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Bug 1492700 - Split adb.js in several files;r=daisuke
Differential Revision: https://phabricator.services.mozilla.com/D13473 --HG-- rename : devtools/shared/adb/adb.js => devtools/shared/adb/commands/list-devices.js rename : devtools/shared/adb/adb.js => devtools/shared/adb/commands/prepare-tcp-connection.js rename : devtools/shared/adb/adb.js => devtools/shared/adb/commands/run-command.js rename : devtools/shared/adb/adb.js => devtools/shared/adb/commands/shell.js rename : devtools/shared/adb/adb.js => devtools/shared/adb/commands/track-devices.js extra : moz-landing-system : lando
This commit is contained in:
parent
ec7b320b38
commit
b77ab873fa
@ -4,7 +4,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { ADB } = require("devtools/shared/adb/adb");
|
||||
const { prepareTCPConnection } = require("devtools/shared/adb/commands/index");
|
||||
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
|
||||
const { DebuggerServer } = require("devtools/server/main");
|
||||
const { ClientWrapper } = require("./client-wrapper");
|
||||
@ -29,7 +29,7 @@ async function createNetworkClient(host, port) {
|
||||
}
|
||||
|
||||
async function createUSBClient(socketPath) {
|
||||
const port = await ADB.prepareTCPConnection(socketPath);
|
||||
const port = await prepareTCPConnection(socketPath);
|
||||
return createNetworkClient("localhost", port);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { ADB } = require("devtools/shared/adb/adb");
|
||||
const { shell } = require("devtools/shared/adb/commands/index");
|
||||
|
||||
/**
|
||||
* A Device instance is created and registered with the Devices module whenever
|
||||
@ -19,7 +19,7 @@ class AdbDevice {
|
||||
if (this._model) {
|
||||
return this._model;
|
||||
}
|
||||
const model = await ADB.shell("getprop ro.product.model");
|
||||
const model = await shell("getprop ro.product.model");
|
||||
this._model = model.trim();
|
||||
return this._model;
|
||||
}
|
||||
@ -33,7 +33,7 @@ class AdbDevice {
|
||||
// 00000000: 00000002 00000000 00010000 0001 01 6551588
|
||||
// /data/data/org.mozilla.fennec/firefox-debugger-socket
|
||||
const query = "cat /proc/net/unix";
|
||||
const rawSocketInfo = await ADB.shell(query);
|
||||
const rawSocketInfo = await shell(query);
|
||||
|
||||
// Filter to lines with "firefox-debugger-socket"
|
||||
let socketInfos = rawSocketInfo.split(/\r?\n/);
|
||||
|
@ -5,7 +5,7 @@
|
||||
"use strict";
|
||||
|
||||
const { RuntimeTypes } = require("devtools/client/webide/modules/runtime-types");
|
||||
const { ADB } = require("devtools/shared/adb/adb");
|
||||
const { prepareTCPConnection } = require("devtools/shared/adb/commands/index");
|
||||
|
||||
class AdbRuntime {
|
||||
constructor(adbDevice, model, socketPath) {
|
||||
@ -33,7 +33,7 @@ class AdbRuntime {
|
||||
}
|
||||
|
||||
connect(connection) {
|
||||
return ADB.prepareTCPConnection(this._socketPath).then(port => {
|
||||
return prepareTCPConnection(this._socketPath).then(port => {
|
||||
connection.host = "localhost";
|
||||
connection.port = port;
|
||||
connection.connect();
|
||||
|
@ -7,6 +7,7 @@
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { dumpn } = require("devtools/shared/DevToolsUtils");
|
||||
const { ADB } = require("devtools/shared/adb/adb");
|
||||
const { trackDevices } = require("devtools/shared/adb/commands/index");
|
||||
const { adbDevicesRegistry } = require("devtools/shared/adb/adb-devices-registry");
|
||||
const { AdbRuntime } = require("devtools/shared/adb/adb-runtime");
|
||||
|
||||
@ -30,7 +31,7 @@ class ADBScanner extends EventEmitter {
|
||||
adbDevicesRegistry.on("unregister", this._updateRuntimes);
|
||||
|
||||
ADB.start().then(() => {
|
||||
ADB.trackDevices();
|
||||
trackDevices();
|
||||
});
|
||||
this._updateRuntimes();
|
||||
}
|
||||
|
@ -7,21 +7,17 @@
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const client = require("./adb-client");
|
||||
const { dumpn } = require("devtools/shared/DevToolsUtils");
|
||||
const { getFileForBinary } = require("./adb-binary");
|
||||
const { setTimeout } = require("resource://gre/modules/Timer.jsm");
|
||||
const { Services } = require("resource://gre/modules/Services.jsm");
|
||||
const { ConnectionManager } = require("devtools/shared/client/connection-manager");
|
||||
const { runCommand } = require("./commands/index");
|
||||
loader.lazyRequireGetter(this, "check",
|
||||
"devtools/shared/adb/adb-running-checker", true);
|
||||
|
||||
let ready = false;
|
||||
let didRunInitially = false;
|
||||
|
||||
const OKAY = 0x59414b4f;
|
||||
|
||||
const ADB = {
|
||||
get didRunInitially() {
|
||||
return didRunInitially;
|
||||
@ -137,7 +133,7 @@ const ADB = {
|
||||
*/
|
||||
async kill() {
|
||||
try {
|
||||
await this.runCommand("host:kill");
|
||||
await runCommand("host:kill");
|
||||
} catch (e) {
|
||||
dumpn("Failed to send host:kill command");
|
||||
}
|
||||
@ -145,280 +141,6 @@ const ADB = {
|
||||
this.ready = false;
|
||||
this.didRunInitially = false;
|
||||
},
|
||||
|
||||
// Start tracking devices connecting and disconnecting from the host.
|
||||
// We can't reuse runCommand here because we keep the socket alive.
|
||||
// @return The socket used.
|
||||
trackDevices() {
|
||||
dumpn("trackDevices");
|
||||
const socket = client.connect();
|
||||
let waitForFirst = true;
|
||||
const devices = {};
|
||||
|
||||
socket.s.onopen = function() {
|
||||
dumpn("trackDevices onopen");
|
||||
Services.obs.notifyObservers(null, "adb-track-devices-start");
|
||||
const req = client.createRequest("host:track-devices");
|
||||
socket.send(req);
|
||||
};
|
||||
|
||||
socket.s.onerror = function(event) {
|
||||
dumpn("trackDevices onerror: " + event);
|
||||
Services.obs.notifyObservers(null, "adb-track-devices-stop");
|
||||
};
|
||||
|
||||
socket.s.onclose = function() {
|
||||
dumpn("trackDevices onclose");
|
||||
|
||||
// Report all devices as disconnected
|
||||
for (const dev in devices) {
|
||||
devices[dev] = false;
|
||||
EventEmitter.emit(ADB, "device-disconnected", dev);
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(null, "adb-track-devices-stop");
|
||||
|
||||
// When we lose connection to the server,
|
||||
// and the adb is still on, we most likely got our server killed
|
||||
// by local adb. So we do try to reconnect to it.
|
||||
setTimeout(function() { // Give some time to the new adb to start
|
||||
if (ADB.ready) { // Only try to reconnect/restart if the add-on is still enabled
|
||||
ADB.start().then(function() { // try to connect to the new local adb server
|
||||
// or, spawn a new one
|
||||
ADB.trackDevices(); // Re-track devices
|
||||
});
|
||||
}
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
socket.s.ondata = function(event) {
|
||||
dumpn("trackDevices ondata");
|
||||
const data = event.data;
|
||||
dumpn("length=" + data.byteLength);
|
||||
const dec = new TextDecoder();
|
||||
dumpn(dec.decode(new Uint8Array(data)).trim());
|
||||
|
||||
// check the OKAY or FAIL on first packet.
|
||||
if (waitForFirst) {
|
||||
if (!client.checkResponse(data, OKAY)) {
|
||||
socket.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const packet = client.unpackPacket(data, !waitForFirst);
|
||||
waitForFirst = false;
|
||||
|
||||
if (packet.data == "") {
|
||||
// All devices got disconnected.
|
||||
for (const dev in devices) {
|
||||
devices[dev] = false;
|
||||
EventEmitter.emit(ADB, "device-disconnected", dev);
|
||||
}
|
||||
} else {
|
||||
// One line per device, each line being $DEVICE\t(offline|device)
|
||||
const lines = packet.data.split("\n");
|
||||
const newDev = {};
|
||||
lines.forEach(function(line) {
|
||||
if (line.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [dev, status] = line.split("\t");
|
||||
newDev[dev] = status !== "offline";
|
||||
});
|
||||
// Check which device changed state.
|
||||
for (const dev in newDev) {
|
||||
if (devices[dev] != newDev[dev]) {
|
||||
if (dev in devices || newDev[dev]) {
|
||||
const topic = newDev[dev] ? "device-connected"
|
||||
: "device-disconnected";
|
||||
EventEmitter.emit(ADB, topic, dev);
|
||||
}
|
||||
devices[dev] = newDev[dev];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
// Sends back an array of device names.
|
||||
listDevices() {
|
||||
dumpn("listDevices");
|
||||
|
||||
return this.runCommand("host:devices").then(
|
||||
function onSuccess(data) {
|
||||
const lines = data.split("\n");
|
||||
const res = [];
|
||||
lines.forEach(function(line) {
|
||||
if (line.length == 0) {
|
||||
return;
|
||||
}
|
||||
const [ device ] = line.split("\t");
|
||||
res.push(device);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
// sends adb forward localPort devicePort
|
||||
forwardPort(localPort, devicePort) {
|
||||
dumpn("forwardPort " + localPort + " -- " + devicePort);
|
||||
// <host-prefix>:forward:<local>;<remote>
|
||||
|
||||
return this.runCommand("host:forward:" + localPort + ";" + devicePort)
|
||||
.then(function onSuccess(data) {
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
||||
// Prepare TCP connection for provided socket path.
|
||||
// The returned value is a port number of localhost for the connection.
|
||||
async prepareTCPConnection(socketPath) {
|
||||
const port = ConnectionManager.getFreeTCPPort();
|
||||
const local = `tcp:${ port }`;
|
||||
const remote = socketPath.startsWith("@")
|
||||
? `localabstract:${ socketPath.substring(1) }`
|
||||
: `localfilesystem:${ socketPath }`;
|
||||
await this.forwardPort(local, remote);
|
||||
return port;
|
||||
},
|
||||
|
||||
// Run a shell command
|
||||
async shell(command) {
|
||||
let state;
|
||||
let stdout = "";
|
||||
|
||||
dumpn("shell " + command);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const shutdown = function() {
|
||||
dumpn("shell shutdown");
|
||||
socket.close();
|
||||
reject("BAD_RESPONSE");
|
||||
};
|
||||
|
||||
const runFSM = function runFSM(data) {
|
||||
dumpn("runFSM " + state);
|
||||
let req;
|
||||
let ignoreResponseCode = false;
|
||||
switch (state) {
|
||||
case "start":
|
||||
state = "send-transport";
|
||||
runFSM();
|
||||
break;
|
||||
case "send-transport":
|
||||
req = client.createRequest("host:transport-any");
|
||||
socket.send(req);
|
||||
state = "wait-transport";
|
||||
break;
|
||||
case "wait-transport":
|
||||
if (!client.checkResponse(data, OKAY)) {
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
state = "send-shell";
|
||||
runFSM();
|
||||
break;
|
||||
case "send-shell":
|
||||
req = client.createRequest("shell:" + command);
|
||||
socket.send(req);
|
||||
state = "rec-shell";
|
||||
break;
|
||||
case "rec-shell":
|
||||
if (!client.checkResponse(data, OKAY)) {
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
state = "decode-shell";
|
||||
if (client.getBuffer(data).byteLength == 4) {
|
||||
break;
|
||||
}
|
||||
ignoreResponseCode = true;
|
||||
// eslint-disable-next-lined no-fallthrough
|
||||
case "decode-shell":
|
||||
const decoder = new TextDecoder();
|
||||
const text = new Uint8Array(client.getBuffer(data),
|
||||
ignoreResponseCode ? 4 : 0);
|
||||
stdout += decoder.decode(text);
|
||||
break;
|
||||
default:
|
||||
dumpn("shell Unexpected State: " + state);
|
||||
reject("UNEXPECTED_STATE");
|
||||
}
|
||||
};
|
||||
|
||||
const socket = client.connect();
|
||||
socket.s.onerror = function(event) {
|
||||
dumpn("shell onerror");
|
||||
reject("SOCKET_ERROR");
|
||||
};
|
||||
|
||||
socket.s.onopen = function(event) {
|
||||
dumpn("shell onopen");
|
||||
state = "start";
|
||||
runFSM();
|
||||
};
|
||||
|
||||
socket.s.onclose = function(event) {
|
||||
resolve(stdout);
|
||||
dumpn("shell onclose");
|
||||
};
|
||||
|
||||
socket.s.ondata = function(event) {
|
||||
dumpn("shell ondata");
|
||||
runFSM(event.data);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
// Asynchronously runs an adb command.
|
||||
// @param command The command as documented in
|
||||
// http://androidxref.com/4.0.4/xref/system/core/adb/SERVICES.TXT
|
||||
runCommand(command) {
|
||||
dumpn("runCommand " + command);
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.ready) {
|
||||
setTimeout(function() {
|
||||
reject("ADB_NOT_READY");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const socket = client.connect();
|
||||
|
||||
socket.s.onopen = function() {
|
||||
dumpn("runCommand onopen");
|
||||
const req = client.createRequest(command);
|
||||
socket.send(req);
|
||||
};
|
||||
|
||||
socket.s.onerror = function() {
|
||||
dumpn("runCommand onerror");
|
||||
reject("NETWORK_ERROR");
|
||||
};
|
||||
|
||||
socket.s.onclose = function() {
|
||||
dumpn("runCommand onclose");
|
||||
};
|
||||
|
||||
socket.s.ondata = function(event) {
|
||||
dumpn("runCommand ondata");
|
||||
const data = event.data;
|
||||
|
||||
const packet = client.unpackPacket(data, false);
|
||||
if (!client.checkResponse(data, OKAY)) {
|
||||
socket.close();
|
||||
dumpn("Error: " + packet.data);
|
||||
reject("PROTOCOL_ERROR");
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(packet.data);
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
exports.ADB = ADB;
|
||||
|
19
devtools/shared/adb/commands/index.js
Normal file
19
devtools/shared/adb/commands/index.js
Normal file
@ -0,0 +1,19 @@
|
||||
/* 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 { listDevices } = require("./list-devices");
|
||||
const { prepareTCPConnection } = require("./prepare-tcp-connection");
|
||||
const { runCommand } = require("./run-command");
|
||||
const { shell } = require("./shell");
|
||||
const { trackDevices } = require("./track-devices");
|
||||
|
||||
module.exports = {
|
||||
listDevices,
|
||||
prepareTCPConnection,
|
||||
runCommand,
|
||||
shell,
|
||||
trackDevices,
|
||||
};
|
31
devtools/shared/adb/commands/list-devices.js
Normal file
31
devtools/shared/adb/commands/list-devices.js
Normal file
@ -0,0 +1,31 @@
|
||||
/* 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("devtools/shared/DevToolsUtils");
|
||||
/**
|
||||
* The listDevices command is currently unused in DevTools. We are keeping it while
|
||||
* working on RemoteDebugging NG, in case it becomes needed later. We will remove it from
|
||||
* the codebase if unused at the end of the project. See Bug 1511779.
|
||||
*/
|
||||
const listDevices = function() {
|
||||
dumpn("listDevices");
|
||||
|
||||
return this.runCommand("host:devices").then(
|
||||
function onSuccess(data) {
|
||||
const lines = data.split("\n");
|
||||
const res = [];
|
||||
lines.forEach(function(line) {
|
||||
if (line.length == 0) {
|
||||
return;
|
||||
}
|
||||
const [ device ] = line.split("\t");
|
||||
res.push(device);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
);
|
||||
};
|
||||
exports.listDevices = listDevices;
|
12
devtools/shared/adb/commands/moz.build
Normal file
12
devtools/shared/adb/commands/moz.build
Normal file
@ -0,0 +1,12 @@
|
||||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
'index.js',
|
||||
'list-devices.js',
|
||||
'prepare-tcp-connection.js',
|
||||
'run-command.js',
|
||||
'shell.js',
|
||||
'track-devices.js',
|
||||
)
|
33
devtools/shared/adb/commands/prepare-tcp-connection.js
Normal file
33
devtools/shared/adb/commands/prepare-tcp-connection.js
Normal file
@ -0,0 +1,33 @@
|
||||
/* 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("devtools/shared/DevToolsUtils");
|
||||
const { ConnectionManager } = require("devtools/shared/client/connection-manager");
|
||||
const { runCommand } = require("./run-command");
|
||||
|
||||
// sends adb forward localPort devicePort
|
||||
const forwardPort = function(localPort, devicePort) {
|
||||
dumpn("forwardPort " + localPort + " -- " + devicePort);
|
||||
// <host-prefix>:forward:<local>;<remote>
|
||||
|
||||
return runCommand("host:forward:" + localPort + ";" + devicePort)
|
||||
.then(function onSuccess(data) {
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
// Prepare TCP connection for provided socket path.
|
||||
// The returned value is a port number of localhost for the connection.
|
||||
const prepareTCPConnection = async function(socketPath) {
|
||||
const port = ConnectionManager.getFreeTCPPort();
|
||||
const local = `tcp:${ port }`;
|
||||
const remote = socketPath.startsWith("@")
|
||||
? `localabstract:${ socketPath.substring(1) }`
|
||||
: `localfilesystem:${ socketPath }`;
|
||||
await forwardPort(local, remote);
|
||||
return port;
|
||||
};
|
||||
exports.prepareTCPConnection = prepareTCPConnection;
|
62
devtools/shared/adb/commands/run-command.js
Normal file
62
devtools/shared/adb/commands/run-command.js
Normal file
@ -0,0 +1,62 @@
|
||||
/* 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/. */
|
||||
|
||||
// Wrapper around the ADB utility.
|
||||
|
||||
"use strict";
|
||||
|
||||
const { dumpn } = require("devtools/shared/DevToolsUtils");
|
||||
const { setTimeout } = require("resource://gre/modules/Timer.jsm");
|
||||
const { ADB } = require("../adb");
|
||||
const client = require("../adb-client");
|
||||
|
||||
const OKAY = 0x59414b4f;
|
||||
|
||||
// Asynchronously runs an adb command.
|
||||
// @param command The command as documented in
|
||||
// http://androidxref.com/4.0.4/xref/system/core/adb/SERVICES.TXT
|
||||
const runCommand = function(command) {
|
||||
dumpn("runCommand " + command);
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!ADB.ready) {
|
||||
setTimeout(function() {
|
||||
reject("ADB_NOT_READY");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const socket = client.connect();
|
||||
|
||||
socket.s.onopen = function() {
|
||||
dumpn("runCommand onopen");
|
||||
const req = client.createRequest(command);
|
||||
socket.send(req);
|
||||
};
|
||||
|
||||
socket.s.onerror = function() {
|
||||
dumpn("runCommand onerror");
|
||||
reject("NETWORK_ERROR");
|
||||
};
|
||||
|
||||
socket.s.onclose = function() {
|
||||
dumpn("runCommand onclose");
|
||||
};
|
||||
|
||||
socket.s.ondata = function(event) {
|
||||
dumpn("runCommand ondata");
|
||||
const data = event.data;
|
||||
|
||||
const packet = client.unpackPacket(data, false);
|
||||
if (!client.checkResponse(data, OKAY)) {
|
||||
socket.close();
|
||||
dumpn("Error: " + packet.data);
|
||||
reject("PROTOCOL_ERROR");
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(packet.data);
|
||||
};
|
||||
});
|
||||
};
|
||||
exports.runCommand = runCommand;
|
101
devtools/shared/adb/commands/shell.js
Normal file
101
devtools/shared/adb/commands/shell.js
Normal file
@ -0,0 +1,101 @@
|
||||
/* 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/. */
|
||||
|
||||
// Wrapper around the ADB utility.
|
||||
|
||||
"use strict";
|
||||
|
||||
const { dumpn } = require("devtools/shared/DevToolsUtils");
|
||||
const client = require("../adb-client");
|
||||
|
||||
const OKAY = 0x59414b4f;
|
||||
|
||||
const shell = async function(command) {
|
||||
let state;
|
||||
let stdout = "";
|
||||
|
||||
dumpn("shell " + command);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const shutdown = function() {
|
||||
dumpn("shell shutdown");
|
||||
socket.close();
|
||||
reject("BAD_RESPONSE");
|
||||
};
|
||||
|
||||
const runFSM = function runFSM(data) {
|
||||
dumpn("runFSM " + state);
|
||||
let req;
|
||||
let ignoreResponseCode = false;
|
||||
switch (state) {
|
||||
case "start":
|
||||
state = "send-transport";
|
||||
runFSM();
|
||||
break;
|
||||
case "send-transport":
|
||||
req = client.createRequest("host:transport-any");
|
||||
socket.send(req);
|
||||
state = "wait-transport";
|
||||
break;
|
||||
case "wait-transport":
|
||||
if (!client.checkResponse(data, OKAY)) {
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
state = "send-shell";
|
||||
runFSM();
|
||||
break;
|
||||
case "send-shell":
|
||||
req = client.createRequest("shell:" + command);
|
||||
socket.send(req);
|
||||
state = "rec-shell";
|
||||
break;
|
||||
case "rec-shell":
|
||||
if (!client.checkResponse(data, OKAY)) {
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
state = "decode-shell";
|
||||
if (client.getBuffer(data).byteLength == 4) {
|
||||
break;
|
||||
}
|
||||
ignoreResponseCode = true;
|
||||
// eslint-disable-next-lined no-fallthrough
|
||||
case "decode-shell":
|
||||
const decoder = new TextDecoder();
|
||||
const text = new Uint8Array(client.getBuffer(data),
|
||||
ignoreResponseCode ? 4 : 0);
|
||||
stdout += decoder.decode(text);
|
||||
break;
|
||||
default:
|
||||
dumpn("shell Unexpected State: " + state);
|
||||
reject("UNEXPECTED_STATE");
|
||||
}
|
||||
};
|
||||
|
||||
const socket = client.connect();
|
||||
socket.s.onerror = function(event) {
|
||||
dumpn("shell onerror");
|
||||
reject("SOCKET_ERROR");
|
||||
};
|
||||
|
||||
socket.s.onopen = function(event) {
|
||||
dumpn("shell onopen");
|
||||
state = "start";
|
||||
runFSM();
|
||||
};
|
||||
|
||||
socket.s.onclose = function(event) {
|
||||
resolve(stdout);
|
||||
dumpn("shell onclose");
|
||||
};
|
||||
|
||||
socket.s.ondata = function(event) {
|
||||
dumpn("shell ondata");
|
||||
runFSM(event.data);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
exports.shell = shell;
|
114
devtools/shared/adb/commands/track-devices.js
Normal file
114
devtools/shared/adb/commands/track-devices.js
Normal file
@ -0,0 +1,114 @@
|
||||
/* 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/. */
|
||||
|
||||
// Wrapper around the ADB utility.
|
||||
|
||||
"use strict";
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { dumpn } = require("devtools/shared/DevToolsUtils");
|
||||
const { setTimeout } = require("resource://gre/modules/Timer.jsm");
|
||||
const { Services } = require("resource://gre/modules/Services.jsm");
|
||||
|
||||
const { ADB } = require("../adb");
|
||||
const client = require("../adb-client");
|
||||
|
||||
const OKAY = 0x59414b4f;
|
||||
|
||||
// Start tracking devices connecting and disconnecting from the host.
|
||||
// We can't reuse runCommand here because we keep the socket alive.
|
||||
// @return The socket used.
|
||||
const trackDevices = function() {
|
||||
dumpn("trackDevices");
|
||||
const socket = client.connect();
|
||||
let waitForFirst = true;
|
||||
const devices = {};
|
||||
|
||||
socket.s.onopen = function() {
|
||||
dumpn("trackDevices onopen");
|
||||
Services.obs.notifyObservers(null, "adb-track-devices-start");
|
||||
const req = client.createRequest("host:track-devices");
|
||||
socket.send(req);
|
||||
};
|
||||
|
||||
socket.s.onerror = function(event) {
|
||||
dumpn("trackDevices onerror: " + event);
|
||||
Services.obs.notifyObservers(null, "adb-track-devices-stop");
|
||||
};
|
||||
|
||||
socket.s.onclose = function() {
|
||||
dumpn("trackDevices onclose");
|
||||
|
||||
// Report all devices as disconnected
|
||||
for (const dev in devices) {
|
||||
devices[dev] = false;
|
||||
EventEmitter.emit(ADB, "device-disconnected", dev);
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(null, "adb-track-devices-stop");
|
||||
|
||||
// When we lose connection to the server,
|
||||
// and the adb is still on, we most likely got our server killed
|
||||
// by local adb. So we do try to reconnect to it.
|
||||
setTimeout(function() { // Give some time to the new adb to start
|
||||
if (ADB.ready) { // Only try to reconnect/restart if the add-on is still enabled
|
||||
ADB.start().then(function() { // try to connect to the new local adb server
|
||||
// or, spawn a new one
|
||||
trackDevices(); // Re-track devices
|
||||
});
|
||||
}
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
socket.s.ondata = function(event) {
|
||||
dumpn("trackDevices ondata");
|
||||
const data = event.data;
|
||||
dumpn("length=" + data.byteLength);
|
||||
const dec = new TextDecoder();
|
||||
dumpn(dec.decode(new Uint8Array(data)).trim());
|
||||
|
||||
// check the OKAY or FAIL on first packet.
|
||||
if (waitForFirst) {
|
||||
if (!client.checkResponse(data, OKAY)) {
|
||||
socket.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const packet = client.unpackPacket(data, !waitForFirst);
|
||||
waitForFirst = false;
|
||||
|
||||
if (packet.data == "") {
|
||||
// All devices got disconnected.
|
||||
for (const dev in devices) {
|
||||
devices[dev] = false;
|
||||
EventEmitter.emit(ADB, "device-disconnected", dev);
|
||||
}
|
||||
} else {
|
||||
// One line per device, each line being $DEVICE\t(offline|device)
|
||||
const lines = packet.data.split("\n");
|
||||
const newDev = {};
|
||||
lines.forEach(function(line) {
|
||||
if (line.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [dev, status] = line.split("\t");
|
||||
newDev[dev] = status !== "offline";
|
||||
});
|
||||
// Check which device changed state.
|
||||
for (const dev in newDev) {
|
||||
if (devices[dev] != newDev[dev]) {
|
||||
if (dev in devices || newDev[dev]) {
|
||||
const topic = newDev[dev] ? "device-connected"
|
||||
: "device-disconnected";
|
||||
EventEmitter.emit(ADB, topic, dev);
|
||||
}
|
||||
devices[dev] = newDev[dev];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
exports.trackDevices = trackDevices;
|
@ -2,6 +2,10 @@
|
||||
# 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/.
|
||||
|
||||
DIRS += [
|
||||
'commands',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'adb-addon.js',
|
||||
'adb-binary.js',
|
||||
|
@ -9,6 +9,7 @@ const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
|
||||
const { getFileForBinary } = require("devtools/shared/adb/adb-binary");
|
||||
const { check } = require("devtools/shared/adb/adb-running-checker");
|
||||
const { ADB } = require("devtools/shared/adb/adb");
|
||||
const { trackDevices } = require("devtools/shared/adb/commands/index");
|
||||
|
||||
const ADB_JSON = {
|
||||
"Linux": {
|
||||
@ -229,7 +230,7 @@ add_task({
|
||||
EventEmitter.on(ADB, "device-connected", deviceId => {
|
||||
resolve(deviceId);
|
||||
});
|
||||
ADB.trackDevices();
|
||||
trackDevices();
|
||||
});
|
||||
|
||||
equal(receivedDeviceId, "1234567890");
|
||||
|
Loading…
Reference in New Issue
Block a user