shell.js (2865B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // Wrapper around the ADB utility. 6 7 "use strict"; 8 9 const { dumpn } = require("resource://devtools/shared/DevToolsUtils.js"); 10 const client = require("resource://devtools/client/shared/remote-debugging/adb/adb-client.js"); 11 12 const OKAY = 0x59414b4f; 13 14 const shell = async function (deviceId, command) { 15 if (!deviceId) { 16 throw new Error("ADB shell command needs the device id"); 17 } 18 19 let state; 20 let stdout = ""; 21 22 dumpn("shell " + command + " on " + deviceId); 23 24 return new Promise((resolve, reject) => { 25 const shutdown = function () { 26 dumpn("shell shutdown"); 27 socket.close(); 28 reject("BAD_RESPONSE"); 29 }; 30 31 const runFSM = function runFSM(data) { 32 dumpn("runFSM " + state); 33 let req; 34 let ignoreResponseCode = false; 35 switch (state) { 36 case "start": 37 state = "send-transport"; 38 runFSM(); 39 break; 40 case "send-transport": 41 req = client.createRequest("host:transport:" + deviceId); 42 socket.send(req); 43 state = "wait-transport"; 44 break; 45 case "wait-transport": 46 if (!client.checkResponse(data, OKAY)) { 47 shutdown(); 48 return; 49 } 50 state = "send-shell"; 51 runFSM(); 52 break; 53 case "send-shell": 54 req = client.createRequest("shell:" + command); 55 socket.send(req); 56 state = "rec-shell"; 57 break; 58 case "rec-shell": 59 if (!client.checkResponse(data, OKAY)) { 60 shutdown(); 61 return; 62 } 63 state = "decode-shell"; 64 if (client.getBuffer(data).byteLength == 4) { 65 break; 66 } 67 ignoreResponseCode = true; 68 // eslint-disable-next-lined no-fallthrough 69 case "decode-shell": { 70 const decoder = new TextDecoder(); 71 const text = new Uint8Array( 72 client.getBuffer(data), 73 ignoreResponseCode ? 4 : 0 74 ); 75 stdout += decoder.decode(text); 76 break; 77 } 78 default: 79 dumpn("shell Unexpected State: " + state); 80 reject("UNEXPECTED_STATE"); 81 } 82 }; 83 84 const socket = client.connect(); 85 socket.s.onerror = function () { 86 dumpn("shell onerror"); 87 reject("SOCKET_ERROR"); 88 }; 89 90 socket.s.onopen = function () { 91 dumpn("shell onopen"); 92 state = "start"; 93 runFSM(); 94 }; 95 96 socket.s.onclose = function () { 97 resolve(stdout); 98 dumpn("shell onclose"); 99 }; 100 101 socket.s.ondata = function (event) { 102 dumpn("shell ondata"); 103 runFSM(event.data); 104 }; 105 }); 106 }; 107 108 exports.shell = shell;