web-ext 7.2.0 → 7.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +2 -2
  2. package/lib/cmd/build.js +18 -36
  3. package/lib/cmd/build.js.map +1 -1
  4. package/lib/cmd/docs.js +1 -0
  5. package/lib/cmd/docs.js.map +1 -1
  6. package/lib/cmd/index.js +3 -5
  7. package/lib/cmd/index.js.map +1 -1
  8. package/lib/cmd/lint.js +28 -17
  9. package/lib/cmd/lint.js.map +1 -1
  10. package/lib/cmd/run.js +19 -23
  11. package/lib/cmd/run.js.map +1 -1
  12. package/lib/cmd/sign.js +80 -47
  13. package/lib/cmd/sign.js.map +1 -1
  14. package/lib/config.js +18 -29
  15. package/lib/config.js.map +1 -1
  16. package/lib/errors.js +8 -18
  17. package/lib/errors.js.map +1 -1
  18. package/lib/extension-runners/base.js +2 -0
  19. package/lib/extension-runners/base.js.map +1 -1
  20. package/lib/extension-runners/chromium.js +36 -62
  21. package/lib/extension-runners/chromium.js.map +1 -1
  22. package/lib/extension-runners/firefox-android.js +65 -102
  23. package/lib/extension-runners/firefox-android.js.map +1 -1
  24. package/lib/extension-runners/firefox-desktop.js +29 -42
  25. package/lib/extension-runners/firefox-desktop.js.map +1 -1
  26. package/lib/extension-runners/index.js +33 -46
  27. package/lib/extension-runners/index.js.map +1 -1
  28. package/lib/firefox/index.js +59 -52
  29. package/lib/firefox/index.js.map +1 -1
  30. package/lib/firefox/package-identifiers.js +2 -0
  31. package/lib/firefox/package-identifiers.js.map +1 -1
  32. package/lib/firefox/preferences.js +14 -15
  33. package/lib/firefox/preferences.js.map +1 -1
  34. package/lib/firefox/rdp-client.js +16 -64
  35. package/lib/firefox/rdp-client.js.map +1 -1
  36. package/lib/firefox/remote.js +15 -30
  37. package/lib/firefox/remote.js.map +1 -1
  38. package/lib/main.js +4 -2
  39. package/lib/main.js.map +1 -1
  40. package/lib/program.js +74 -76
  41. package/lib/program.js.map +1 -1
  42. package/lib/util/adb.js +33 -63
  43. package/lib/util/adb.js.map +1 -1
  44. package/lib/util/artifacts.js +3 -5
  45. package/lib/util/artifacts.js.map +1 -1
  46. package/lib/util/desktop-notifier.js +1 -0
  47. package/lib/util/desktop-notifier.js.map +1 -1
  48. package/lib/util/file-exists.js +1 -2
  49. package/lib/util/file-exists.js.map +1 -1
  50. package/lib/util/file-filter.js +17 -19
  51. package/lib/util/file-filter.js.map +1 -1
  52. package/lib/util/is-directory.js +2 -1
  53. package/lib/util/is-directory.js.map +1 -1
  54. package/lib/util/logger.js +7 -12
  55. package/lib/util/logger.js.map +1 -1
  56. package/lib/util/manifest.js +6 -13
  57. package/lib/util/manifest.js.map +1 -1
  58. package/lib/util/promisify.js +7 -3
  59. package/lib/util/promisify.js.map +1 -1
  60. package/lib/util/stdin.js +2 -0
  61. package/lib/util/stdin.js.map +1 -1
  62. package/lib/util/submit-addon.js +288 -0
  63. package/lib/util/submit-addon.js.map +1 -0
  64. package/lib/util/temp-dir.js +8 -18
  65. package/lib/util/temp-dir.js.map +1 -1
  66. package/lib/util/updates.js +1 -1
  67. package/lib/util/updates.js.map +1 -1
  68. package/lib/watcher.js +14 -9
  69. package/lib/watcher.js.map +1 -1
  70. package/package.json +16 -14
