adb-runtime.js (4022B)
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 "use strict"; 6 7 const { 8 prepareTCPConnection, 9 } = require("resource://devtools/client/shared/remote-debugging/adb/commands/index.js"); 10 const { 11 shell, 12 } = require("resource://devtools/client/shared/remote-debugging/adb/commands/index.js"); 13 14 class AdbRuntime { 15 constructor(adbDevice, socketPath) { 16 this._adbDevice = adbDevice; 17 this._socketPath = socketPath; 18 // Set a default version name in case versionName cannot be parsed. 19 this._versionName = ""; 20 } 21 22 async init() { 23 const packageName = this._packageName(); 24 const query = `dumpsys package ${packageName} | grep versionName`; 25 const versionNameString = await shell(this._adbDevice.id, query); 26 27 // The versionName can have different formats depending on the channel 28 // - `versionName=Nightly 191016 06:01\n` on Nightly 29 // - `versionName=2.1.0\n` on Release 30 // We use a very flexible regular expression to accommodate for those 31 // different formats. 32 const matches = versionNameString.match(/versionName=(.*)\n/); 33 if (matches?.[1]) { 34 this._versionName = matches[1]; 35 } 36 } 37 38 get id() { 39 return this._adbDevice.id + "|" + this._socketPath; 40 } 41 42 get isFenix() { 43 // Firefox Release uses "org.mozilla.firefox" 44 // Firefox Beta uses "org.mozilla.firefox_beta" 45 // Firefox Nightly uses "org.mozilla.fenix" 46 const isFirefox = 47 this._packageName().includes("org.mozilla.firefox") || 48 this._packageName().includes("org.mozilla.fenix"); 49 50 if (!isFirefox) { 51 return false; 52 } 53 54 // Firefox Release (based on Fenix) is not released in all regions yet, so 55 // we should still check for Fennec using the version number. 56 // Note that Fennec's versionName followed Firefox versions (eg "68.11.0"). 57 // We can find the main version number in it. Fenix on the other hand has 58 // version names such as "Nightly 200730 06:21". 59 const mainVersion = Number(this.versionName.split(".")[0]); 60 const isFennec = mainVersion === 68; 61 62 // Application is Fenix if this is a Firefox application with a version 63 // different from the Fennec version. 64 return !isFennec; 65 } 66 67 get deviceId() { 68 return this._adbDevice.id; 69 } 70 71 get deviceName() { 72 return this._adbDevice.name; 73 } 74 75 get versionName() { 76 return this._versionName; 77 } 78 79 get shortName() { 80 const packageName = this._packageName(); 81 82 switch (packageName) { 83 case "org.mozilla.firefox": 84 if (!this.isFenix) { 85 // Old Fennec release 86 return "Firefox (Fennec)"; 87 } 88 // Official Firefox app, based on Fenix 89 return "Firefox"; 90 case "org.mozilla.firefox_beta": 91 // Official Firefox Beta app, based on Fenix 92 return "Firefox Beta"; 93 case "org.mozilla.fenix": 94 case "org.mozilla.fenix.nightly": 95 // Official Firefox Nightly app, based on Fenix 96 return "Firefox Nightly"; 97 default: 98 // Unknown package name 99 return `Firefox (${packageName})`; 100 } 101 } 102 103 get socketPath() { 104 return this._socketPath; 105 } 106 107 get name() { 108 return `${this.shortName} on Android (${this.deviceName})`; 109 } 110 111 connect(connection) { 112 return prepareTCPConnection(this.deviceId, this._socketPath).then(port => { 113 connection.host = "localhost"; 114 connection.port = port; 115 connection.connect(); 116 }); 117 } 118 119 _packageName() { 120 // If using abstract socket address, it is "@org.mozilla.firefox/..." 121 // If using path base socket, it is "/data/data/<package>..."" 122 // Until Fennec 62 only supports path based UNIX domain socket, but 123 // Fennec 63+ supports both path based and abstract socket. 124 return this._socketPath.startsWith("@") 125 ? this._socketPath.substr(1).split("/")[0] 126 : this._socketPath.split("/")[3]; 127 } 128 } 129 exports.AdbRuntime = AdbRuntime;