@@ -1 +1 @@
1
- {"version":3,"file":"firefox-android.js","names":["path","readline","withTempDir","DefaultADBUtils","showDesktopNotification","defaultDesktopNotifications","MultiExtensionsReloadError","UsageError","WebExtError","defaultFirefoxApp","connectWithMaxRetries","defaultFirefoxConnector","findFreeTcpPort","createLogger","isTTY","setRawMode","log","import","meta","url","ignoredParams","profilePath","keepProfileChanges","browserConsole","preInstall","startUrl","args","DEFAULT_ADB_HOST","getIgnoredParamsWarningsMessage","optionName","FirefoxAndroidExtensionRunner","unixSocketDiscoveryRetryInterval","unixSocketDiscoveryMaxTime","constructor","params","cleanupCallbacks","Set","adbExtensionsPathBySourceDir","Map","reloadableExtensions","printIgnoredParamsWarnings","run","adbBin","adbHost","adbPort","ADBUtils","adbUtils","adbDevicesDiscoveryAndSelect","apkPackagesDiscoveryAndSelect","adbCheckRuntimePermissions","adbForceStopSelectedPackage","adbPrepareProfileDir","Promise","all","adbStartSelectedPackage","buildAndPushExtensions","adbDiscoveryAndForwardRDPUnixSocket","rdpInstallExtensions","getName","reloadAllExtensions","runnerName","reloadErrors","sourceDir","extensions","res","reloadExtensionBySourceDir","reloadError","Error","set","size","extensionSourceDir","addonId","get","buildAndPushExtension","remoteFirefox","reloadAddon","error","registerCleanup","fn","add","exit","selectedAdbDevice","selectedArtifactsDir","exiting","debug","clearArtifactsDir","getDeviceProfileDir","Object","keys","forEach","ignoredParam","warn","adbDevice","devices","discoverDevices","length","devicesMsg","map","dev","join","info","foundDevices","filter","device","JSON","stringify","firefoxApk","packages","discoverInstalledFirefoxAPKs","pkgsListMsg","pkgs","pkg","selectedFirefoxApk","filteredPackages","line","pkgsList","amForceStopAPK","androidVersion","getAndroidVersionNumber","Number","isNaN","requiredPermissions","ensureRequiredAPKRuntimePermissions","customPrefs","firefoxApp","adbRemoveOldArtifacts","profile","createProfile","app","foundOldArtifacts","detectOrRemoveOldArtifacts","getOrCreateArtifactsDir","deviceProfileDir","runShellCommand","pushFile","profileDir","firefoxApkComponent","startFirefoxAPK","buildSourceDir","tmpDir","extensionPath","extFileName","basename","adbExtensionPath","adbDiscoveryTimeout","stdin","process","handleCtrlC","str","key","ctrl","name","setUserAbortDiscovery","emitKeypressEvents","on","selectedRDPSocketFile","discoverRDPUnixSocket","maxDiscoveryTime","retryInterval","removeListener","tcpPort","forwardSocketSpec","startsWith","substr","setupForward","selectedTCPPort","firefoxClient","port","client","extension","installTemporaryAddon","then","installResult","addon","id"],"sources":["../../src/extension-runners/firefox-android.js"],"sourcesContent":["/* @flow */\n\n/**\n * This module provide an ExtensionRunner subclass that manage an extension executed\n * in a Firefox for Android instance.\n */\n\nimport path from 'path';\nimport readline from 'readline';\n\nimport {withTempDir} from '../util/temp-dir.js';\nimport DefaultADBUtils from '../util/adb.js';\nimport {\n showDesktopNotification as defaultDesktopNotifications,\n} from '../util/desktop-notifier.js';\nimport {\n MultiExtensionsReloadError,\n UsageError,\n WebExtError,\n} from '../errors.js';\nimport * as defaultFirefoxApp from '../firefox/index.js';\nimport {\n connectWithMaxRetries as defaultFirefoxConnector,\n findFreeTcpPort,\n} from '../firefox/remote.js';\nimport {createLogger} from '../util/logger.js';\nimport {isTTY, setRawMode} from '../util/stdin.js';\nimport type {\n ExtensionRunnerParams,\n ExtensionRunnerReloadResult,\n} from './base';\nimport type {\n FirefoxPreferences,\n} from '../firefox/preferences';\nimport type {\n FirefoxRDPResponseAddon,\n RemoteFirefox,\n} from '../firefox/remote';\nimport type {\n ExtensionBuildResult,\n} from '../cmd/build';\n\nconst log = createLogger(import.meta.url);\n\nconst ignoredParams = {\n profilePath: '--profile-path',\n keepProfileChanges: '--keep-profile-changes',\n browserConsole: '--browser-console',\n preInstall: '--pre-install',\n startUrl: '--start-url',\n args: '--args',\n};\n\n// Default adbHost to 127.0.0.1 to prevent issues with nodejs 17\n// (because if not specified adbkit may default to ipv6 while\n// adb may still only be listening on the ipv4 address),\n// see https://github.com/mozilla/web-ext/issues/2337.\nconst DEFAULT_ADB_HOST = '127.0.0.1';\n\nconst getIgnoredParamsWarningsMessage = (optionName) => {\n return `The Firefox for Android target does not support ${optionName}`;\n};\n\nexport type FirefoxAndroidExtensionRunnerParams = {|\n ...ExtensionRunnerParams,\n\n // Firefox specific.\n customPrefs?: FirefoxPreferences,\n\n // Not supported (currently ignored with logged warning).\n preInstall?: boolean,\n browserConsole?: boolean,\n\n // Firefox android injected dependencies.\n adbBin?: string,\n adbHost?: string,\n adbPort?: string,\n adbDevice?: string,\n adbDiscoveryTimeout?: number,\n adbRemoveOldArtifacts?: boolean,\n firefoxApk?: string,\n firefoxApkComponent?: string,\n\n // Injected Dependencies.\n firefoxApp: typeof defaultFirefoxApp,\n firefoxClient: typeof defaultFirefoxConnector,\n ADBUtils?: typeof DefaultADBUtils,\n buildSourceDir: (string, string) => Promise<ExtensionBuildResult>,\n desktopNotifications: typeof defaultDesktopNotifications,\n stdin?: stream$Readable,\n|};\n\n/**\n * Implements an IExtensionRunner which manages a Firefox for Android instance.\n */\nexport class FirefoxAndroidExtensionRunner {\n // Wait 3s before the next unix socket discovery loop.\n static unixSocketDiscoveryRetryInterval: number = 3 * 1000;\n // Wait for at most 3 minutes before giving up.\n static unixSocketDiscoveryMaxTime: number = 3 * 60 * 1000;\n\n params: FirefoxAndroidExtensionRunnerParams;\n adbUtils: DefaultADBUtils;\n exiting: boolean;\n selectedAdbDevice: string;\n selectedFirefoxApk: string;\n selectedArtifactsDir: string;\n selectedRDPSocketFile: string;\n selectedTCPPort: number;\n cleanupCallbacks: Set<Function>;\n adbExtensionsPathBySourceDir: Map<string, string>;\n reloadableExtensions: Map<string, string>;\n remoteFirefox: RemoteFirefox;\n\n constructor(params: FirefoxAndroidExtensionRunnerParams) {\n this.params = params;\n this.cleanupCallbacks = new Set();\n this.adbExtensionsPathBySourceDir = new Map();\n this.reloadableExtensions = new Map();\n\n // Print warning for not currently supported options (e.g. preInstall,\n // cloned profiles, browser console).\n this.printIgnoredParamsWarnings();\n }\n\n async run(): Promise<void> {\n const {\n adbBin,\n adbHost = DEFAULT_ADB_HOST,\n adbPort,\n ADBUtils = DefaultADBUtils,\n } = this.params;\n\n this.adbUtils = new ADBUtils({\n adbBin, adbHost, adbPort,\n });\n\n await this.adbDevicesDiscoveryAndSelect();\n await this.apkPackagesDiscoveryAndSelect();\n await this.adbCheckRuntimePermissions();\n await this.adbForceStopSelectedPackage();\n\n // Create profile prefs (with enabled remote RDP server), prepare the\n // artifacts and temporary directory on the selected device, and\n // push the profile preferences to the remote profile dir.\n await this.adbPrepareProfileDir();\n\n // NOTE: running Firefox for Android on the Android Emulator can be\n // pretty slow, we can run the following 3 steps in parallel to speed up\n // it a bit.\n await Promise.all([\n // Start Firefox for Android instance if not started yet.\n // (Fennec would run in an temporary profile and so it is explicitly\n // stopped, Fenix runs on its usual profile and so it may be already\n // running).\n this.adbStartSelectedPackage(),\n\n // Build and push to devices all the extension xpis\n // and keep track of the xpi built and uploaded by extension sourceDir.\n this.buildAndPushExtensions(),\n\n // Wait for RDP unix socket file created and\n // Create an ADB forward connection on a free tcp port\n this.adbDiscoveryAndForwardRDPUnixSocket(),\n ]);\n\n // Connect to RDP socket on the local tcp server, install all the pushed extension\n // and keep track of the built and installed extension by extension sourceDir.\n await this.rdpInstallExtensions();\n }\n\n // Method exported from the IExtensionRunner interface.\n\n /**\n * Returns the runner name.\n */\n getName(): string {\n return 'Firefox Android';\n }\n\n /**\n * Reloads all the extensions, collect any reload error and resolves to\n * an array composed by a single ExtensionRunnerReloadResult object.\n */\n async reloadAllExtensions(): Promise<Array<ExtensionRunnerReloadResult>> {\n const runnerName = this.getName();\n const reloadErrors = new Map();\n\n for (const {sourceDir} of this.params.extensions) {\n const [res] = await this.reloadExtensionBySourceDir(sourceDir);\n if (res.reloadError instanceof Error) {\n reloadErrors.set(sourceDir, res.reloadError);\n }\n }\n\n if (reloadErrors.size > 0) {\n return [{\n runnerName,\n reloadError: new MultiExtensionsReloadError(reloadErrors),\n }];\n }\n\n return [{runnerName}];\n }\n\n /**\n * Reloads a single extension, collect any reload error and resolves to\n * an array composed by a single ExtensionRunnerReloadResult object.\n */\n async reloadExtensionBySourceDir(\n extensionSourceDir: string\n ): Promise<Array<ExtensionRunnerReloadResult>> {\n const runnerName = this.getName();\n const addonId = this.reloadableExtensions.get(extensionSourceDir);\n\n if (!addonId) {\n return [{\n sourceDir: extensionSourceDir,\n reloadError: new WebExtError(\n 'Extension not reloadable: ' +\n `no addonId has been mapped to \"${extensionSourceDir}\"`\n ),\n runnerName,\n }];\n }\n\n try {\n await this.buildAndPushExtension(extensionSourceDir);\n await this.remoteFirefox.reloadAddon(addonId);\n } catch (error) {\n return [{\n sourceDir: extensionSourceDir,\n reloadError: error,\n runnerName,\n }];\n }\n\n return [{runnerName, sourceDir: extensionSourceDir}];\n }\n\n /**\n * Register a callback to be called when the runner has been exited\n * (e.g. the Firefox instance exits or the user has requested web-ext\n * to exit).\n */\n registerCleanup(fn: Function): void {\n this.cleanupCallbacks.add(fn);\n }\n\n /**\n * Exits the runner, by closing the managed Firefox instance.\n */\n async exit(): Promise<void> {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedArtifactsDir,\n } = this;\n\n this.exiting = true;\n\n // If a Firefox for Android instance has been started,\n // we should ensure that it has been stopped when we exit.\n await this.adbForceStopSelectedPackage();\n\n if (selectedArtifactsDir) {\n log.debug('Cleaning up artifacts directory on the Android device...');\n await adbUtils.clearArtifactsDir(selectedAdbDevice);\n }\n\n // Call all the registered cleanup callbacks.\n for (const fn of this.cleanupCallbacks) {\n try {\n fn();\n } catch (error) {\n log.error(error);\n }\n }\n }\n\n // Private helper methods.\n\n getDeviceProfileDir(): string {\n return `${this.selectedArtifactsDir}/profile`;\n }\n\n printIgnoredParamsWarnings() {\n Object.keys(ignoredParams).forEach((ignoredParam) => {\n if (this.params[ignoredParam]) {\n log.warn(\n getIgnoredParamsWarningsMessage(ignoredParams[ignoredParam])\n );\n }\n });\n }\n\n async adbDevicesDiscoveryAndSelect() {\n const {adbUtils} = this;\n const {adbDevice} = this.params;\n let devices = [];\n\n log.debug('Listing android devices');\n devices = await adbUtils.discoverDevices();\n\n if (devices.length === 0) {\n throw new UsageError(\n 'No Android device found through ADB. ' +\n 'Make sure the device is connected and USB debugging is enabled.'\n );\n }\n\n if (!adbDevice) {\n const devicesMsg = devices.map((dev) => ` - ${dev}`).join('\\n');\n log.info(`\\nAndroid devices found:\\n${devicesMsg}`);\n throw new UsageError(\n 'Select an android device using --android-device=<name>');\n }\n\n const foundDevices = devices.filter((device) => {\n return device === adbDevice;\n });\n\n if (foundDevices.length === 0) {\n const devicesMsg = JSON.stringify(devices);\n throw new UsageError(\n `Android device ${adbDevice} was not found in list: ${devicesMsg}`);\n }\n\n this.selectedAdbDevice = foundDevices[0];\n log.info(`Selected ADB device: ${this.selectedAdbDevice}`);\n }\n\n async apkPackagesDiscoveryAndSelect() {\n const {\n adbUtils,\n selectedAdbDevice,\n params: {\n firefoxApk,\n },\n } = this;\n // Discovery and select a Firefox for Android version.\n const packages = await adbUtils.discoverInstalledFirefoxAPKs(\n selectedAdbDevice,\n firefoxApk\n );\n\n if (packages.length === 0) {\n throw new UsageError(\n 'No Firefox packages were found on the selected Android device');\n }\n\n const pkgsListMsg = (pkgs) => {\n return pkgs.map((pkg) => ` - ${ pkg}`).join('\\n');\n };\n\n if (!firefoxApk) {\n log.info(`\\nPackages found:\\n${pkgsListMsg(packages)}`);\n\n if (packages.length > 1) {\n throw new UsageError('Select one of the packages using --firefox-apk');\n }\n\n // If only one APK has been found, select it even if it has not been\n // specified explicitly on the comment line.\n this.selectedFirefoxApk = packages[0];\n log.info(`Selected Firefox for Android APK: ${this.selectedFirefoxApk}`);\n return;\n }\n\n const filteredPackages = packages.filter((line) => line === firefoxApk);\n\n if (filteredPackages.length === 0) {\n const pkgsList = pkgsListMsg(filteredPackages);\n throw new UsageError(\n `Package ${firefoxApk} was not found in list: ${pkgsList}`\n );\n }\n\n this.selectedFirefoxApk = filteredPackages[0];\n log.debug(`Selected Firefox for Android APK: ${this.selectedFirefoxApk}`);\n }\n\n async adbForceStopSelectedPackage() {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedFirefoxApk,\n } = this;\n\n log.info(`Stopping existing instances of ${selectedFirefoxApk}...`);\n await adbUtils.amForceStopAPK(selectedAdbDevice, selectedFirefoxApk);\n }\n\n async adbCheckRuntimePermissions() {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedFirefoxApk,\n } = this;\n\n log.debug(`Discovering Android version for ${selectedAdbDevice}...`);\n\n const androidVersion = await adbUtils.getAndroidVersionNumber(\n selectedAdbDevice\n );\n\n if (typeof androidVersion !== 'number' || Number.isNaN(androidVersion)) {\n throw new WebExtError(`Invalid Android version: ${androidVersion}`);\n }\n\n log.debug(`Detected Android version ${androidVersion}`);\n\n if (androidVersion < 23) {\n return;\n }\n\n log.debug('Checking read/write permissions needed for web-ext' +\n `on ${selectedFirefoxApk}...`);\n\n // Runtime permissions needed to Firefox to be able to access the\n // xpi file uploaded to the android device or emulator.\n const requiredPermissions = [\n 'android.permission.READ_EXTERNAL_STORAGE',\n ];\n\n await adbUtils.ensureRequiredAPKRuntimePermissions(\n selectedAdbDevice, selectedFirefoxApk, requiredPermissions\n );\n }\n\n async adbPrepareProfileDir() {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedFirefoxApk,\n params: {\n customPrefs,\n firefoxApp,\n adbRemoveOldArtifacts,\n },\n } = this;\n // Create the preferences file and the Fennec temporary profile.\n log.debug(`Preparing a temporary profile for ${selectedFirefoxApk}...`);\n\n const profile = await firefoxApp.createProfile({\n app: 'fennec',\n customPrefs,\n });\n\n // Check if there are any artifacts dirs from previous runs and\n // automatically remove them if adbRemoteOldArtifacts is true.\n const foundOldArtifacts = await adbUtils.detectOrRemoveOldArtifacts(\n selectedAdbDevice, adbRemoveOldArtifacts\n );\n\n if (foundOldArtifacts) {\n if (adbRemoveOldArtifacts) {\n log.info('Old web-ext artifacts have been found and removed ' +\n `from ${selectedAdbDevice} device`);\n } else {\n log.warn(\n `Old artifacts directories have been found on ${selectedAdbDevice} ` +\n 'device. Use --adb-remove-old-artifacts to remove them automatically.'\n );\n }\n }\n\n // Choose a artifacts dir name for the assets pushed to the\n // Android device.\n this.selectedArtifactsDir = await adbUtils.getOrCreateArtifactsDir(\n selectedAdbDevice\n );\n\n const deviceProfileDir = this.getDeviceProfileDir();\n\n await adbUtils.runShellCommand(selectedAdbDevice, [\n 'mkdir', '-p', deviceProfileDir,\n ]);\n await adbUtils.pushFile(selectedAdbDevice,\n path.join(profile.profileDir, 'user.js'),\n `${deviceProfileDir}/user.js`);\n\n log.debug(`Created temporary profile at ${deviceProfileDir}.`);\n }\n\n async adbStartSelectedPackage() {\n const {\n adbUtils,\n selectedFirefoxApk,\n selectedAdbDevice,\n params: {\n firefoxApkComponent,\n },\n } = this;\n\n const deviceProfileDir = this.getDeviceProfileDir();\n\n log.info(`Starting ${selectedFirefoxApk}...`);\n\n log.debug(`Using profile ${deviceProfileDir} (ignored by Fenix)`);\n\n await adbUtils.startFirefoxAPK(\n selectedAdbDevice,\n selectedFirefoxApk,\n firefoxApkComponent,\n deviceProfileDir,\n );\n }\n\n async buildAndPushExtension(sourceDir: string) {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedArtifactsDir,\n params: {\n buildSourceDir,\n },\n } = this;\n\n await withTempDir(async (tmpDir) => {\n const {extensionPath} = await buildSourceDir(sourceDir, tmpDir.path());\n\n const extFileName = path.basename(extensionPath, '.zip');\n\n let adbExtensionPath = this.adbExtensionsPathBySourceDir.get(sourceDir);\n\n if (!adbExtensionPath) {\n adbExtensionPath = `${selectedArtifactsDir}/${extFileName}.xpi`;\n }\n\n log.debug(`Uploading ${extFileName} on the android device`);\n\n await adbUtils.pushFile(\n selectedAdbDevice, extensionPath, adbExtensionPath\n );\n\n log.debug(`Upload completed: ${adbExtensionPath}`);\n\n this.adbExtensionsPathBySourceDir.set(sourceDir, adbExtensionPath);\n });\n }\n\n async buildAndPushExtensions() {\n for (const {sourceDir} of this.params.extensions) {\n await this.buildAndPushExtension(sourceDir);\n }\n }\n\n async adbDiscoveryAndForwardRDPUnixSocket() {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedFirefoxApk,\n params: {\n adbDiscoveryTimeout,\n },\n } = this;\n\n const stdin = this.params.stdin || process.stdin;\n\n const {\n unixSocketDiscoveryRetryInterval,\n } = FirefoxAndroidExtensionRunner;\n\n let {\n unixSocketDiscoveryMaxTime,\n } = FirefoxAndroidExtensionRunner;\n\n if (typeof adbDiscoveryTimeout === 'number') {\n unixSocketDiscoveryMaxTime = adbDiscoveryTimeout;\n }\n\n const handleCtrlC = (str, key) => {\n if (key.ctrl && key.name === 'c') {\n adbUtils.setUserAbortDiscovery(true);\n }\n };\n\n // TODO: use noInput property to decide if we should\n // disable direct keypress handling.\n if (isTTY(stdin)) {\n readline.emitKeypressEvents(stdin);\n setRawMode(stdin, true);\n\n stdin.on('keypress', handleCtrlC);\n }\n\n try {\n // Got a debugger socket file to connect.\n this.selectedRDPSocketFile = (\n await adbUtils.discoverRDPUnixSocket(\n selectedAdbDevice, selectedFirefoxApk, {\n maxDiscoveryTime: unixSocketDiscoveryMaxTime,\n retryInterval: unixSocketDiscoveryRetryInterval,\n }\n )\n );\n } finally {\n if (isTTY(stdin)) {\n stdin.removeListener('keypress', handleCtrlC);\n }\n }\n\n log.debug(`RDP Socket File selected: ${this.selectedRDPSocketFile}`);\n\n const tcpPort = await findFreeTcpPort();\n\n // Log the choosen tcp port at info level (useful to the user to be able\n // to connect the Firefox DevTools to the Firefox for Android instance).\n log.info(`You can connect to this Android device on TCP port ${tcpPort}`);\n\n const forwardSocketSpec = this.selectedRDPSocketFile.startsWith('@') ?\n `localabstract:${this.selectedRDPSocketFile.substr(1)}`\n : `localfilesystem:${this.selectedRDPSocketFile}`;\n\n await adbUtils.setupForward(\n selectedAdbDevice,\n forwardSocketSpec,\n `tcp:${tcpPort}`\n );\n\n this.selectedTCPPort = tcpPort;\n }\n\n async rdpInstallExtensions() {\n const {\n selectedTCPPort,\n params: {\n extensions,\n firefoxClient,\n },\n } = this;\n\n const remoteFirefox = this.remoteFirefox = await firefoxClient({\n port: selectedTCPPort,\n });\n\n // Exit and cleanup the extension runner if the connection to the\n // remote Firefox for Android instance has been closed.\n remoteFirefox.client.on('end', () => {\n if (!this.exiting) {\n log.info('Exiting the device because Firefox for Android disconnected');\n this.exit();\n }\n });\n\n // Install all the temporary addons.\n for (const extension of extensions) {\n const {sourceDir} = extension;\n const adbExtensionPath = this.adbExtensionsPathBySourceDir.get(\n sourceDir\n );\n\n if (!adbExtensionPath) {\n throw new WebExtError(\n `ADB extension path for \"${sourceDir}\" was unexpectedly empty`\n );\n }\n\n const addonId = await (\n remoteFirefox.installTemporaryAddon(adbExtensionPath)\n .then((installResult: FirefoxRDPResponseAddon) => {\n return installResult.addon.id;\n })\n );\n\n if (!addonId) {\n throw new WebExtError(\n 'Received an empty addonId from ' +\n `remoteFirefox.installTemporaryAddon(\"${adbExtensionPath}\")`\n );\n }\n\n this.reloadableExtensions.set(extension.sourceDir, addonId);\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"firefox-android.js","names":["path","readline","withTempDir","DefaultADBUtils","showDesktopNotification","defaultDesktopNotifications","MultiExtensionsReloadError","UsageError","WebExtError","defaultFirefoxApp","connectWithMaxRetries","defaultFirefoxConnector","findFreeTcpPort","createLogger","isTTY","setRawMode","log","import","meta","url","ignoredParams","profilePath","keepProfileChanges","browserConsole","preInstall","startUrl","args","DEFAULT_ADB_HOST","getIgnoredParamsWarningsMessage","optionName","FirefoxAndroidExtensionRunner","unixSocketDiscoveryRetryInterval","unixSocketDiscoveryMaxTime","constructor","params","cleanupCallbacks","Set","adbExtensionsPathBySourceDir","Map","reloadableExtensions","printIgnoredParamsWarnings","run","adbBin","adbHost","adbPort","ADBUtils","adbUtils","adbDevicesDiscoveryAndSelect","apkPackagesDiscoveryAndSelect","adbCheckRuntimePermissions","adbForceStopSelectedPackage","adbPrepareProfileDir","Promise","all","adbStartSelectedPackage","buildAndPushExtensions","adbDiscoveryAndForwardRDPUnixSocket","rdpInstallExtensions","getName","reloadAllExtensions","runnerName","reloadErrors","sourceDir","extensions","res","reloadExtensionBySourceDir","reloadError","Error","set","size","extensionSourceDir","addonId","get","buildAndPushExtension","remoteFirefox","reloadAddon","error","registerCleanup","fn","add","exit","selectedAdbDevice","selectedArtifactsDir","exiting","debug","clearArtifactsDir","getDeviceProfileDir","Object","keys","forEach","ignoredParam","warn","adbDevice","devices","discoverDevices","length","devicesMsg","map","dev","join","info","foundDevices","filter","device","JSON","stringify","firefoxApk","packages","discoverInstalledFirefoxAPKs","pkgsListMsg","pkgs","pkg","selectedFirefoxApk","filteredPackages","line","pkgsList","amForceStopAPK","androidVersion","getAndroidVersionNumber","Number","isNaN","requiredPermissions","ensureRequiredAPKRuntimePermissions","customPrefs","firefoxApp","adbRemoveOldArtifacts","profile","createProfile","app","foundOldArtifacts","detectOrRemoveOldArtifacts","getOrCreateArtifactsDir","deviceProfileDir","runShellCommand","pushFile","profileDir","firefoxApkComponent","startFirefoxAPK","buildSourceDir","tmpDir","extensionPath","extFileName","basename","adbExtensionPath","adbDiscoveryTimeout","stdin","process","handleCtrlC","str","key","ctrl","name","setUserAbortDiscovery","emitKeypressEvents","on","selectedRDPSocketFile","discoverRDPUnixSocket","maxDiscoveryTime","retryInterval","removeListener","tcpPort","forwardSocketSpec","startsWith","substr","setupForward","selectedTCPPort","firefoxClient","port","client","extension","installTemporaryAddon","then","installResult","addon","id"],"sources":["../../src/extension-runners/firefox-android.js"],"sourcesContent":["/* @flow */\n\n/**\n * This module provide an ExtensionRunner subclass that manage an extension executed\n * in a Firefox for Android instance.\n */\n\nimport path from 'path';\nimport readline from 'readline';\n\nimport {withTempDir} from '../util/temp-dir.js';\nimport DefaultADBUtils from '../util/adb.js';\nimport {\n showDesktopNotification as defaultDesktopNotifications,\n} from '../util/desktop-notifier.js';\nimport {\n MultiExtensionsReloadError,\n UsageError,\n WebExtError,\n} from '../errors.js';\nimport * as defaultFirefoxApp from '../firefox/index.js';\nimport {\n connectWithMaxRetries as defaultFirefoxConnector,\n findFreeTcpPort,\n} from '../firefox/remote.js';\nimport {createLogger} from '../util/logger.js';\nimport {isTTY, setRawMode} from '../util/stdin.js';\nimport type {\n ExtensionRunnerParams,\n ExtensionRunnerReloadResult,\n} from './base';\nimport type {\n FirefoxPreferences,\n} from '../firefox/preferences';\nimport type {\n FirefoxRDPResponseAddon,\n RemoteFirefox,\n} from '../firefox/remote';\nimport type {\n ExtensionBuildResult,\n} from '../cmd/build';\n\nconst log = createLogger(import.meta.url);\n\nconst ignoredParams = {\n profilePath: '--profile-path',\n keepProfileChanges: '--keep-profile-changes',\n browserConsole: '--browser-console',\n preInstall: '--pre-install',\n startUrl: '--start-url',\n args: '--args',\n};\n\n// Default adbHost to 127.0.0.1 to prevent issues with nodejs 17\n// (because if not specified adbkit may default to ipv6 while\n// adb may still only be listening on the ipv4 address),\n// see https://github.com/mozilla/web-ext/issues/2337.\nconst DEFAULT_ADB_HOST = '127.0.0.1';\n\nconst getIgnoredParamsWarningsMessage = (optionName) => {\n return `The Firefox for Android target does not support ${optionName}`;\n};\n\nexport type FirefoxAndroidExtensionRunnerParams = {|\n ...ExtensionRunnerParams,\n\n // Firefox specific.\n customPrefs?: FirefoxPreferences,\n\n // Not supported (currently ignored with logged warning).\n preInstall?: boolean,\n browserConsole?: boolean,\n\n // Firefox android injected dependencies.\n adbBin?: string,\n adbHost?: string,\n adbPort?: string,\n adbDevice?: string,\n adbDiscoveryTimeout?: number,\n adbRemoveOldArtifacts?: boolean,\n firefoxApk?: string,\n firefoxApkComponent?: string,\n\n // Injected Dependencies.\n firefoxApp: typeof defaultFirefoxApp,\n firefoxClient: typeof defaultFirefoxConnector,\n ADBUtils?: typeof DefaultADBUtils,\n buildSourceDir: (string, string) => Promise<ExtensionBuildResult>,\n desktopNotifications: typeof defaultDesktopNotifications,\n stdin?: stream$Readable,\n|};\n\n/**\n * Implements an IExtensionRunner which manages a Firefox for Android instance.\n */\nexport class FirefoxAndroidExtensionRunner {\n // Wait 3s before the next unix socket discovery loop.\n static unixSocketDiscoveryRetryInterval: number = 3 * 1000;\n // Wait for at most 3 minutes before giving up.\n static unixSocketDiscoveryMaxTime: number = 3 * 60 * 1000;\n\n params: FirefoxAndroidExtensionRunnerParams;\n adbUtils: DefaultADBUtils;\n exiting: boolean;\n selectedAdbDevice: string;\n selectedFirefoxApk: string;\n selectedArtifactsDir: string;\n selectedRDPSocketFile: string;\n selectedTCPPort: number;\n cleanupCallbacks: Set<Function>;\n adbExtensionsPathBySourceDir: Map<string, string>;\n reloadableExtensions: Map<string, string>;\n remoteFirefox: RemoteFirefox;\n\n constructor(params: FirefoxAndroidExtensionRunnerParams) {\n this.params = params;\n this.cleanupCallbacks = new Set();\n this.adbExtensionsPathBySourceDir = new Map();\n this.reloadableExtensions = new Map();\n\n // Print warning for not currently supported options (e.g. preInstall,\n // cloned profiles, browser console).\n this.printIgnoredParamsWarnings();\n }\n\n async run(): Promise<void> {\n const {\n adbBin,\n adbHost = DEFAULT_ADB_HOST,\n adbPort,\n ADBUtils = DefaultADBUtils,\n } = this.params;\n\n this.adbUtils = new ADBUtils({\n adbBin, adbHost, adbPort,\n });\n\n await this.adbDevicesDiscoveryAndSelect();\n await this.apkPackagesDiscoveryAndSelect();\n await this.adbCheckRuntimePermissions();\n await this.adbForceStopSelectedPackage();\n\n // Create profile prefs (with enabled remote RDP server), prepare the\n // artifacts and temporary directory on the selected device, and\n // push the profile preferences to the remote profile dir.\n await this.adbPrepareProfileDir();\n\n // NOTE: running Firefox for Android on the Android Emulator can be\n // pretty slow, we can run the following 3 steps in parallel to speed up\n // it a bit.\n await Promise.all([\n // Start Firefox for Android instance if not started yet.\n // (Fennec would run in an temporary profile and so it is explicitly\n // stopped, Fenix runs on its usual profile and so it may be already\n // running).\n this.adbStartSelectedPackage(),\n\n // Build and push to devices all the extension xpis\n // and keep track of the xpi built and uploaded by extension sourceDir.\n this.buildAndPushExtensions(),\n\n // Wait for RDP unix socket file created and\n // Create an ADB forward connection on a free tcp port\n this.adbDiscoveryAndForwardRDPUnixSocket(),\n ]);\n\n // Connect to RDP socket on the local tcp server, install all the pushed extension\n // and keep track of the built and installed extension by extension sourceDir.\n await this.rdpInstallExtensions();\n }\n\n // Method exported from the IExtensionRunner interface.\n\n /**\n * Returns the runner name.\n */\n getName(): string {\n return 'Firefox Android';\n }\n\n /**\n * Reloads all the extensions, collect any reload error and resolves to\n * an array composed by a single ExtensionRunnerReloadResult object.\n */\n async reloadAllExtensions(): Promise<Array<ExtensionRunnerReloadResult>> {\n const runnerName = this.getName();\n const reloadErrors = new Map();\n\n for (const {sourceDir} of this.params.extensions) {\n const [res] = await this.reloadExtensionBySourceDir(sourceDir);\n if (res.reloadError instanceof Error) {\n reloadErrors.set(sourceDir, res.reloadError);\n }\n }\n\n if (reloadErrors.size > 0) {\n return [{\n runnerName,\n reloadError: new MultiExtensionsReloadError(reloadErrors),\n }];\n }\n\n return [{runnerName}];\n }\n\n /**\n * Reloads a single extension, collect any reload error and resolves to\n * an array composed by a single ExtensionRunnerReloadResult object.\n */\n async reloadExtensionBySourceDir(\n extensionSourceDir: string\n ): Promise<Array<ExtensionRunnerReloadResult>> {\n const runnerName = this.getName();\n const addonId = this.reloadableExtensions.get(extensionSourceDir);\n\n if (!addonId) {\n return [{\n sourceDir: extensionSourceDir,\n reloadError: new WebExtError(\n 'Extension not reloadable: ' +\n `no addonId has been mapped to \"${extensionSourceDir}\"`\n ),\n runnerName,\n }];\n }\n\n try {\n await this.buildAndPushExtension(extensionSourceDir);\n await this.remoteFirefox.reloadAddon(addonId);\n } catch (error) {\n return [{\n sourceDir: extensionSourceDir,\n reloadError: error,\n runnerName,\n }];\n }\n\n return [{runnerName, sourceDir: extensionSourceDir}];\n }\n\n /**\n * Register a callback to be called when the runner has been exited\n * (e.g. the Firefox instance exits or the user has requested web-ext\n * to exit).\n */\n registerCleanup(fn: Function): void {\n this.cleanupCallbacks.add(fn);\n }\n\n /**\n * Exits the runner, by closing the managed Firefox instance.\n */\n async exit(): Promise<void> {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedArtifactsDir,\n } = this;\n\n this.exiting = true;\n\n // If a Firefox for Android instance has been started,\n // we should ensure that it has been stopped when we exit.\n await this.adbForceStopSelectedPackage();\n\n if (selectedArtifactsDir) {\n log.debug('Cleaning up artifacts directory on the Android device...');\n await adbUtils.clearArtifactsDir(selectedAdbDevice);\n }\n\n // Call all the registered cleanup callbacks.\n for (const fn of this.cleanupCallbacks) {\n try {\n fn();\n } catch (error) {\n log.error(error);\n }\n }\n }\n\n // Private helper methods.\n\n getDeviceProfileDir(): string {\n return `${this.selectedArtifactsDir}/profile`;\n }\n\n printIgnoredParamsWarnings() {\n Object.keys(ignoredParams).forEach((ignoredParam) => {\n if (this.params[ignoredParam]) {\n log.warn(\n getIgnoredParamsWarningsMessage(ignoredParams[ignoredParam])\n );\n }\n });\n }\n\n async adbDevicesDiscoveryAndSelect() {\n const {adbUtils} = this;\n const {adbDevice} = this.params;\n let devices = [];\n\n log.debug('Listing android devices');\n devices = await adbUtils.discoverDevices();\n\n if (devices.length === 0) {\n throw new UsageError(\n 'No Android device found through ADB. ' +\n 'Make sure the device is connected and USB debugging is enabled.'\n );\n }\n\n if (!adbDevice) {\n const devicesMsg = devices.map((dev) => ` - ${dev}`).join('\\n');\n log.info(`\\nAndroid devices found:\\n${devicesMsg}`);\n throw new UsageError(\n 'Select an android device using --android-device=<name>');\n }\n\n const foundDevices = devices.filter((device) => {\n return device === adbDevice;\n });\n\n if (foundDevices.length === 0) {\n const devicesMsg = JSON.stringify(devices);\n throw new UsageError(\n `Android device ${adbDevice} was not found in list: ${devicesMsg}`);\n }\n\n this.selectedAdbDevice = foundDevices[0];\n log.info(`Selected ADB device: ${this.selectedAdbDevice}`);\n }\n\n async apkPackagesDiscoveryAndSelect() {\n const {\n adbUtils,\n selectedAdbDevice,\n params: {\n firefoxApk,\n },\n } = this;\n // Discovery and select a Firefox for Android version.\n const packages = await adbUtils.discoverInstalledFirefoxAPKs(\n selectedAdbDevice,\n firefoxApk\n );\n\n if (packages.length === 0) {\n throw new UsageError(\n 'No Firefox packages were found on the selected Android device');\n }\n\n const pkgsListMsg = (pkgs) => {\n return pkgs.map((pkg) => ` - ${ pkg}`).join('\\n');\n };\n\n if (!firefoxApk) {\n log.info(`\\nPackages found:\\n${pkgsListMsg(packages)}`);\n\n if (packages.length > 1) {\n throw new UsageError('Select one of the packages using --firefox-apk');\n }\n\n // If only one APK has been found, select it even if it has not been\n // specified explicitly on the comment line.\n this.selectedFirefoxApk = packages[0];\n log.info(`Selected Firefox for Android APK: ${this.selectedFirefoxApk}`);\n return;\n }\n\n const filteredPackages = packages.filter((line) => line === firefoxApk);\n\n if (filteredPackages.length === 0) {\n const pkgsList = pkgsListMsg(filteredPackages);\n throw new UsageError(\n `Package ${firefoxApk} was not found in list: ${pkgsList}`\n );\n }\n\n this.selectedFirefoxApk = filteredPackages[0];\n log.debug(`Selected Firefox for Android APK: ${this.selectedFirefoxApk}`);\n }\n\n async adbForceStopSelectedPackage() {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedFirefoxApk,\n } = this;\n\n log.info(`Stopping existing instances of ${selectedFirefoxApk}...`);\n await adbUtils.amForceStopAPK(selectedAdbDevice, selectedFirefoxApk);\n }\n\n async adbCheckRuntimePermissions() {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedFirefoxApk,\n } = this;\n\n log.debug(`Discovering Android version for ${selectedAdbDevice}...`);\n\n const androidVersion = await adbUtils.getAndroidVersionNumber(\n selectedAdbDevice\n );\n\n if (typeof androidVersion !== 'number' || Number.isNaN(androidVersion)) {\n throw new WebExtError(`Invalid Android version: ${androidVersion}`);\n }\n\n log.debug(`Detected Android version ${androidVersion}`);\n\n if (androidVersion < 23) {\n return;\n }\n\n log.debug('Checking read/write permissions needed for web-ext' +\n `on ${selectedFirefoxApk}...`);\n\n // Runtime permissions needed to Firefox to be able to access the\n // xpi file uploaded to the android device or emulator.\n const requiredPermissions = [\n 'android.permission.READ_EXTERNAL_STORAGE',\n ];\n\n await adbUtils.ensureRequiredAPKRuntimePermissions(\n selectedAdbDevice, selectedFirefoxApk, requiredPermissions\n );\n }\n\n async adbPrepareProfileDir() {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedFirefoxApk,\n params: {\n customPrefs,\n firefoxApp,\n adbRemoveOldArtifacts,\n },\n } = this;\n // Create the preferences file and the Fennec temporary profile.\n log.debug(`Preparing a temporary profile for ${selectedFirefoxApk}...`);\n\n const profile = await firefoxApp.createProfile({\n app: 'fennec',\n customPrefs,\n });\n\n // Check if there are any artifacts dirs from previous runs and\n // automatically remove them if adbRemoteOldArtifacts is true.\n const foundOldArtifacts = await adbUtils.detectOrRemoveOldArtifacts(\n selectedAdbDevice, adbRemoveOldArtifacts\n );\n\n if (foundOldArtifacts) {\n if (adbRemoveOldArtifacts) {\n log.info('Old web-ext artifacts have been found and removed ' +\n `from ${selectedAdbDevice} device`);\n } else {\n log.warn(\n `Old artifacts directories have been found on ${selectedAdbDevice} ` +\n 'device. Use --adb-remove-old-artifacts to remove them automatically.'\n );\n }\n }\n\n // Choose a artifacts dir name for the assets pushed to the\n // Android device.\n this.selectedArtifactsDir = await adbUtils.getOrCreateArtifactsDir(\n selectedAdbDevice\n );\n\n const deviceProfileDir = this.getDeviceProfileDir();\n\n await adbUtils.runShellCommand(selectedAdbDevice, [\n 'mkdir', '-p', deviceProfileDir,\n ]);\n await adbUtils.pushFile(selectedAdbDevice,\n path.join(profile.profileDir, 'user.js'),\n `${deviceProfileDir}/user.js`);\n\n log.debug(`Created temporary profile at ${deviceProfileDir}.`);\n }\n\n async adbStartSelectedPackage() {\n const {\n adbUtils,\n selectedFirefoxApk,\n selectedAdbDevice,\n params: {\n firefoxApkComponent,\n },\n } = this;\n\n const deviceProfileDir = this.getDeviceProfileDir();\n\n log.info(`Starting ${selectedFirefoxApk}...`);\n\n log.debug(`Using profile ${deviceProfileDir} (ignored by Fenix)`);\n\n await adbUtils.startFirefoxAPK(\n selectedAdbDevice,\n selectedFirefoxApk,\n firefoxApkComponent,\n deviceProfileDir,\n );\n }\n\n async buildAndPushExtension(sourceDir: string) {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedArtifactsDir,\n params: {\n buildSourceDir,\n },\n } = this;\n\n await withTempDir(async (tmpDir) => {\n const {extensionPath} = await buildSourceDir(sourceDir, tmpDir.path());\n\n const extFileName = path.basename(extensionPath, '.zip');\n\n let adbExtensionPath = this.adbExtensionsPathBySourceDir.get(sourceDir);\n\n if (!adbExtensionPath) {\n adbExtensionPath = `${selectedArtifactsDir}/${extFileName}.xpi`;\n }\n\n log.debug(`Uploading ${extFileName} on the android device`);\n\n await adbUtils.pushFile(\n selectedAdbDevice, extensionPath, adbExtensionPath\n );\n\n log.debug(`Upload completed: ${adbExtensionPath}`);\n\n this.adbExtensionsPathBySourceDir.set(sourceDir, adbExtensionPath);\n });\n }\n\n async buildAndPushExtensions() {\n for (const {sourceDir} of this.params.extensions) {\n await this.buildAndPushExtension(sourceDir);\n }\n }\n\n async adbDiscoveryAndForwardRDPUnixSocket() {\n const {\n adbUtils,\n selectedAdbDevice,\n selectedFirefoxApk,\n params: {\n adbDiscoveryTimeout,\n },\n } = this;\n\n const stdin = this.params.stdin || process.stdin;\n\n const {\n unixSocketDiscoveryRetryInterval,\n } = FirefoxAndroidExtensionRunner;\n\n let {\n unixSocketDiscoveryMaxTime,\n } = FirefoxAndroidExtensionRunner;\n\n if (typeof adbDiscoveryTimeout === 'number') {\n unixSocketDiscoveryMaxTime = adbDiscoveryTimeout;\n }\n\n const handleCtrlC = (str, key) => {\n if (key.ctrl && key.name === 'c') {\n adbUtils.setUserAbortDiscovery(true);\n }\n };\n\n // TODO: use noInput property to decide if we should\n // disable direct keypress handling.\n if (isTTY(stdin)) {\n readline.emitKeypressEvents(stdin);\n setRawMode(stdin, true);\n\n stdin.on('keypress', handleCtrlC);\n }\n\n try {\n // Got a debugger socket file to connect.\n this.selectedRDPSocketFile = (\n await adbUtils.discoverRDPUnixSocket(\n selectedAdbDevice, selectedFirefoxApk, {\n maxDiscoveryTime: unixSocketDiscoveryMaxTime,\n retryInterval: unixSocketDiscoveryRetryInterval,\n }\n )\n );\n } finally {\n if (isTTY(stdin)) {\n stdin.removeListener('keypress', handleCtrlC);\n }\n }\n\n log.debug(`RDP Socket File selected: ${this.selectedRDPSocketFile}`);\n\n const tcpPort = await findFreeTcpPort();\n\n // Log the choosen tcp port at info level (useful to the user to be able\n // to connect the Firefox DevTools to the Firefox for Android instance).\n log.info(`You can connect to this Android device on TCP port ${tcpPort}`);\n\n const forwardSocketSpec = this.selectedRDPSocketFile.startsWith('@') ?\n `localabstract:${this.selectedRDPSocketFile.substr(1)}`\n : `localfilesystem:${this.selectedRDPSocketFile}`;\n\n await adbUtils.setupForward(\n selectedAdbDevice,\n forwardSocketSpec,\n `tcp:${tcpPort}`\n );\n\n this.selectedTCPPort = tcpPort;\n }\n\n async rdpInstallExtensions() {\n const {\n selectedTCPPort,\n params: {\n extensions,\n firefoxClient,\n },\n } = this;\n\n const remoteFirefox = this.remoteFirefox = await firefoxClient({\n port: selectedTCPPort,\n });\n\n // Exit and cleanup the extension runner if the connection to the\n // remote Firefox for Android instance has been closed.\n remoteFirefox.client.on('end', () => {\n if (!this.exiting) {\n log.info('Exiting the device because Firefox for Android disconnected');\n this.exit();\n }\n });\n\n // Install all the temporary addons.\n for (const extension of extensions) {\n const {sourceDir} = extension;\n const adbExtensionPath = this.adbExtensionsPathBySourceDir.get(\n sourceDir\n );\n\n if (!adbExtensionPath) {\n throw new WebExtError(\n `ADB extension path for \"${sourceDir}\" was unexpectedly empty`\n );\n }\n\n const addonId = await (\n remoteFirefox.installTemporaryAddon(adbExtensionPath)\n .then((installResult: FirefoxRDPResponseAddon) => {\n return installResult.addon.id;\n })\n );\n\n if (!addonId) {\n throw new WebExtError(\n 'Received an empty addonId from ' +\n `remoteFirefox.installTemporaryAddon(\"${adbExtensionPath}\")`\n );\n }\n\n this.reloadableExtensions.set(extension.sourceDir, addonId);\n }\n }\n}\n"],"mappings":"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"}
@@ -1,90 +1,89 @@
1
+
2
+
1
3
  /**
2
4
  * This module provide an ExtensionRunner subclass that manage an extension executed
3
5
  * in a Firefox for Desktop instance.
4
6
  */
7
+
5
8
  // Import flow types from npm dependencies.
9
+
6
10
  import { MultiExtensionsReloadError, RemoteTempInstallNotSupported, WebExtError } from '../errors.js';
7
11
  import * as defaultFirefoxApp from '../firefox/index.js';
8
12
  import { connectWithMaxRetries as defaultFirefoxConnector } from '../firefox/remote.js';
9
- import { createLogger } from '../util/logger.js'; // Import flow types from project files.
13
+ import { createLogger } from '../util/logger.js';
14
+ // Import flow types from project files.
10
15
 
11
16
  const log = createLogger(import.meta.url);
17
+
12
18
  /**
13
19
  * Implements an IExtensionRunner which manages a Firefox Desktop instance.
14
20
  */
15
-
16
21
  export class FirefoxDesktopExtensionRunner {
17
22
  // Map extensions sourceDir to their related addon ids.
23
+
18
24
  constructor(params) {
19
25
  this.params = params;
20
26
  this.reloadableExtensions = new Map();
21
27
  this.cleanupCallbacks = new Set();
22
- } // Method exported from the IExtensionRunner interface.
28
+ }
29
+
30
+ // Method exported from the IExtensionRunner interface.
23
31
 
24
32
  /**
25
33
  * Returns the runner name.
26
34
  */
27
-
28
-
29
35
  getName() {
30
36
  return 'Firefox Desktop';
31
37
  }
38
+
32
39
  /**
33
40
  * Setup the Firefox Profile and run a Firefox Desktop instance.
34
41
  */
35
-
36
-
37
42
  async run() {
38
43
  // Get a firefox profile with the custom Prefs set (a new or a cloned one).
39
44
  // Pre-install extensions as proxy if needed (and disable auto-reload if you do)
40
- await this.setupProfileDir(); // (if reload is enabled):
45
+ await this.setupProfileDir();
46
+
47
+ // (if reload is enabled):
41
48
  // - Connect to the firefox instance on RDP
42
49
  // - Install any extension if needed (if not installed as proxy)
43
50
  // - Keep track of the extension id assigned in a map with the sourceDir as a key
44
-
45
51
  await this.startFirefoxInstance();
46
52
  }
53
+
47
54
  /**
48
55
  * Reloads all the extensions, collect any reload error and resolves to
49
56
  * an array composed by a single ExtensionRunnerReloadResult object.
50
57
  */
51
-
52
-
53
58
  async reloadAllExtensions() {
54
59
  const runnerName = this.getName();
55
60
  const reloadErrors = new Map();
56
-
57
61
  for (const {
58
62
  sourceDir
59
63
  } of this.params.extensions) {
60
64
  const [res] = await this.reloadExtensionBySourceDir(sourceDir);
61
-
62
65
  if (res.reloadError instanceof Error) {
63
66
  reloadErrors.set(sourceDir, res.reloadError);
64
67
  }
65
68
  }
66
-
67
69
  if (reloadErrors.size > 0) {
68
70
  return [{
69
71
  runnerName,
70
72
  reloadError: new MultiExtensionsReloadError(reloadErrors)
71
73
  }];
72
74
  }
73
-
74
75
  return [{
75
76
  runnerName
76
77
  }];
77
78
  }
79
+
78
80
  /**
79
81
  * Reloads a single extension, collect any reload error and resolves to
80
82
  * an array composed by a single ExtensionRunnerReloadResult object.
81
83
  */
82
-
83
-
84
84
  async reloadExtensionBySourceDir(extensionSourceDir) {
85
85
  const runnerName = this.getName();
86
86
  const addonId = this.reloadableExtensions.get(extensionSourceDir);
87
-
88
87
  if (!addonId) {
89
88
  return [{
90
89
  sourceDir: extensionSourceDir,
@@ -92,7 +91,6 @@ export class FirefoxDesktopExtensionRunner {
92
91
  runnerName
93
92
  }];
94
93
  }
95
-
96
94
  try {
97
95
  await this.remoteFirefox.reloadAddon(addonId);
98
96
  } catch (error) {
@@ -102,35 +100,32 @@ export class FirefoxDesktopExtensionRunner {
102
100
  runnerName
103
101
  }];
104
102
  }
105
-
106
103
  return [{
107
104
  runnerName,
108
105
  sourceDir: extensionSourceDir
109
106
  }];
110
107
  }
108
+
111
109
  /**
112
110
  * Register a callback to be called when the runner has been exited
113
111
  * (e.g. the Firefox instance exits or the user has requested web-ext
114
112
  * to exit).
115
113
  */
116
-
117
-
118
114
  registerCleanup(fn) {
119
115
  this.cleanupCallbacks.add(fn);
120
116
  }
117
+
121
118
  /**
122
119
  * Exits the runner, by closing the managed Firefox instance.
123
120
  */
124
-
125
-
126
121
  async exit() {
127
122
  if (!this.runningInfo || !this.runningInfo.firefox) {
128
123
  throw new WebExtError('No firefox instance is currently running');
129
124
  }
130
-
131
125
  this.runningInfo.firefox.kill();
132
- } // Private helper methods.
126
+ }
133
127
 
128
+ // Private helper methods.
134
129
 
135
130
  async setupProfileDir() {
136
131
  const {
@@ -141,7 +136,6 @@ export class FirefoxDesktopExtensionRunner {
141
136
  profilePath,
142
137
  firefoxApp
143
138
  } = this.params;
144
-
145
139
  if (profilePath) {
146
140
  if (keepProfileChanges) {
147
141
  log.debug(`Using Firefox profile from ${profilePath}`);
@@ -159,9 +153,9 @@ export class FirefoxDesktopExtensionRunner {
159
153
  this.profile = await firefoxApp.createProfile({
160
154
  customPrefs
161
155
  });
162
- } // preInstall the extensions if needed.
163
-
156
+ }
164
157
 
158
+ // preInstall the extensions if needed.
165
159
  if (preInstall) {
166
160
  for (const extension of extensions) {
167
161
  await firefoxApp.installExtension({
@@ -173,10 +167,10 @@ export class FirefoxDesktopExtensionRunner {
173
167
  }
174
168
  }
175
169
  }
176
-
177
170
  async startFirefoxInstance() {
178
171
  const {
179
172
  browserConsole,
173
+ devtools,
180
174
  extensions,
181
175
  firefoxBinary,
182
176
  preInstall,
@@ -186,27 +180,23 @@ export class FirefoxDesktopExtensionRunner {
186
180
  args
187
181
  } = this.params;
188
182
  const binaryArgs = [];
189
-
190
183
  if (browserConsole) {
191
184
  binaryArgs.push('-jsconsole');
192
185
  }
193
-
194
186
  if (startUrl) {
195
187
  const urls = Array.isArray(startUrl) ? startUrl : [startUrl];
196
-
197
188
  for (const url of urls) {
198
189
  binaryArgs.push('--url', url);
199
190
  }
200
191
  }
201
-
202
192
  if (args) {
203
193
  binaryArgs.push(...args);
204
194
  }
205
-
206
195
  this.runningInfo = await firefoxApp.run(this.profile, {
207
196
  firefoxBinary,
208
197
  binaryArgs,
209
- extensions
198
+ extensions,
199
+ devtools
210
200
  });
211
201
  this.runningInfo.firefox.on('close', () => {
212
202
  for (const cleanupCb of this.cleanupCallbacks) {
@@ -217,22 +207,20 @@ export class FirefoxDesktopExtensionRunner {
217
207
  }
218
208
  }
219
209
  });
220
-
221
210
  if (!preInstall) {
222
211
  const remoteFirefox = this.remoteFirefox = await firefoxClient({
223
212
  port: this.runningInfo.debuggerPort
224
- }); // Install all the temporary addons.
213
+ });
225
214
 
215
+ // Install all the temporary addons.
226
216
  for (const extension of extensions) {
227
217
  try {
228
- const addonId = await remoteFirefox.installTemporaryAddon(extension.sourceDir).then(installResult => {
218
+ const addonId = await remoteFirefox.installTemporaryAddon(extension.sourceDir, devtools).then(installResult => {
229
219
  return installResult.addon.id;
230
220
  });
231
-
232
221
  if (!addonId) {
233
222
  throw new WebExtError('Unexpected missing addonId in the installAsTemporaryAddon result');
234
223
  }
235
-
236
224
  this.reloadableExtensions.set(extension.sourceDir, addonId);
237
225
  } catch (error) {
238
226
  if (error instanceof RemoteTempInstallNotSupported) {
@@ -245,6 +233,5 @@ export class FirefoxDesktopExtensionRunner {
245
233
  }
246
234
  }
247
235
  }
248
-
249
236
  }
250
237
  //# sourceMappingURL=firefox-desktop.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"firefox-desktop.js","names":["MultiExtensionsReloadError","RemoteTempInstallNotSupported","WebExtError","defaultFirefoxApp","connectWithMaxRetries","defaultFirefoxConnector","createLogger","log","import","meta","url","FirefoxDesktopExtensionRunner","constructor","params","reloadableExtensions","Map","cleanupCallbacks","Set","getName","run","setupProfileDir","startFirefoxInstance","reloadAllExtensions","runnerName","reloadErrors","sourceDir","extensions","res","reloadExtensionBySourceDir","reloadError","Error","set","size","extensionSourceDir","addonId","get","remoteFirefox","reloadAddon","error","registerCleanup","fn","add","exit","runningInfo","firefox","kill","customPrefs","keepProfileChanges","preInstall","profilePath","firefoxApp","debug","profile","useProfile","copyProfile","createProfile","extension","installExtension","asProxy","extensionPath","manifestData","browserConsole","firefoxBinary","startUrl","firefoxClient","args","binaryArgs","push","urls","Array","isArray","on","cleanupCb","port","debuggerPort","installTemporaryAddon","then","installResult","addon","id","String"],"sources":["../../src/extension-runners/firefox-desktop.js"],"sourcesContent":["/* @flow */\n\n/**\n * This module provide an ExtensionRunner subclass that manage an extension executed\n * in a Firefox for Desktop instance.\n */\n\n// Import flow types from npm dependencies.\nimport type FirefoxProfile from 'firefox-profile';\n\nimport {\n MultiExtensionsReloadError,\n RemoteTempInstallNotSupported,\n WebExtError,\n} from '../errors.js';\nimport * as defaultFirefoxApp from '../firefox/index.js';\nimport {\n connectWithMaxRetries as defaultFirefoxConnector,\n} from '../firefox/remote.js';\nimport {createLogger} from '../util/logger.js';\n// Import flow types from project files.\nimport type {\n FirefoxRDPResponseAddon,\n RemoteFirefox,\n} from '../firefox/remote';\nimport type {\n ExtensionRunnerParams,\n ExtensionRunnerReloadResult,\n} from './base';\nimport type {FirefoxPreferences} from '../firefox/preferences';\nimport type {FirefoxInfo} from '../firefox/index'; // eslint-disable-line import/named\n\ntype FirefoxDesktopSpecificRunnerParams = {|\n customPrefs?: FirefoxPreferences,\n browserConsole: boolean,\n firefoxBinary: string,\n preInstall: boolean,\n\n // Firefox desktop injected dependencies.\n firefoxApp: typeof defaultFirefoxApp,\n firefoxClient: typeof defaultFirefoxConnector,\n|};\n\nexport type FirefoxDesktopExtensionRunnerParams = {|\n ...ExtensionRunnerParams,\n // Firefox desktop CLI params.\n ...FirefoxDesktopSpecificRunnerParams,\n|};\n\nconst log = createLogger(import.meta.url);\n\n\n/**\n * Implements an IExtensionRunner which manages a Firefox Desktop instance.\n */\nexport class FirefoxDesktopExtensionRunner {\n cleanupCallbacks: Set<Function>;\n params: FirefoxDesktopExtensionRunnerParams;\n profile: FirefoxProfile;\n // Map extensions sourceDir to their related addon ids.\n reloadableExtensions: Map<string, string>;\n remoteFirefox: RemoteFirefox;\n runningInfo: FirefoxInfo;\n\n constructor(params: FirefoxDesktopExtensionRunnerParams) {\n this.params = params;\n\n this.reloadableExtensions = new Map();\n this.cleanupCallbacks = new Set();\n }\n\n // Method exported from the IExtensionRunner interface.\n\n /**\n * Returns the runner name.\n */\n getName(): string {\n return 'Firefox Desktop';\n }\n\n /**\n * Setup the Firefox Profile and run a Firefox Desktop instance.\n */\n async run(): Promise<void> {\n // Get a firefox profile with the custom Prefs set (a new or a cloned one).\n // Pre-install extensions as proxy if needed (and disable auto-reload if you do)\n await this.setupProfileDir();\n\n // (if reload is enabled):\n // - Connect to the firefox instance on RDP\n // - Install any extension if needed (if not installed as proxy)\n // - Keep track of the extension id assigned in a map with the sourceDir as a key\n await this.startFirefoxInstance();\n }\n\n /**\n * Reloads all the extensions, collect any reload error and resolves to\n * an array composed by a single ExtensionRunnerReloadResult object.\n */\n async reloadAllExtensions(): Promise<Array<ExtensionRunnerReloadResult>> {\n const runnerName = this.getName();\n const reloadErrors = new Map();\n for (const {sourceDir} of this.params.extensions) {\n const [res] = await this.reloadExtensionBySourceDir(sourceDir);\n if (res.reloadError instanceof Error) {\n reloadErrors.set(sourceDir, res.reloadError);\n }\n }\n\n if (reloadErrors.size > 0) {\n return [{\n runnerName,\n reloadError: new MultiExtensionsReloadError(reloadErrors),\n }];\n }\n\n return [{runnerName}];\n }\n\n /**\n * Reloads a single extension, collect any reload error and resolves to\n * an array composed by a single ExtensionRunnerReloadResult object.\n */\n async reloadExtensionBySourceDir(\n extensionSourceDir: string\n ): Promise<Array<ExtensionRunnerReloadResult>> {\n const runnerName = this.getName();\n const addonId = this.reloadableExtensions.get(extensionSourceDir);\n\n if (!addonId) {\n return [{\n sourceDir: extensionSourceDir,\n reloadError: new WebExtError(\n 'Extension not reloadable: ' +\n `no addonId has been mapped to \"${extensionSourceDir}\"`\n ),\n runnerName,\n }];\n }\n\n try {\n await this.remoteFirefox.reloadAddon(addonId);\n } catch (error) {\n return [{\n sourceDir: extensionSourceDir,\n reloadError: error,\n runnerName,\n }];\n }\n\n return [{runnerName, sourceDir: extensionSourceDir}];\n }\n\n /**\n * Register a callback to be called when the runner has been exited\n * (e.g. the Firefox instance exits or the user has requested web-ext\n * to exit).\n */\n registerCleanup(fn: Function): void {\n this.cleanupCallbacks.add(fn);\n }\n\n /**\n * Exits the runner, by closing the managed Firefox instance.\n */\n async exit(): Promise<void> {\n if (!this.runningInfo || !this.runningInfo.firefox) {\n throw new WebExtError('No firefox instance is currently running');\n }\n\n this.runningInfo.firefox.kill();\n }\n\n // Private helper methods.\n\n async setupProfileDir() {\n const {\n customPrefs,\n extensions,\n keepProfileChanges,\n preInstall,\n profilePath,\n firefoxApp,\n } = this.params;\n\n if (profilePath) {\n if (keepProfileChanges) {\n log.debug(`Using Firefox profile from ${profilePath}`);\n this.profile = await firefoxApp.useProfile(profilePath, {customPrefs});\n } else {\n log.debug(`Copying Firefox profile from ${profilePath}`);\n this.profile = await firefoxApp.copyProfile(profilePath, {customPrefs});\n }\n } else {\n log.debug('Creating new Firefox profile');\n this.profile = await firefoxApp.createProfile({customPrefs});\n }\n\n // preInstall the extensions if needed.\n if (preInstall) {\n for (const extension of extensions) {\n await firefoxApp.installExtension({\n asProxy: true,\n extensionPath: extension.sourceDir,\n manifestData: extension.manifestData,\n profile: this.profile,\n });\n }\n }\n }\n\n async startFirefoxInstance() {\n const {\n browserConsole,\n extensions,\n firefoxBinary,\n preInstall,\n startUrl,\n firefoxApp,\n firefoxClient,\n args,\n } = this.params;\n\n const binaryArgs = [];\n\n if (browserConsole) {\n binaryArgs.push('-jsconsole');\n }\n if (startUrl) {\n const urls = Array.isArray(startUrl) ? startUrl : [startUrl];\n for (const url of urls) {\n binaryArgs.push('--url', url);\n }\n }\n\n if (args) {\n binaryArgs.push(...args);\n }\n\n this.runningInfo = await firefoxApp.run(this.profile, {\n firefoxBinary,\n binaryArgs,\n extensions,\n });\n\n this.runningInfo.firefox.on('close', () => {\n for (const cleanupCb of this.cleanupCallbacks) {\n try {\n cleanupCb();\n } catch (error) {\n log.error(`Exception on executing cleanup callback: ${error}`);\n }\n }\n });\n\n if (!preInstall) {\n const remoteFirefox = this.remoteFirefox = await firefoxClient({\n port: this.runningInfo.debuggerPort,\n });\n\n // Install all the temporary addons.\n for (const extension of extensions) {\n try {\n const addonId = await (\n remoteFirefox.installTemporaryAddon(extension.sourceDir)\n .then((installResult: FirefoxRDPResponseAddon) => {\n return installResult.addon.id;\n })\n );\n\n if (!addonId) {\n throw new WebExtError(\n 'Unexpected missing addonId in the installAsTemporaryAddon result'\n );\n }\n\n this.reloadableExtensions.set(extension.sourceDir, addonId);\n } catch (error) {\n if (error instanceof RemoteTempInstallNotSupported) {\n log.debug(`Caught: ${String(error)}`);\n throw new WebExtError(\n 'Temporary add-on installation is not supported in this version' +\n ' of Firefox (you need Firefox 49 or higher). For older Firefox' +\n ' versions, use --pre-install'\n );\n } else {\n throw error;\n }\n }\n }\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"firefox-desktop.js","names":["MultiExtensionsReloadError","RemoteTempInstallNotSupported","WebExtError","defaultFirefoxApp","connectWithMaxRetries","defaultFirefoxConnector","createLogger","log","import","meta","url","FirefoxDesktopExtensionRunner","constructor","params","reloadableExtensions","Map","cleanupCallbacks","Set","getName","run","setupProfileDir","startFirefoxInstance","reloadAllExtensions","runnerName","reloadErrors","sourceDir","extensions","res","reloadExtensionBySourceDir","reloadError","Error","set","size","extensionSourceDir","addonId","get","remoteFirefox","reloadAddon","error","registerCleanup","fn","add","exit","runningInfo","firefox","kill","customPrefs","keepProfileChanges","preInstall","profilePath","firefoxApp","debug","profile","useProfile","copyProfile","createProfile","extension","installExtension","asProxy","extensionPath","manifestData","browserConsole","devtools","firefoxBinary","startUrl","firefoxClient","args","binaryArgs","push","urls","Array","isArray","on","cleanupCb","port","debuggerPort","installTemporaryAddon","then","installResult","addon","id","String"],"sources":["../../src/extension-runners/firefox-desktop.js"],"sourcesContent":["/* @flow */\n\n/**\n * This module provide an ExtensionRunner subclass that manage an extension executed\n * in a Firefox for Desktop instance.\n */\n\n// Import flow types from npm dependencies.\nimport type FirefoxProfile from 'firefox-profile';\n\nimport {\n MultiExtensionsReloadError,\n RemoteTempInstallNotSupported,\n WebExtError,\n} from '../errors.js';\nimport * as defaultFirefoxApp from '../firefox/index.js';\nimport {\n connectWithMaxRetries as defaultFirefoxConnector,\n} from '../firefox/remote.js';\nimport {createLogger} from '../util/logger.js';\n// Import flow types from project files.\nimport type {\n FirefoxRDPResponseAddon,\n RemoteFirefox,\n} from '../firefox/remote';\nimport type {\n ExtensionRunnerParams,\n ExtensionRunnerReloadResult,\n} from './base';\nimport type {FirefoxPreferences} from '../firefox/preferences';\nimport type {FirefoxInfo} from '../firefox/index'; // eslint-disable-line import/named\n\ntype FirefoxDesktopSpecificRunnerParams = {|\n customPrefs?: FirefoxPreferences,\n browserConsole: boolean,\n devtools: boolean,\n firefoxBinary: string,\n preInstall: boolean,\n\n // Firefox desktop injected dependencies.\n firefoxApp: typeof defaultFirefoxApp,\n firefoxClient: typeof defaultFirefoxConnector,\n|};\n\nexport type FirefoxDesktopExtensionRunnerParams = {|\n ...ExtensionRunnerParams,\n // Firefox desktop CLI params.\n ...FirefoxDesktopSpecificRunnerParams,\n|};\n\nconst log = createLogger(import.meta.url);\n\n\n/**\n * Implements an IExtensionRunner which manages a Firefox Desktop instance.\n */\nexport class FirefoxDesktopExtensionRunner {\n cleanupCallbacks: Set<Function>;\n params: FirefoxDesktopExtensionRunnerParams;\n profile: FirefoxProfile;\n // Map extensions sourceDir to their related addon ids.\n reloadableExtensions: Map<string, string>;\n remoteFirefox: RemoteFirefox;\n runningInfo: FirefoxInfo;\n\n constructor(params: FirefoxDesktopExtensionRunnerParams) {\n this.params = params;\n\n this.reloadableExtensions = new Map();\n this.cleanupCallbacks = new Set();\n }\n\n // Method exported from the IExtensionRunner interface.\n\n /**\n * Returns the runner name.\n */\n getName(): string {\n return 'Firefox Desktop';\n }\n\n /**\n * Setup the Firefox Profile and run a Firefox Desktop instance.\n */\n async run(): Promise<void> {\n // Get a firefox profile with the custom Prefs set (a new or a cloned one).\n // Pre-install extensions as proxy if needed (and disable auto-reload if you do)\n await this.setupProfileDir();\n\n // (if reload is enabled):\n // - Connect to the firefox instance on RDP\n // - Install any extension if needed (if not installed as proxy)\n // - Keep track of the extension id assigned in a map with the sourceDir as a key\n await this.startFirefoxInstance();\n }\n\n /**\n * Reloads all the extensions, collect any reload error and resolves to\n * an array composed by a single ExtensionRunnerReloadResult object.\n */\n async reloadAllExtensions(): Promise<Array<ExtensionRunnerReloadResult>> {\n const runnerName = this.getName();\n const reloadErrors = new Map();\n for (const {sourceDir} of this.params.extensions) {\n const [res] = await this.reloadExtensionBySourceDir(sourceDir);\n if (res.reloadError instanceof Error) {\n reloadErrors.set(sourceDir, res.reloadError);\n }\n }\n\n if (reloadErrors.size > 0) {\n return [{\n runnerName,\n reloadError: new MultiExtensionsReloadError(reloadErrors),\n }];\n }\n\n return [{runnerName}];\n }\n\n /**\n * Reloads a single extension, collect any reload error and resolves to\n * an array composed by a single ExtensionRunnerReloadResult object.\n */\n async reloadExtensionBySourceDir(\n extensionSourceDir: string\n ): Promise<Array<ExtensionRunnerReloadResult>> {\n const runnerName = this.getName();\n const addonId = this.reloadableExtensions.get(extensionSourceDir);\n\n if (!addonId) {\n return [{\n sourceDir: extensionSourceDir,\n reloadError: new WebExtError(\n 'Extension not reloadable: ' +\n `no addonId has been mapped to \"${extensionSourceDir}\"`\n ),\n runnerName,\n }];\n }\n\n try {\n await this.remoteFirefox.reloadAddon(addonId);\n } catch (error) {\n return [{\n sourceDir: extensionSourceDir,\n reloadError: error,\n runnerName,\n }];\n }\n\n return [{runnerName, sourceDir: extensionSourceDir}];\n }\n\n /**\n * Register a callback to be called when the runner has been exited\n * (e.g. the Firefox instance exits or the user has requested web-ext\n * to exit).\n */\n registerCleanup(fn: Function): void {\n this.cleanupCallbacks.add(fn);\n }\n\n /**\n * Exits the runner, by closing the managed Firefox instance.\n */\n async exit(): Promise<void> {\n if (!this.runningInfo || !this.runningInfo.firefox) {\n throw new WebExtError('No firefox instance is currently running');\n }\n\n this.runningInfo.firefox.kill();\n }\n\n // Private helper methods.\n\n async setupProfileDir() {\n const {\n customPrefs,\n extensions,\n keepProfileChanges,\n preInstall,\n profilePath,\n firefoxApp,\n } = this.params;\n\n if (profilePath) {\n if (keepProfileChanges) {\n log.debug(`Using Firefox profile from ${profilePath}`);\n this.profile = await firefoxApp.useProfile(profilePath, {customPrefs});\n } else {\n log.debug(`Copying Firefox profile from ${profilePath}`);\n this.profile = await firefoxApp.copyProfile(profilePath, {customPrefs});\n }\n } else {\n log.debug('Creating new Firefox profile');\n this.profile = await firefoxApp.createProfile({customPrefs});\n }\n\n // preInstall the extensions if needed.\n if (preInstall) {\n for (const extension of extensions) {\n await firefoxApp.installExtension({\n asProxy: true,\n extensionPath: extension.sourceDir,\n manifestData: extension.manifestData,\n profile: this.profile,\n });\n }\n }\n }\n\n async startFirefoxInstance() {\n const {\n browserConsole,\n devtools,\n extensions,\n firefoxBinary,\n preInstall,\n startUrl,\n firefoxApp,\n firefoxClient,\n args,\n } = this.params;\n\n const binaryArgs = [];\n\n if (browserConsole) {\n binaryArgs.push('-jsconsole');\n }\n if (startUrl) {\n const urls = Array.isArray(startUrl) ? startUrl : [startUrl];\n for (const url of urls) {\n binaryArgs.push('--url', url);\n }\n }\n\n if (args) {\n binaryArgs.push(...args);\n }\n\n this.runningInfo = await firefoxApp.run(this.profile, {\n firefoxBinary,\n binaryArgs,\n extensions,\n devtools,\n });\n\n this.runningInfo.firefox.on('close', () => {\n for (const cleanupCb of this.cleanupCallbacks) {\n try {\n cleanupCb();\n } catch (error) {\n log.error(`Exception on executing cleanup callback: ${error}`);\n }\n }\n });\n\n if (!preInstall) {\n const remoteFirefox = this.remoteFirefox = await firefoxClient({\n port: this.runningInfo.debuggerPort,\n });\n\n // Install all the temporary addons.\n for (const extension of extensions) {\n try {\n const addonId = await (\n remoteFirefox.installTemporaryAddon(extension.sourceDir, devtools)\n .then((installResult: FirefoxRDPResponseAddon) => {\n return installResult.addon.id;\n })\n );\n\n if (!addonId) {\n throw new WebExtError(\n 'Unexpected missing addonId in the installAsTemporaryAddon result'\n );\n }\n\n this.reloadableExtensions.set(extension.sourceDir, addonId);\n } catch (error) {\n if (error instanceof RemoteTempInstallNotSupported) {\n log.debug(`Caught: ${String(error)}`);\n throw new WebExtError(\n 'Temporary add-on installation is not supported in this version' +\n ' of Firefox (you need Firefox 49 or higher). For older Firefox' +\n ' versions, use --pre-install'\n );\n } else {\n throw error;\n }\n }\n }\n }\n }\n}\n"],"mappings":"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"}