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
package/lib/errors.js CHANGED
@@ -1,64 +1,59 @@
1
+
1
2
  import ExtendableError from 'es6-error';
3
+
2
4
  /*
3
5
  * Base error for all custom web-ext errors.
4
6
  */
5
-
6
7
  export class WebExtError extends ExtendableError {
7
8
  constructor(message) {
8
9
  super(message);
9
10
  }
10
-
11
11
  }
12
+
12
13
  /*
13
14
  * The class for errors that can be fixed by the developer.
14
15
  */
15
-
16
16
  export class UsageError extends WebExtError {
17
17
  constructor(message) {
18
18
  super(message);
19
19
  }
20
-
21
20
  }
21
+
22
22
  /*
23
23
  * The manifest for the extension is invalid (or missing).
24
24
  */
25
-
26
25
  export class InvalidManifest extends UsageError {
27
26
  constructor(message) {
28
27
  super(message);
29
28
  }
30
-
31
29
  }
30
+
32
31
  /*
33
32
  * The remote Firefox does not support temporary add-on installation.
34
33
  */
35
-
36
34
  export class RemoteTempInstallNotSupported extends WebExtError {
37
35
  constructor(message) {
38
36
  super(message);
39
37
  }
40
-
41
38
  }
39
+
42
40
  /*
43
41
  * The errors collected when reloading all extensions at once
44
42
  * (initialized from a map of errors by extensionSourceDir string).
45
43
  */
46
-
47
44
  export class MultiExtensionsReloadError extends WebExtError {
48
45
  constructor(errorsMap) {
49
46
  let errors = '';
50
-
51
47
  for (const [sourceDir, error] of errorsMap) {
52
48
  const msg = String(error);
53
49
  errors += `\nError on extension loaded from ${sourceDir}: ${msg}\n`;
54
50
  }
55
-
56
51
  const message = `Reload errors: ${errors}`;
57
52
  super(message);
58
53
  this.errorsBySourceDir = errorsMap;
59
54
  }
60
-
61
55
  }
56
+
62
57
  /*
63
58
  * Sugar-y way to catch only instances of a certain error.
64
59
  *
@@ -72,7 +67,6 @@ export class MultiExtensionsReloadError extends WebExtError {
72
67
  * All other errors will be re-thrown.
73
68
  *
74
69
  */
75
-
76
70
  export function onlyInstancesOf(predicate, errorHandler) {
77
71
  return error => {
78
72
  if (error instanceof predicate) {
@@ -82,6 +76,7 @@ export function onlyInstancesOf(predicate, errorHandler) {
82
76
  }
83
77
  };
84
78
  }
79
+
85
80
  /*
86
81
  * Sugar-y way to catch only errors having certain code(s).
87
82
  *
@@ -102,11 +97,9 @@ export function onlyInstancesOf(predicate, errorHandler) {
102
97
  * All other errors will be re-thrown.
103
98
  *
104
99
  */
105
-
106
100
  export function onlyErrorsWithCode(codeWanted, errorHandler) {
107
101
  return error => {
108
102
  let throwError = true;
109
-
110
103
  if (Array.isArray(codeWanted)) {
111
104
  if (codeWanted.indexOf(error.code) !== -1 || codeWanted.indexOf(error.errno) !== -1) {
112
105
  throwError = false;
@@ -114,11 +107,9 @@ export function onlyErrorsWithCode(codeWanted, errorHandler) {
114
107
  } else if (error.code === codeWanted || error.errno === codeWanted) {
115
108
  throwError = false;
116
109
  }
117
-
118
110
  if (throwError) {
119
111
  throw error;
120
112
  }
121
-
122
113
  return errorHandler(error);
123
114
  };
124
115
  }
@@ -128,7 +119,6 @@ export function isErrorWithCode(codeWanted, error) {
128
119
  } else if (error.code === codeWanted) {
129
120
  return true;
130
121
  }
131
-
132
122
  return false;
133
123
  }
134
124
  //# sourceMappingURL=errors.js.map
package/lib/errors.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":["ExtendableError","WebExtError","constructor","message","UsageError","InvalidManifest","RemoteTempInstallNotSupported","MultiExtensionsReloadError","errorsMap","errors","sourceDir","error","msg","String","errorsBySourceDir","onlyInstancesOf","predicate","errorHandler","onlyErrorsWithCode","codeWanted","throwError","Array","isArray","indexOf","code","errno","isErrorWithCode"],"sources":["../src/errors.js"],"sourcesContent":["/* @flow */\nimport ExtendableError from 'es6-error';\n\n\n/*\n * Base error for all custom web-ext errors.\n */\nexport class WebExtError extends ExtendableError {\n constructor(message: string) {\n super(message);\n }\n}\n\n\n/*\n * The class for errors that can be fixed by the developer.\n */\nexport class UsageError extends WebExtError {\n constructor(message: string) {\n super(message);\n }\n}\n\n\n/*\n * The manifest for the extension is invalid (or missing).\n */\nexport class InvalidManifest extends UsageError {\n constructor(message: string) {\n super(message);\n }\n}\n\n\n/*\n * The remote Firefox does not support temporary add-on installation.\n */\nexport class RemoteTempInstallNotSupported extends WebExtError {\n constructor(message: string) {\n super(message);\n }\n}\n\n/*\n * The errors collected when reloading all extensions at once\n * (initialized from a map of errors by extensionSourceDir string).\n */\nexport class MultiExtensionsReloadError extends WebExtError {\n constructor(errorsMap: Map<string, Error>) {\n let errors = '';\n for (const [sourceDir, error] of errorsMap) {\n const msg = String(error);\n errors += `\\nError on extension loaded from ${sourceDir}: ${msg}\\n`;\n }\n const message = `Reload errors: ${errors}`;\n\n super(message);\n this.errorsBySourceDir = errorsMap;\n }\n}\n\n/*\n * Sugar-y way to catch only instances of a certain error.\n *\n * Usage:\n *\n * Promise.reject(SyntaxError)\n * .catch(onlyInstancesOf(SyntaxError, (error) => {\n * // error is guaranteed to be an instance of SyntaxError\n * }))\n *\n * All other errors will be re-thrown.\n *\n */\nexport function onlyInstancesOf(\n predicate: Function, errorHandler: Function\n): Function {\n return (error) => {\n if (error instanceof predicate) {\n return errorHandler(error);\n } else {\n throw error;\n }\n };\n}\n\n\n/*\n * Sugar-y way to catch only errors having certain code(s).\n *\n * Usage:\n *\n * Promise.resolve()\n * .catch(onlyErrorsWithCode('ENOENT', (error) => {\n * // error.code is guaranteed to be ENOENT\n * }))\n *\n * or:\n *\n * Promise.resolve()\n * .catch(onlyErrorsWithCode(['ENOENT', 'ENOTDIR'], (error) => {\n * // ...\n * }))\n *\n * All other errors will be re-thrown.\n *\n */\nexport function onlyErrorsWithCode(\n codeWanted: (string | number) | Array<string | number>,\n errorHandler: Function\n): Function {\n return (error) => {\n let throwError = true;\n\n if (Array.isArray(codeWanted)) {\n if (codeWanted.indexOf(error.code) !== -1 ||\n codeWanted.indexOf(error.errno) !== -1) {\n throwError = false;\n }\n } else if (error.code === codeWanted || error.errno === codeWanted) {\n throwError = false;\n }\n\n if (throwError) {\n throw error;\n }\n\n return errorHandler(error);\n };\n}\n\nexport function isErrorWithCode(\n codeWanted: string | Array<string>,\n error: Object,\n): boolean {\n if (Array.isArray(codeWanted) && codeWanted.indexOf(error.code) !== -1) {\n return true;\n } else if (error.code === codeWanted) {\n return true;\n }\n\n return false;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","names":["ExtendableError","WebExtError","constructor","message","UsageError","InvalidManifest","RemoteTempInstallNotSupported","MultiExtensionsReloadError","errorsMap","errors","sourceDir","error","msg","String","errorsBySourceDir","onlyInstancesOf","predicate","errorHandler","onlyErrorsWithCode","codeWanted","throwError","Array","isArray","indexOf","code","errno","isErrorWithCode"],"sources":["../src/errors.js"],"sourcesContent":["/* @flow */\nimport ExtendableError from 'es6-error';\n\n\n/*\n * Base error for all custom web-ext errors.\n */\nexport class WebExtError extends ExtendableError {\n constructor(message: string) {\n super(message);\n }\n}\n\n\n/*\n * The class for errors that can be fixed by the developer.\n */\nexport class UsageError extends WebExtError {\n constructor(message: string) {\n super(message);\n }\n}\n\n\n/*\n * The manifest for the extension is invalid (or missing).\n */\nexport class InvalidManifest extends UsageError {\n constructor(message: string) {\n super(message);\n }\n}\n\n\n/*\n * The remote Firefox does not support temporary add-on installation.\n */\nexport class RemoteTempInstallNotSupported extends WebExtError {\n constructor(message: string) {\n super(message);\n }\n}\n\n/*\n * The errors collected when reloading all extensions at once\n * (initialized from a map of errors by extensionSourceDir string).\n */\nexport class MultiExtensionsReloadError extends WebExtError {\n constructor(errorsMap: Map<string, Error>) {\n let errors = '';\n for (const [sourceDir, error] of errorsMap) {\n const msg = String(error);\n errors += `\\nError on extension loaded from ${sourceDir}: ${msg}\\n`;\n }\n const message = `Reload errors: ${errors}`;\n\n super(message);\n this.errorsBySourceDir = errorsMap;\n }\n}\n\n/*\n * Sugar-y way to catch only instances of a certain error.\n *\n * Usage:\n *\n * Promise.reject(SyntaxError)\n * .catch(onlyInstancesOf(SyntaxError, (error) => {\n * // error is guaranteed to be an instance of SyntaxError\n * }))\n *\n * All other errors will be re-thrown.\n *\n */\nexport function onlyInstancesOf(\n predicate: Function, errorHandler: Function\n): Function {\n return (error) => {\n if (error instanceof predicate) {\n return errorHandler(error);\n } else {\n throw error;\n }\n };\n}\n\n\n/*\n * Sugar-y way to catch only errors having certain code(s).\n *\n * Usage:\n *\n * Promise.resolve()\n * .catch(onlyErrorsWithCode('ENOENT', (error) => {\n * // error.code is guaranteed to be ENOENT\n * }))\n *\n * or:\n *\n * Promise.resolve()\n * .catch(onlyErrorsWithCode(['ENOENT', 'ENOTDIR'], (error) => {\n * // ...\n * }))\n *\n * All other errors will be re-thrown.\n *\n */\nexport function onlyErrorsWithCode(\n codeWanted: (string | number) | Array<string | number>,\n errorHandler: Function\n): Function {\n return (error) => {\n let throwError = true;\n\n if (Array.isArray(codeWanted)) {\n if (codeWanted.indexOf(error.code) !== -1 ||\n codeWanted.indexOf(error.errno) !== -1) {\n throwError = false;\n }\n } else if (error.code === codeWanted || error.errno === codeWanted) {\n throwError = false;\n }\n\n if (throwError) {\n throw error;\n }\n\n return errorHandler(error);\n };\n}\n\nexport function isErrorWithCode(\n codeWanted: string | Array<string>,\n error: Object,\n): boolean {\n if (Array.isArray(codeWanted) && codeWanted.indexOf(error.code) !== -1) {\n return true;\n } else if (error.code === codeWanted) {\n return true;\n }\n\n return false;\n}\n"],"mappings":"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"}
@@ -1,2 +1,4 @@
1
+
2
+
1
3
  import { showDesktopNotification as defaultDesktopNotifications } from '../util/desktop-notifier';
2
4
  //# sourceMappingURL=base.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","names":["showDesktopNotification","defaultDesktopNotifications"],"sources":["../../src/extension-runners/base.js"],"sourcesContent":["/* @flow */\n\nimport {\n showDesktopNotification as defaultDesktopNotifications,\n} from '../util/desktop-notifier';\nimport type {ExtensionManifest} from '../util/manifest';\n\nexport type Extension = {|\n sourceDir: string,\n manifestData: ExtensionManifest,\n|};\n\nexport type ExtensionRunnerParams = {|\n // Common cli params.\n extensions: Array<Extension>,\n profilePath?: string,\n keepProfileChanges: boolean,\n startUrl: ?string | ?Array<string>,\n args?: Array<string>,\n\n // Common injected dependencies.\n desktopNotifications: typeof defaultDesktopNotifications,\n|};\n\nexport type ExtensionRunnerReloadResult = {|\n runnerName: string,\n reloadError?: Error,\n sourceDir?: string,\n|};\n\nexport interface IExtensionRunner {\n getName(): string,\n run(): Promise<void>,\n reloadAllExtensions(): Promise<Array<ExtensionRunnerReloadResult>>,\n reloadExtensionBySourceDir(\n extensionSourceDir: string\n ): Promise<Array<ExtensionRunnerReloadResult>>,\n registerCleanup(fn: Function): void,\n exit(): Promise<void>,\n}\n"],"mappings":"AAEA,SACEA,uBAAuB,IAAIC,2BAD7B,QAEO,0BAFP"}
1
+ {"version":3,"file":"base.js","names":["showDesktopNotification","defaultDesktopNotifications"],"sources":["../../src/extension-runners/base.js"],"sourcesContent":["/* @flow */\n\nimport {\n showDesktopNotification as defaultDesktopNotifications,\n} from '../util/desktop-notifier';\nimport type {ExtensionManifest} from '../util/manifest';\n\nexport type Extension = {|\n sourceDir: string,\n manifestData: ExtensionManifest,\n|};\n\nexport type ExtensionRunnerParams = {|\n // Common cli params.\n extensions: Array<Extension>,\n profilePath?: string,\n keepProfileChanges: boolean,\n startUrl: ?string | ?Array<string>,\n args?: Array<string>,\n\n // Common injected dependencies.\n desktopNotifications: typeof defaultDesktopNotifications,\n|};\n\nexport type ExtensionRunnerReloadResult = {|\n runnerName: string,\n reloadError?: Error,\n sourceDir?: string,\n|};\n\nexport interface IExtensionRunner {\n getName(): string,\n run(): Promise<void>,\n reloadAllExtensions(): Promise<Array<ExtensionRunnerReloadResult>>,\n reloadExtensionBySourceDir(\n extensionSourceDir: string\n ): Promise<Array<ExtensionRunnerReloadResult>>,\n registerCleanup(fn: Function): void,\n exit(): Promise<void>,\n}\n"],"mappings":";;AAEA,SACEA,uBAAuB,IAAIC,2BAA2B,QACjD,0BAA0B"}
@@ -1,7 +1,10 @@
1
+
2
+
1
3
  /**
2
4
  * This module provide an ExtensionRunner subclass that manage an extension executed
3
5
  * in a Chromium-based browser instance.
4
6
  */
7
+
5
8
  import path from 'path';
6
9
  import fs from 'fs-extra';
7
10
  import asyncMkdirp from 'mkdirp';
@@ -14,10 +17,10 @@ import fileExists from '../util/file-exists.js';
14
17
  const log = createLogger(import.meta.url);
15
18
  const EXCLUDED_CHROME_FLAGS = ['--disable-extensions', '--mute-audio'];
16
19
  export const DEFAULT_CHROME_FLAGS = ChromeLauncher.defaultFlags().filter(flag => !EXCLUDED_CHROME_FLAGS.includes(flag));
20
+
17
21
  /**
18
22
  * Implements an IExtensionRunner which manages a Chromium instance.
19
23
  */
20
-
21
24
  export class ChromiumExtensionRunner {
22
25
  constructor(params) {
23
26
  const {
@@ -26,36 +29,32 @@ export class ChromiumExtensionRunner {
26
29
  this.params = params;
27
30
  this.chromiumLaunch = chromiumLaunch;
28
31
  this.cleanupCallbacks = new Set();
29
- } // Method exported from the IExtensionRunner interface.
32
+ }
33
+
34
+ // Method exported from the IExtensionRunner interface.
30
35
 
31
36
  /**
32
37
  * Returns the runner name.
33
38
  */
34
-
35
-
36
39
  getName() {
37
40
  return 'Chromium';
38
41
  }
39
-
40
42
  async run() {
41
43
  // Run should never be called more than once.
42
44
  this._promiseSetupDone = this.setupInstance();
43
45
  await this._promiseSetupDone;
44
46
  }
45
-
46
47
  static async isUserDataDir(dirPath) {
47
48
  const localStatePath = path.join(dirPath, 'Local State');
48
- const defaultPath = path.join(dirPath, 'Default'); // Local State and Default are typical for the user-data-dir
49
-
49
+ const defaultPath = path.join(dirPath, 'Default');
50
+ // Local State and Default are typical for the user-data-dir
50
51
  return (await fileExists(localStatePath)) && (await isDirectory(defaultPath));
51
52
  }
52
-
53
53
  static async isProfileDir(dirPath) {
54
- const securePreferencesPath = path.join(dirPath, 'Secure Preferences'); //Secure Preferences is typical for a profile dir inside a user data dir
55
-
54
+ const securePreferencesPath = path.join(dirPath, 'Secure Preferences');
55
+ //Secure Preferences is typical for a profile dir inside a user data dir
56
56
  return await fileExists(securePreferencesPath);
57
57
  }
58
-
59
58
  static async getProfilePaths(chromiumProfile) {
60
59
  if (!chromiumProfile) {
61
60
  return {
@@ -63,9 +62,7 @@ export class ChromiumExtensionRunner {
63
62
  profileDirName: null
64
63
  };
65
64
  }
66
-
67
65
  const isProfileDirAndNotUserData = (await ChromiumExtensionRunner.isProfileDir(chromiumProfile)) && !(await ChromiumExtensionRunner.isUserDataDir(chromiumProfile));
68
-
69
66
  if (isProfileDirAndNotUserData) {
70
67
  const {
71
68
  dir: userDataDir,
@@ -76,40 +73,43 @@ export class ChromiumExtensionRunner {
76
73
  profileDirName
77
74
  };
78
75
  }
79
-
80
76
  return {
81
77
  userDataDir: chromiumProfile,
82
78
  profileDirName: null
83
79
  };
84
80
  }
81
+
85
82
  /**
86
83
  * Setup the Chromium Profile and run a Chromium instance.
87
84
  */
88
-
89
-
90
85
  async setupInstance() {
91
86
  // Start a websocket server on a free localhost TCP port.
92
87
  this.wss = await new Promise(resolve => {
93
- const server = new WebSocketServer( // Use a ipv4 host so we don't need to escape ipv6 address
88
+ const server = new WebSocketServer(
89
+ // Use a ipv4 host so we don't need to escape ipv6 address
94
90
  // https://github.com/mozilla/web-ext/issues/2331
95
91
  {
96
92
  port: 0,
97
93
  host: '127.0.0.1',
98
94
  clientTracking: true
99
- }, // Wait the server to be listening (so that the extension
95
+ },
96
+ // Wait the server to be listening (so that the extension
100
97
  // runner can successfully retrieve server address and port).
101
98
  () => resolve(server));
102
- }); // Prevent unhandled socket error (e.g. when chrome
103
- // is exiting, See https://github.com/websockets/ws/issues/1256).
99
+ });
104
100
 
101
+ // Prevent unhandled socket error (e.g. when chrome
102
+ // is exiting, See https://github.com/websockets/ws/issues/1256).
105
103
  this.wss.on('connection', function (socket) {
106
104
  socket.on('error', err => {
107
105
  log.debug(`websocket connection error: ${err}`);
108
106
  });
109
- }); // Create the extension that will manage the addon reloads
107
+ });
110
108
 
111
- this.reloadManagerExtension = await this.createReloadManagerExtension(); // Start chrome pointing it to a given profile dir
109
+ // Create the extension that will manage the addon reloads
110
+ this.reloadManagerExtension = await this.createReloadManagerExtension();
112
111
 
112
+ // Start chrome pointing it to a given profile dir
113
113
  const extensions = [this.reloadManagerExtension].concat(this.params.extensions.map(({
114
114
  sourceDir
115
115
  }) => sourceDir)).join(',');
@@ -117,24 +117,20 @@ export class ChromiumExtensionRunner {
117
117
  chromiumBinary
118
118
  } = this.params;
119
119
  log.debug('Starting Chromium instance...');
120
-
121
120
  if (chromiumBinary) {
122
121
  log.debug(`(chromiumBinary: ${chromiumBinary})`);
123
122
  }
124
-
125
123
  const chromeFlags = [...DEFAULT_CHROME_FLAGS];
126
124
  chromeFlags.push(`--load-extension=${extensions}`);
127
-
128
125
  if (this.params.args) {
129
126
  chromeFlags.push(...this.params.args);
130
- } // eslint-disable-next-line prefer-const
131
-
127
+ }
132
128
 
129
+ // eslint-disable-next-line prefer-const
133
130
  let {
134
131
  userDataDir,
135
132
  profileDirName
136
133
  } = await ChromiumExtensionRunner.getProfilePaths(this.params.chromiumProfile);
137
-
138
134
  if (userDataDir && this.params.keepProfileChanges) {
139
135
  if (profileDirName && !(await ChromiumExtensionRunner.isUserDataDir(userDataDir))) {
140
136
  throw new Error('The profile you provided is not in a ' + 'user-data-dir. The changes cannot be kept. Please either ' + 'remove --keep-profile-changes or use a profile in a ' + 'user-data-dir directory');
@@ -146,29 +142,23 @@ export class ChromiumExtensionRunner {
146
142
  const tmpDir = new TempDir();
147
143
  await tmpDir.create();
148
144
  const tmpDirPath = tmpDir.path();
149
-
150
145
  if (userDataDir && profileDirName) {
151
146
  // copy profile dir to this temp user data dir.
152
147
  await fs.copy(path.join(userDataDir, profileDirName), path.join(tmpDirPath, profileDirName));
153
148
  } else if (userDataDir) {
154
149
  await fs.copy(userDataDir, tmpDirPath);
155
150
  }
156
-
157
151
  userDataDir = tmpDirPath;
158
152
  }
159
-
160
153
  if (profileDirName) {
161
154
  chromeFlags.push(`--profile-directory=${profileDirName}`);
162
155
  }
163
-
164
156
  let startingUrl;
165
-
166
157
  if (this.params.startUrl) {
167
158
  const startingUrls = Array.isArray(this.params.startUrl) ? this.params.startUrl : [this.params.startUrl];
168
159
  startingUrl = startingUrls.shift();
169
160
  chromeFlags.push(...startingUrls);
170
161
  }
171
-
172
162
  this.chromiumInstance = await this.chromiumLaunch({
173
163
  enableExtensions: true,
174
164
  chromePath: chromiumBinary,
@@ -180,37 +170,30 @@ export class ChromiumExtensionRunner {
180
170
  });
181
171
  this.chromiumInstance.process.once('close', () => {
182
172
  this.chromiumInstance = null;
183
-
184
173
  if (!this.exiting) {
185
174
  log.info('Exiting on Chromium instance disconnected.');
186
175
  this.exit();
187
176
  }
188
177
  });
189
178
  }
190
-
191
179
  async wssBroadcast(data) {
192
180
  return new Promise(resolve => {
193
181
  const clients = this.wss ? new Set(this.wss.clients) : new Set();
194
-
195
182
  function cleanWebExtReloadComplete() {
196
183
  const client = this;
197
184
  client.removeEventListener('message', webExtReloadComplete);
198
185
  client.removeEventListener('close', cleanWebExtReloadComplete);
199
186
  clients.delete(client);
200
187
  }
201
-
202
188
  const webExtReloadComplete = async message => {
203
189
  const msg = JSON.parse(message.data);
204
-
205
190
  if (msg.type === 'webExtReloadExtensionComplete') {
206
191
  for (const client of clients) {
207
192
  cleanWebExtReloadComplete.call(client);
208
193
  }
209
-
210
194
  resolve();
211
195
  }
212
196
  };
213
-
214
197
  for (const client of clients) {
215
198
  if (client.readyState === WebSocket.OPEN) {
216
199
  client.addEventListener('message', webExtReloadComplete);
@@ -220,13 +203,11 @@ export class ChromiumExtensionRunner {
220
203
  clients.delete(client);
221
204
  }
222
205
  }
223
-
224
206
  if (clients.size === 0) {
225
207
  resolve();
226
208
  }
227
209
  });
228
210
  }
229
-
230
211
  async createReloadManagerExtension() {
231
212
  const tmpDir = new TempDir();
232
213
  await tmpDir.create();
@@ -242,8 +223,9 @@ export class ChromiumExtensionRunner {
242
223
  background: {
243
224
  scripts: ['bg.js']
244
225
  }
245
- })); // $FlowIgnore: this method is only called right after creating the server and so wss should be defined.
226
+ }));
246
227
 
228
+ // $FlowIgnore: this method is only called right after creating the server and so wss should be defined.
247
229
  const wssInfo = this.wss.address();
248
230
  const bgPage = `(function bgPage() {
249
231
  async function getAllDevExtensions() {
@@ -282,12 +264,11 @@ export class ChromiumExtensionRunner {
282
264
  await fs.writeFile(path.join(extPath, 'bg.js'), bgPage);
283
265
  return extPath;
284
266
  }
267
+
285
268
  /**
286
269
  * Reloads all the extensions, collect any reload error and resolves to
287
270
  * an array composed by a single ExtensionRunnerReloadResult object.
288
271
  */
289
-
290
-
291
272
  async reloadAllExtensions() {
292
273
  const runnerName = this.getName();
293
274
  await this.wssBroadcast({
@@ -299,66 +280,60 @@ export class ChromiumExtensionRunner {
299
280
  runnerName
300
281
  }];
301
282
  }
283
+
302
284
  /**
303
285
  * Reloads a single extension, collect any reload error and resolves to
304
286
  * an array composed by a single ExtensionRunnerReloadResult object.
305
287
  */
306
-
307
-
308
288
  async reloadExtensionBySourceDir(extensionSourceDir) {
309
289
  // TODO(rpl): detect the extension ids assigned to the
310
290
  // target extensions and map it to the extensions source dir
311
291
  // (https://github.com/mozilla/web-ext/issues/1687).
312
292
  return this.reloadAllExtensions();
313
293
  }
294
+
314
295
  /**
315
296
  * Register a callback to be called when the runner has been exited
316
297
  * (e.g. the Chromium instance exits or the user has requested web-ext
317
298
  * to exit).
318
299
  */
319
-
320
-
321
300
  registerCleanup(fn) {
322
301
  this.cleanupCallbacks.add(fn);
323
302
  }
303
+
324
304
  /**
325
305
  * Exits the runner, by closing the managed Chromium instance.
326
306
  */
327
-
328
-
329
307
  async exit() {
330
- this.exiting = true; // Wait for the setup to complete if the extension runner is already
331
- // being started.
308
+ this.exiting = true;
332
309
 
310
+ // Wait for the setup to complete if the extension runner is already
311
+ // being started.
333
312
  if (this._promiseSetupDone) {
334
313
  // Ignore initialization errors if any.
335
314
  await this._promiseSetupDone.catch(err => {
336
315
  log.debug(`ignored setup error on chromium runner shutdown: ${err}`);
337
316
  });
338
317
  }
339
-
340
318
  if (this.chromiumInstance) {
341
319
  await this.chromiumInstance.kill();
342
320
  this.chromiumInstance = null;
343
321
  }
344
-
345
322
  if (this.wss) {
346
323
  // Close all websocket clients, closing the WebSocketServer
347
324
  // does not terminate the existing connection and it wouldn't
348
325
  // resolve until all of the existing connections are closed.
349
326
  for (const wssClient of ((_this$wss = this.wss) === null || _this$wss === void 0 ? void 0 : _this$wss.clients) || []) {
350
327
  var _this$wss;
351
-
352
328
  if (wssClient.readyState === WebSocket.OPEN) {
353
329
  wssClient.terminate();
354
330
  }
355
331
  }
356
-
357
332
  await new Promise(resolve => this.wss ? this.wss.close(resolve) : resolve());
358
333
  this.wss = null;
359
- } // Call all the registered cleanup callbacks.
360
-
334
+ }
361
335
 
336
+ // Call all the registered cleanup callbacks.
362
337
  for (const fn of this.cleanupCallbacks) {
363
338
  try {
364
339
  fn();
@@ -367,6 +342,5 @@ export class ChromiumExtensionRunner {
367
342
  }
368
343
  }
369
344
  }
370
-
371
345
  }
372
346
  //# sourceMappingURL=chromium.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chromium.js","names":["path","fs","asyncMkdirp","Launcher","ChromeLauncher","launch","defaultChromiumLaunch","WebSocket","WebSocketServer","createLogger","TempDir","isDirectory","fileExists","log","import","meta","url","EXCLUDED_CHROME_FLAGS","DEFAULT_CHROME_FLAGS","defaultFlags","filter","flag","includes","ChromiumExtensionRunner","constructor","params","chromiumLaunch","cleanupCallbacks","Set","getName","run","_promiseSetupDone","setupInstance","isUserDataDir","dirPath","localStatePath","join","defaultPath","isProfileDir","securePreferencesPath","getProfilePaths","chromiumProfile","userDataDir","profileDirName","isProfileDirAndNotUserData","dir","base","parse","wss","Promise","resolve","server","port","host","clientTracking","on","socket","err","debug","reloadManagerExtension","createReloadManagerExtension","extensions","concat","map","sourceDir","chromiumBinary","chromeFlags","push","args","keepProfileChanges","Error","tmpDir","create","tmpDirPath","copy","startingUrl","startUrl","startingUrls","Array","isArray","shift","chromiumInstance","enableExtensions","chromePath","ignoreDefaultFlags","process","once","exiting","info","exit","wssBroadcast","data","clients","cleanWebExtReloadComplete","client","removeEventListener","webExtReloadComplete","delete","message","msg","JSON","type","call","readyState","OPEN","addEventListener","send","stringify","size","registerCleanup","remove","extPath","Date","now","writeFile","manifest_version","name","version","permissions","background","scripts","wssInfo","address","bgPage","reloadAllExtensions","runnerName","stdout","write","toTimeString","reloadExtensionBySourceDir","extensionSourceDir","fn","add","catch","kill","wssClient","terminate","close","error"],"sources":["../../src/extension-runners/chromium.js"],"sourcesContent":["/* @flow */\n\n/**\n * This module provide an ExtensionRunner subclass that manage an extension executed\n * in a Chromium-based browser instance.\n */\n\nimport path from 'path';\n\nimport fs from 'fs-extra';\nimport asyncMkdirp from 'mkdirp';\nimport {\n Launcher as ChromeLauncher,\n launch as defaultChromiumLaunch,\n} from 'chrome-launcher';\nimport WebSocket, {WebSocketServer} from 'ws';\n\nimport {createLogger} from '../util/logger.js';\nimport {TempDir} from '../util/temp-dir.js';\nimport type {\n ExtensionRunnerParams,\n ExtensionRunnerReloadResult,\n} from './base';\nimport isDirectory from '../util/is-directory.js';\nimport fileExists from '../util/file-exists.js';\n\ntype ChromiumSpecificRunnerParams = {|\n chromiumBinary?: string,\n chromiumProfile?: string,\n chromiumLaunch?: typeof defaultChromiumLaunch,\n|};\n\nexport type ChromiumExtensionRunnerParams = {|\n ...ExtensionRunnerParams,\n // Chromium desktop CLI params.\n ...ChromiumSpecificRunnerParams,\n|};\n\nconst log = createLogger(import.meta.url);\n\nconst EXCLUDED_CHROME_FLAGS = [\n '--disable-extensions',\n '--mute-audio',\n];\n\nexport const DEFAULT_CHROME_FLAGS: Array<string> = ChromeLauncher.defaultFlags()\n .filter((flag) => !EXCLUDED_CHROME_FLAGS.includes(flag));\n\n/**\n * Implements an IExtensionRunner which manages a Chromium instance.\n */\nexport class ChromiumExtensionRunner {\n cleanupCallbacks: Set<Function>;\n params: ChromiumExtensionRunnerParams;\n chromiumInstance: ?ChromeLauncher;\n chromiumLaunch: typeof defaultChromiumLaunch;\n reloadManagerExtension: string;\n wss: ?WebSocketServer;\n exiting: boolean;\n _promiseSetupDone: ?Promise<void>;\n\n constructor(params: ChromiumExtensionRunnerParams) {\n const {\n chromiumLaunch = defaultChromiumLaunch,\n } = params;\n this.params = params;\n this.chromiumLaunch = chromiumLaunch;\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 'Chromium';\n }\n\n async run(): Promise<void> {\n // Run should never be called more than once.\n this._promiseSetupDone = this.setupInstance();\n await this._promiseSetupDone;\n }\n\n static async isUserDataDir(dirPath: string): Promise<boolean> {\n const localStatePath = path.join(dirPath, 'Local State');\n const defaultPath = path.join(dirPath, 'Default');\n // Local State and Default are typical for the user-data-dir\n return (await fileExists(localStatePath))\n && (await isDirectory(defaultPath));\n }\n\n static async isProfileDir(dirPath: string): Promise<boolean> {\n const securePreferencesPath = path.join(\n dirPath, 'Secure Preferences');\n //Secure Preferences is typical for a profile dir inside a user data dir\n return await fileExists(securePreferencesPath);\n }\n\n static async getProfilePaths(chromiumProfile: ?string): Promise<{\n userDataDir: ?string,\n profileDirName: ?string\n }> {\n if (!chromiumProfile) {\n return {\n userDataDir: null,\n profileDirName: null,\n };\n }\n\n const isProfileDirAndNotUserData =\n (await ChromiumExtensionRunner.isProfileDir(chromiumProfile))\n && !(await ChromiumExtensionRunner.isUserDataDir(chromiumProfile));\n\n if (isProfileDirAndNotUserData) {\n const {dir: userDataDir, base: profileDirName} =\n path.parse(chromiumProfile);\n return {\n userDataDir,\n profileDirName,\n };\n }\n\n return {\n userDataDir: chromiumProfile,\n profileDirName: null,\n };\n\n }\n\n /**\n * Setup the Chromium Profile and run a Chromium instance.\n */\n async setupInstance(): Promise<void> {\n // Start a websocket server on a free localhost TCP port.\n this.wss = await new Promise((resolve) => {\n const server = new WebSocketServer(\n // Use a ipv4 host so we don't need to escape ipv6 address\n // https://github.com/mozilla/web-ext/issues/2331\n {port: 0, host: '127.0.0.1', clientTracking: true},\n // Wait the server to be listening (so that the extension\n // runner can successfully retrieve server address and port).\n () => resolve(server));\n });\n\n // Prevent unhandled socket error (e.g. when chrome\n // is exiting, See https://github.com/websockets/ws/issues/1256).\n this.wss.on('connection', function(socket) {\n socket.on('error', (err) => {\n log.debug(`websocket connection error: ${err}`);\n });\n });\n\n // Create the extension that will manage the addon reloads\n this.reloadManagerExtension = await this.createReloadManagerExtension();\n\n // Start chrome pointing it to a given profile dir\n const extensions = [this.reloadManagerExtension].concat(\n this.params.extensions.map(({sourceDir}) => sourceDir)\n ).join(',');\n\n const {chromiumBinary} = this.params;\n\n log.debug('Starting Chromium instance...');\n\n if (chromiumBinary) {\n log.debug(`(chromiumBinary: ${chromiumBinary})`);\n }\n\n const chromeFlags = [...DEFAULT_CHROME_FLAGS];\n\n chromeFlags.push(`--load-extension=${extensions}`);\n\n if (this.params.args) {\n chromeFlags.push(...this.params.args);\n }\n\n // eslint-disable-next-line prefer-const\n let {userDataDir, profileDirName} =\n await ChromiumExtensionRunner.getProfilePaths(\n this.params.chromiumProfile);\n\n if (userDataDir && this.params.keepProfileChanges) {\n if (profileDirName\n && !(await ChromiumExtensionRunner.isUserDataDir(userDataDir))) {\n throw new Error('The profile you provided is not in a ' +\n 'user-data-dir. The changes cannot be kept. Please either ' +\n 'remove --keep-profile-changes or use a profile in a ' +\n 'user-data-dir directory');\n }\n } else if (!this.params.keepProfileChanges) {\n // the user provided an existing profile directory but doesn't want\n // the changes to be kept. we copy this directory to a temporary\n // user data dir.\n const tmpDir = new TempDir();\n await tmpDir.create();\n const tmpDirPath = tmpDir.path();\n\n if (userDataDir && profileDirName) {\n // copy profile dir to this temp user data dir.\n await fs.copy(path.join(\n userDataDir,\n profileDirName), path.join(\n tmpDirPath,\n profileDirName),\n );\n } else if (userDataDir) {\n await fs.copy(userDataDir, tmpDirPath);\n }\n userDataDir = tmpDirPath;\n }\n\n if (profileDirName) {\n chromeFlags.push(`--profile-directory=${profileDirName}`);\n }\n\n let startingUrl;\n if (this.params.startUrl) {\n const startingUrls = Array.isArray(this.params.startUrl) ?\n this.params.startUrl : [this.params.startUrl];\n startingUrl = startingUrls.shift();\n chromeFlags.push(...startingUrls);\n }\n\n this.chromiumInstance = await this.chromiumLaunch({\n enableExtensions: true,\n chromePath: chromiumBinary,\n chromeFlags,\n startingUrl,\n userDataDir,\n // Ignore default flags to keep the extension enabled.\n ignoreDefaultFlags: true,\n });\n\n this.chromiumInstance.process.once('close', () => {\n this.chromiumInstance = null;\n\n if (!this.exiting) {\n log.info('Exiting on Chromium instance disconnected.');\n this.exit();\n }\n });\n }\n\n async wssBroadcast(data: Object): Promise<void> {\n return new Promise((resolve) => {\n const clients = this.wss ? new Set(this.wss.clients) : new Set();\n\n function cleanWebExtReloadComplete() {\n const client = this;\n client.removeEventListener('message', webExtReloadComplete);\n client.removeEventListener('close', cleanWebExtReloadComplete);\n clients.delete(client);\n }\n\n const webExtReloadComplete = async (message) => {\n const msg = JSON.parse(message.data);\n\n if (msg.type === 'webExtReloadExtensionComplete') {\n for (const client of clients) {\n cleanWebExtReloadComplete.call(client);\n }\n resolve();\n }\n };\n\n for (const client of clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.addEventListener('message', webExtReloadComplete);\n client.addEventListener('close', cleanWebExtReloadComplete);\n\n client.send(JSON.stringify(data));\n } else {\n clients.delete(client);\n }\n }\n\n if (clients.size === 0) {\n resolve();\n }\n });\n }\n\n async createReloadManagerExtension(): Promise<string> {\n const tmpDir = new TempDir();\n await tmpDir.create();\n this.registerCleanup(() => tmpDir.remove());\n\n const extPath = path.join(\n tmpDir.path(),\n `reload-manager-extension-${Date.now()}`\n );\n\n log.debug(`Creating reload-manager-extension in ${extPath}`);\n\n await asyncMkdirp(extPath);\n\n await fs.writeFile(\n path.join(extPath, 'manifest.json'),\n JSON.stringify({\n manifest_version: 2,\n name: 'web-ext Reload Manager Extension',\n version: '1.0',\n permissions: ['management', 'tabs'],\n background: {\n scripts: ['bg.js'],\n },\n })\n );\n\n // $FlowIgnore: this method is only called right after creating the server and so wss should be defined.\n const wssInfo = this.wss.address();\n\n const bgPage = `(function bgPage() {\n async function getAllDevExtensions() {\n const allExtensions = await new Promise(\n r => chrome.management.getAll(r));\n\n return allExtensions.filter((extension) => {\n return extension.enabled &&\n extension.installType === \"development\" &&\n extension.id !== chrome.runtime.id;\n });\n }\n\n const setEnabled = (extensionId, value) =>\n chrome.runtime.id == extensionId ?\n new Promise.resolve() :\n new Promise(r => chrome.management.setEnabled(extensionId, value, r));\n\n async function reloadExtension(extensionId) {\n await setEnabled(extensionId, false);\n await setEnabled(extensionId, true);\n }\n\n const ws = new window.WebSocket(\n \"ws://${wssInfo.address}:${wssInfo.port}\");\n\n ws.onmessage = async (evt) => {\n const msg = JSON.parse(evt.data);\n if (msg.type === 'webExtReloadAllExtensions') {\n const devExtensions = await getAllDevExtensions();\n await Promise.all(devExtensions.map(ext => reloadExtension(ext.id)));\n ws.send(JSON.stringify({ type: 'webExtReloadExtensionComplete' }));\n }\n };\n })()`;\n\n await fs.writeFile(path.join(extPath, 'bg.js'), bgPage);\n return extPath;\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\n await this.wssBroadcast({\n type: 'webExtReloadAllExtensions',\n });\n\n process.stdout.write(\n `\\rLast extension reload: ${(new Date()).toTimeString()}`);\n log.debug('\\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 // eslint-disable-line no-unused-vars\n ): Promise<Array<ExtensionRunnerReloadResult>> {\n // TODO(rpl): detect the extension ids assigned to the\n // target extensions and map it to the extensions source dir\n // (https://github.com/mozilla/web-ext/issues/1687).\n return this.reloadAllExtensions();\n }\n\n /**\n * Register a callback to be called when the runner has been exited\n * (e.g. the Chromium 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 Chromium instance.\n */\n async exit(): Promise<void> {\n this.exiting = true;\n\n // Wait for the setup to complete if the extension runner is already\n // being started.\n if (this._promiseSetupDone) {\n // Ignore initialization errors if any.\n await this._promiseSetupDone.catch((err) => {\n log.debug(`ignored setup error on chromium runner shutdown: ${err}`);\n });\n }\n\n if (this.chromiumInstance) {\n await this.chromiumInstance.kill();\n this.chromiumInstance = null;\n }\n\n if (this.wss) {\n // Close all websocket clients, closing the WebSocketServer\n // does not terminate the existing connection and it wouldn't\n // resolve until all of the existing connections are closed.\n for (const wssClient of this.wss?.clients || []) {\n if (wssClient.readyState === WebSocket.OPEN) {\n wssClient.terminate();\n }\n }\n await new Promise((resolve) =>\n this.wss ? this.wss.close(resolve) : resolve());\n this.wss = null;\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"],"mappings":"AAEA;AACA;AACA;AACA;AAEA,OAAOA,IAAP,MAAiB,MAAjB;AAEA,OAAOC,EAAP,MAAe,UAAf;AACA,OAAOC,WAAP,MAAwB,QAAxB;AACA,SACEC,QAAQ,IAAIC,cADd,EAEEC,MAAM,IAAIC,qBAFZ,QAGO,iBAHP;AAIA,OAAOC,SAAP,IAAmBC,eAAnB,QAAyC,IAAzC;AAEA,SAAQC,YAAR,QAA2B,mBAA3B;AACA,SAAQC,OAAR,QAAsB,qBAAtB;AAKA,OAAOC,WAAP,MAAwB,yBAAxB;AACA,OAAOC,UAAP,MAAuB,wBAAvB;AAcA,MAAMC,GAAG,GAAGJ,YAAY,CAACK,MAAM,CAACC,IAAP,CAAYC,GAAb,CAAxB;AAEA,MAAMC,qBAAqB,GAAG,CAC5B,sBAD4B,EAE5B,cAF4B,CAA9B;AAKA,OAAO,MAAMC,oBAAmC,GAAGd,cAAc,CAACe,YAAf,GAChDC,MADgD,CACxCC,IAAD,IAAU,CAACJ,qBAAqB,CAACK,QAAtB,CAA+BD,IAA/B,CAD8B,CAA5C;AAGP;AACA;AACA;;AACA,OAAO,MAAME,uBAAN,CAA8B;EAUnCC,WAAW,CAACC,MAAD,EAAwC;IACjD,MAAM;MACJC,cAAc,GAAGpB;IADb,IAEFmB,MAFJ;IAGA,KAAKA,MAAL,GAAcA,MAAd;IACA,KAAKC,cAAL,GAAsBA,cAAtB;IACA,KAAKC,gBAAL,GAAwB,IAAIC,GAAJ,EAAxB;EACD,CAjBkC,CAmBnC;;EAEA;AACF;AACA;;;EACEC,OAAO,GAAW;IAChB,OAAO,UAAP;EACD;;EAEQ,MAAHC,GAAG,GAAkB;IACzB;IACA,KAAKC,iBAAL,GAAyB,KAAKC,aAAL,EAAzB;IACA,MAAM,KAAKD,iBAAX;EACD;;EAEyB,aAAbE,aAAa,CAACC,OAAD,EAAoC;IAC5D,MAAMC,cAAc,GAAGnC,IAAI,CAACoC,IAAL,CAAUF,OAAV,EAAmB,aAAnB,CAAvB;IACA,MAAMG,WAAW,GAAGrC,IAAI,CAACoC,IAAL,CAAUF,OAAV,EAAmB,SAAnB,CAApB,CAF4D,CAG5D;;IACA,OAAO,CAAC,MAAMtB,UAAU,CAACuB,cAAD,CAAjB,MACD,MAAMxB,WAAW,CAAC0B,WAAD,CADhB,CAAP;EAED;;EAEwB,aAAZC,YAAY,CAACJ,OAAD,EAAoC;IAC3D,MAAMK,qBAAqB,GAAGvC,IAAI,CAACoC,IAAL,CAC5BF,OAD4B,EACnB,oBADmB,CAA9B,CAD2D,CAG3D;;IACA,OAAO,MAAMtB,UAAU,CAAC2B,qBAAD,CAAvB;EACD;;EAE2B,aAAfC,eAAe,CAACC,eAAD,EAGzB;IACD,IAAI,CAACA,eAAL,EAAsB;MACpB,OAAO;QACLC,WAAW,EAAE,IADR;QAELC,cAAc,EAAE;MAFX,CAAP;IAID;;IAED,MAAMC,0BAA0B,GAC9B,CAAC,MAAMrB,uBAAuB,CAACe,YAAxB,CAAqCG,eAArC,CAAP,KACG,EAAE,MAAMlB,uBAAuB,CAACU,aAAxB,CAAsCQ,eAAtC,CAAR,CAFL;;IAIA,IAAIG,0BAAJ,EAAgC;MAC9B,MAAM;QAACC,GAAG,EAAEH,WAAN;QAAmBI,IAAI,EAAEH;MAAzB,IACJ3C,IAAI,CAAC+C,KAAL,CAAWN,eAAX,CADF;MAEA,OAAO;QACLC,WADK;QAELC;MAFK,CAAP;IAID;;IAED,OAAO;MACLD,WAAW,EAAED,eADR;MAELE,cAAc,EAAE;IAFX,CAAP;EAKD;EAED;AACF;AACA;;;EACqB,MAAbX,aAAa,GAAkB;IACnC;IACA,KAAKgB,GAAL,GAAW,MAAM,IAAIC,OAAJ,CAAaC,OAAD,IAAa;MACxC,MAAMC,MAAM,GAAG,IAAI3C,eAAJ,EACb;MACA;MACA;QAAC4C,IAAI,EAAE,CAAP;QAAUC,IAAI,EAAE,WAAhB;QAA6BC,cAAc,EAAE;MAA7C,CAHa,EAIb;MACA;MACA,MAAMJ,OAAO,CAACC,MAAD,CANA,CAAf;IAOD,CARgB,CAAjB,CAFmC,CAYnC;IACA;;IACA,KAAKH,GAAL,CAASO,EAAT,CAAY,YAAZ,EAA0B,UAASC,MAAT,EAAiB;MACzCA,MAAM,CAACD,EAAP,CAAU,OAAV,EAAoBE,GAAD,IAAS;QAC1B5C,GAAG,CAAC6C,KAAJ,CAAW,+BAA8BD,GAAI,EAA7C;MACD,CAFD;IAGD,CAJD,EAdmC,CAoBnC;;IACA,KAAKE,sBAAL,GAA8B,MAAM,KAAKC,4BAAL,EAApC,CArBmC,CAuBnC;;IACA,MAAMC,UAAU,GAAG,CAAC,KAAKF,sBAAN,EAA8BG,MAA9B,CACjB,KAAKrC,MAAL,CAAYoC,UAAZ,CAAuBE,GAAvB,CAA2B,CAAC;MAACC;IAAD,CAAD,KAAiBA,SAA5C,CADiB,EAEjB5B,IAFiB,CAEZ,GAFY,CAAnB;IAIA,MAAM;MAAC6B;IAAD,IAAmB,KAAKxC,MAA9B;IAEAZ,GAAG,CAAC6C,KAAJ,CAAU,+BAAV;;IAEA,IAAIO,cAAJ,EAAoB;MAClBpD,GAAG,CAAC6C,KAAJ,CAAW,oBAAmBO,cAAe,GAA7C;IACD;;IAED,MAAMC,WAAW,GAAG,CAAC,GAAGhD,oBAAJ,CAApB;IAEAgD,WAAW,CAACC,IAAZ,CAAkB,oBAAmBN,UAAW,EAAhD;;IAEA,IAAI,KAAKpC,MAAL,CAAY2C,IAAhB,EAAsB;MACpBF,WAAW,CAACC,IAAZ,CAAiB,GAAG,KAAK1C,MAAL,CAAY2C,IAAhC;IACD,CA1CkC,CA4CnC;;;IACA,IAAI;MAAC1B,WAAD;MAAcC;IAAd,IACF,MAAMpB,uBAAuB,CAACiB,eAAxB,CACJ,KAAKf,MAAL,CAAYgB,eADR,CADR;;IAIA,IAAIC,WAAW,IAAI,KAAKjB,MAAL,CAAY4C,kBAA/B,EAAmD;MACjD,IAAI1B,cAAc,IACb,EAAE,MAAMpB,uBAAuB,CAACU,aAAxB,CAAsCS,WAAtC,CAAR,CADL,EACkE;QAChE,MAAM,IAAI4B,KAAJ,CAAU,0CACd,2DADc,GAEd,sDAFc,GAGd,yBAHI,CAAN;MAID;IACF,CARD,MAQO,IAAI,CAAC,KAAK7C,MAAL,CAAY4C,kBAAjB,EAAqC;MAC1C;MACA;MACA;MACA,MAAME,MAAM,GAAG,IAAI7D,OAAJ,EAAf;MACA,MAAM6D,MAAM,CAACC,MAAP,EAAN;MACA,MAAMC,UAAU,GAAGF,MAAM,CAACvE,IAAP,EAAnB;;MAEA,IAAI0C,WAAW,IAAIC,cAAnB,EAAmC;QACjC;QACA,MAAM1C,EAAE,CAACyE,IAAH,CAAQ1E,IAAI,CAACoC,IAAL,CACZM,WADY,EAEZC,cAFY,CAAR,EAEa3C,IAAI,CAACoC,IAAL,CACjBqC,UADiB,EAEjB9B,cAFiB,CAFb,CAAN;MAMD,CARD,MAQO,IAAID,WAAJ,EAAiB;QACtB,MAAMzC,EAAE,CAACyE,IAAH,CAAQhC,WAAR,EAAqB+B,UAArB,CAAN;MACD;;MACD/B,WAAW,GAAG+B,UAAd;IACD;;IAED,IAAI9B,cAAJ,EAAoB;MAClBuB,WAAW,CAACC,IAAZ,CAAkB,uBAAsBxB,cAAe,EAAvD;IACD;;IAED,IAAIgC,WAAJ;;IACA,IAAI,KAAKlD,MAAL,CAAYmD,QAAhB,EAA0B;MACxB,MAAMC,YAAY,GAAGC,KAAK,CAACC,OAAN,CAAc,KAAKtD,MAAL,CAAYmD,QAA1B,IACnB,KAAKnD,MAAL,CAAYmD,QADO,GACI,CAAC,KAAKnD,MAAL,CAAYmD,QAAb,CADzB;MAEAD,WAAW,GAAGE,YAAY,CAACG,KAAb,EAAd;MACAd,WAAW,CAACC,IAAZ,CAAiB,GAAGU,YAApB;IACD;;IAED,KAAKI,gBAAL,GAAwB,MAAM,KAAKvD,cAAL,CAAoB;MAChDwD,gBAAgB,EAAE,IAD8B;MAEhDC,UAAU,EAAElB,cAFoC;MAGhDC,WAHgD;MAIhDS,WAJgD;MAKhDjC,WALgD;MAMhD;MACA0C,kBAAkB,EAAE;IAP4B,CAApB,CAA9B;IAUA,KAAKH,gBAAL,CAAsBI,OAAtB,CAA8BC,IAA9B,CAAmC,OAAnC,EAA4C,MAAM;MAChD,KAAKL,gBAAL,GAAwB,IAAxB;;MAEA,IAAI,CAAC,KAAKM,OAAV,EAAmB;QACjB1E,GAAG,CAAC2E,IAAJ,CAAS,4CAAT;QACA,KAAKC,IAAL;MACD;IACF,CAPD;EAQD;;EAEiB,MAAZC,YAAY,CAACC,IAAD,EAA8B;IAC9C,OAAO,IAAI1C,OAAJ,CAAaC,OAAD,IAAa;MAC9B,MAAM0C,OAAO,GAAG,KAAK5C,GAAL,GAAW,IAAIpB,GAAJ,CAAQ,KAAKoB,GAAL,CAAS4C,OAAjB,CAAX,GAAuC,IAAIhE,GAAJ,EAAvD;;MAEA,SAASiE,yBAAT,GAAqC;QACnC,MAAMC,MAAM,GAAG,IAAf;QACAA,MAAM,CAACC,mBAAP,CAA2B,SAA3B,EAAsCC,oBAAtC;QACAF,MAAM,CAACC,mBAAP,CAA2B,OAA3B,EAAoCF,yBAApC;QACAD,OAAO,CAACK,MAAR,CAAeH,MAAf;MACD;;MAED,MAAME,oBAAoB,GAAG,MAAOE,OAAP,IAAmB;QAC9C,MAAMC,GAAG,GAAGC,IAAI,CAACrD,KAAL,CAAWmD,OAAO,CAACP,IAAnB,CAAZ;;QAEA,IAAIQ,GAAG,CAACE,IAAJ,KAAa,+BAAjB,EAAkD;UAChD,KAAK,MAAMP,MAAX,IAAqBF,OAArB,EAA8B;YAC5BC,yBAAyB,CAACS,IAA1B,CAA+BR,MAA/B;UACD;;UACD5C,OAAO;QACR;MACF,CATD;;MAWA,KAAK,MAAM4C,MAAX,IAAqBF,OAArB,EAA8B;QAC5B,IAAIE,MAAM,CAACS,UAAP,KAAsBhG,SAAS,CAACiG,IAApC,EAA0C;UACxCV,MAAM,CAACW,gBAAP,CAAwB,SAAxB,EAAmCT,oBAAnC;UACAF,MAAM,CAACW,gBAAP,CAAwB,OAAxB,EAAiCZ,yBAAjC;UAEAC,MAAM,CAACY,IAAP,CAAYN,IAAI,CAACO,SAAL,CAAehB,IAAf,CAAZ;QACD,CALD,MAKO;UACLC,OAAO,CAACK,MAAR,CAAeH,MAAf;QACD;MACF;;MAED,IAAIF,OAAO,CAACgB,IAAR,KAAiB,CAArB,EAAwB;QACtB1D,OAAO;MACR;IACF,CAnCM,CAAP;EAoCD;;EAEiC,MAA5BU,4BAA4B,GAAoB;IACpD,MAAMW,MAAM,GAAG,IAAI7D,OAAJ,EAAf;IACA,MAAM6D,MAAM,CAACC,MAAP,EAAN;IACA,KAAKqC,eAAL,CAAqB,MAAMtC,MAAM,CAACuC,MAAP,EAA3B;IAEA,MAAMC,OAAO,GAAG/G,IAAI,CAACoC,IAAL,CACdmC,MAAM,CAACvE,IAAP,EADc,EAEb,4BAA2BgH,IAAI,CAACC,GAAL,EAAW,EAFzB,CAAhB;IAKApG,GAAG,CAAC6C,KAAJ,CAAW,wCAAuCqD,OAAQ,EAA1D;IAEA,MAAM7G,WAAW,CAAC6G,OAAD,CAAjB;IAEA,MAAM9G,EAAE,CAACiH,SAAH,CACJlH,IAAI,CAACoC,IAAL,CAAU2E,OAAV,EAAmB,eAAnB,CADI,EAEJX,IAAI,CAACO,SAAL,CAAe;MACbQ,gBAAgB,EAAE,CADL;MAEbC,IAAI,EAAE,kCAFO;MAGbC,OAAO,EAAE,KAHI;MAIbC,WAAW,EAAE,CAAC,YAAD,EAAe,MAAf,CAJA;MAKbC,UAAU,EAAE;QACVC,OAAO,EAAE,CAAC,OAAD;MADC;IALC,CAAf,CAFI,CAAN,CAdoD,CA2BpD;;IACA,MAAMC,OAAO,GAAG,KAAKzE,GAAL,CAAS0E,OAAT,EAAhB;IAEA,MAAMC,MAAM,GAAI;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgBF,OAAO,CAACC,OAAQ,IAAGD,OAAO,CAACrE,IAAK;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAjCI;IAmCA,MAAMnD,EAAE,CAACiH,SAAH,CAAalH,IAAI,CAACoC,IAAL,CAAU2E,OAAV,EAAmB,OAAnB,CAAb,EAA0CY,MAA1C,CAAN;IACA,OAAOZ,OAAP;EACD;EAED;AACF;AACA;AACA;;;EAC2B,MAAnBa,mBAAmB,GAAgD;IACvE,MAAMC,UAAU,GAAG,KAAKhG,OAAL,EAAnB;IAEA,MAAM,KAAK6D,YAAL,CAAkB;MACtBW,IAAI,EAAE;IADgB,CAAlB,CAAN;IAIAhB,OAAO,CAACyC,MAAR,CAAeC,KAAf,CACG,4BAA4B,IAAIf,IAAJ,EAAD,CAAagB,YAAb,EAA4B,EAD1D;IAEAnH,GAAG,CAAC6C,KAAJ,CAAU,IAAV;IAEA,OAAO,CAAC;MAACmE;IAAD,CAAD,CAAP;EACD;EAED;AACF;AACA;AACA;;;EACkC,MAA1BI,0BAA0B,CAC9BC,kBAD8B,EAEe;IAC7C;IACA;IACA;IACA,OAAO,KAAKN,mBAAL,EAAP;EACD;EAED;AACF;AACA;AACA;AACA;;;EACEf,eAAe,CAACsB,EAAD,EAAqB;IAClC,KAAKxG,gBAAL,CAAsByG,GAAtB,CAA0BD,EAA1B;EACD;EAED;AACF;AACA;;;EACY,MAAJ1C,IAAI,GAAkB;IAC1B,KAAKF,OAAL,GAAe,IAAf,CAD0B,CAG1B;IACA;;IACA,IAAI,KAAKxD,iBAAT,EAA4B;MAC1B;MACA,MAAM,KAAKA,iBAAL,CAAuBsG,KAAvB,CAA8B5E,GAAD,IAAS;QAC1C5C,GAAG,CAAC6C,KAAJ,CAAW,oDAAmDD,GAAI,EAAlE;MACD,CAFK,CAAN;IAGD;;IAED,IAAI,KAAKwB,gBAAT,EAA2B;MACzB,MAAM,KAAKA,gBAAL,CAAsBqD,IAAtB,EAAN;MACA,KAAKrD,gBAAL,GAAwB,IAAxB;IACD;;IAED,IAAI,KAAKjC,GAAT,EAAc;MACZ;MACA;MACA;MACA,KAAK,MAAMuF,SAAX,IAAwB,mBAAKvF,GAAL,wDAAU4C,OAAV,KAAqB,EAA7C,EAAiD;QAAA;;QAC/C,IAAI2C,SAAS,CAAChC,UAAV,KAAyBhG,SAAS,CAACiG,IAAvC,EAA6C;UAC3C+B,SAAS,CAACC,SAAV;QACD;MACF;;MACD,MAAM,IAAIvF,OAAJ,CAAaC,OAAD,IAChB,KAAKF,GAAL,GAAW,KAAKA,GAAL,CAASyF,KAAT,CAAevF,OAAf,CAAX,GAAqCA,OAAO,EADxC,CAAN;MAEA,KAAKF,GAAL,GAAW,IAAX;IACD,CA7ByB,CA+B1B;;;IACA,KAAK,MAAMmF,EAAX,IAAiB,KAAKxG,gBAAtB,EAAwC;MACtC,IAAI;QACFwG,EAAE;MACH,CAFD,CAEE,OAAOO,KAAP,EAAc;QACd7H,GAAG,CAAC6H,KAAJ,CAAUA,KAAV;MACD;IACF;EACF;;AAhYkC"}
1
+ {"version":3,"file":"chromium.js","names":["path","fs","asyncMkdirp","Launcher","ChromeLauncher","launch","defaultChromiumLaunch","WebSocket","WebSocketServer","createLogger","TempDir","isDirectory","fileExists","log","import","meta","url","EXCLUDED_CHROME_FLAGS","DEFAULT_CHROME_FLAGS","defaultFlags","filter","flag","includes","ChromiumExtensionRunner","constructor","params","chromiumLaunch","cleanupCallbacks","Set","getName","run","_promiseSetupDone","setupInstance","isUserDataDir","dirPath","localStatePath","join","defaultPath","isProfileDir","securePreferencesPath","getProfilePaths","chromiumProfile","userDataDir","profileDirName","isProfileDirAndNotUserData","dir","base","parse","wss","Promise","resolve","server","port","host","clientTracking","on","socket","err","debug","reloadManagerExtension","createReloadManagerExtension","extensions","concat","map","sourceDir","chromiumBinary","chromeFlags","push","args","keepProfileChanges","Error","tmpDir","create","tmpDirPath","copy","startingUrl","startUrl","startingUrls","Array","isArray","shift","chromiumInstance","enableExtensions","chromePath","ignoreDefaultFlags","process","once","exiting","info","exit","wssBroadcast","data","clients","cleanWebExtReloadComplete","client","removeEventListener","webExtReloadComplete","delete","message","msg","JSON","type","call","readyState","OPEN","addEventListener","send","stringify","size","registerCleanup","remove","extPath","Date","now","writeFile","manifest_version","name","version","permissions","background","scripts","wssInfo","address","bgPage","reloadAllExtensions","runnerName","stdout","write","toTimeString","reloadExtensionBySourceDir","extensionSourceDir","fn","add","catch","kill","wssClient","terminate","close","error"],"sources":["../../src/extension-runners/chromium.js"],"sourcesContent":["/* @flow */\n\n/**\n * This module provide an ExtensionRunner subclass that manage an extension executed\n * in a Chromium-based browser instance.\n */\n\nimport path from 'path';\n\nimport fs from 'fs-extra';\nimport asyncMkdirp from 'mkdirp';\nimport {\n Launcher as ChromeLauncher,\n launch as defaultChromiumLaunch,\n} from 'chrome-launcher';\nimport WebSocket, {WebSocketServer} from 'ws';\n\nimport {createLogger} from '../util/logger.js';\nimport {TempDir} from '../util/temp-dir.js';\nimport type {\n ExtensionRunnerParams,\n ExtensionRunnerReloadResult,\n} from './base';\nimport isDirectory from '../util/is-directory.js';\nimport fileExists from '../util/file-exists.js';\n\ntype ChromiumSpecificRunnerParams = {|\n chromiumBinary?: string,\n chromiumProfile?: string,\n chromiumLaunch?: typeof defaultChromiumLaunch,\n|};\n\nexport type ChromiumExtensionRunnerParams = {|\n ...ExtensionRunnerParams,\n // Chromium desktop CLI params.\n ...ChromiumSpecificRunnerParams,\n|};\n\nconst log = createLogger(import.meta.url);\n\nconst EXCLUDED_CHROME_FLAGS = [\n '--disable-extensions',\n '--mute-audio',\n];\n\nexport const DEFAULT_CHROME_FLAGS: Array<string> = ChromeLauncher.defaultFlags()\n .filter((flag) => !EXCLUDED_CHROME_FLAGS.includes(flag));\n\n/**\n * Implements an IExtensionRunner which manages a Chromium instance.\n */\nexport class ChromiumExtensionRunner {\n cleanupCallbacks: Set<Function>;\n params: ChromiumExtensionRunnerParams;\n chromiumInstance: ?ChromeLauncher;\n chromiumLaunch: typeof defaultChromiumLaunch;\n reloadManagerExtension: string;\n wss: ?WebSocketServer;\n exiting: boolean;\n _promiseSetupDone: ?Promise<void>;\n\n constructor(params: ChromiumExtensionRunnerParams) {\n const {\n chromiumLaunch = defaultChromiumLaunch,\n } = params;\n this.params = params;\n this.chromiumLaunch = chromiumLaunch;\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 'Chromium';\n }\n\n async run(): Promise<void> {\n // Run should never be called more than once.\n this._promiseSetupDone = this.setupInstance();\n await this._promiseSetupDone;\n }\n\n static async isUserDataDir(dirPath: string): Promise<boolean> {\n const localStatePath = path.join(dirPath, 'Local State');\n const defaultPath = path.join(dirPath, 'Default');\n // Local State and Default are typical for the user-data-dir\n return (await fileExists(localStatePath))\n && (await isDirectory(defaultPath));\n }\n\n static async isProfileDir(dirPath: string): Promise<boolean> {\n const securePreferencesPath = path.join(\n dirPath, 'Secure Preferences');\n //Secure Preferences is typical for a profile dir inside a user data dir\n return await fileExists(securePreferencesPath);\n }\n\n static async getProfilePaths(chromiumProfile: ?string): Promise<{\n userDataDir: ?string,\n profileDirName: ?string\n }> {\n if (!chromiumProfile) {\n return {\n userDataDir: null,\n profileDirName: null,\n };\n }\n\n const isProfileDirAndNotUserData =\n (await ChromiumExtensionRunner.isProfileDir(chromiumProfile))\n && !(await ChromiumExtensionRunner.isUserDataDir(chromiumProfile));\n\n if (isProfileDirAndNotUserData) {\n const {dir: userDataDir, base: profileDirName} =\n path.parse(chromiumProfile);\n return {\n userDataDir,\n profileDirName,\n };\n }\n\n return {\n userDataDir: chromiumProfile,\n profileDirName: null,\n };\n\n }\n\n /**\n * Setup the Chromium Profile and run a Chromium instance.\n */\n async setupInstance(): Promise<void> {\n // Start a websocket server on a free localhost TCP port.\n this.wss = await new Promise((resolve) => {\n const server = new WebSocketServer(\n // Use a ipv4 host so we don't need to escape ipv6 address\n // https://github.com/mozilla/web-ext/issues/2331\n {port: 0, host: '127.0.0.1', clientTracking: true},\n // Wait the server to be listening (so that the extension\n // runner can successfully retrieve server address and port).\n () => resolve(server));\n });\n\n // Prevent unhandled socket error (e.g. when chrome\n // is exiting, See https://github.com/websockets/ws/issues/1256).\n this.wss.on('connection', function(socket) {\n socket.on('error', (err) => {\n log.debug(`websocket connection error: ${err}`);\n });\n });\n\n // Create the extension that will manage the addon reloads\n this.reloadManagerExtension = await this.createReloadManagerExtension();\n\n // Start chrome pointing it to a given profile dir\n const extensions = [this.reloadManagerExtension].concat(\n this.params.extensions.map(({sourceDir}) => sourceDir)\n ).join(',');\n\n const {chromiumBinary} = this.params;\n\n log.debug('Starting Chromium instance...');\n\n if (chromiumBinary) {\n log.debug(`(chromiumBinary: ${chromiumBinary})`);\n }\n\n const chromeFlags = [...DEFAULT_CHROME_FLAGS];\n\n chromeFlags.push(`--load-extension=${extensions}`);\n\n if (this.params.args) {\n chromeFlags.push(...this.params.args);\n }\n\n // eslint-disable-next-line prefer-const\n let {userDataDir, profileDirName} =\n await ChromiumExtensionRunner.getProfilePaths(\n this.params.chromiumProfile);\n\n if (userDataDir && this.params.keepProfileChanges) {\n if (profileDirName\n && !(await ChromiumExtensionRunner.isUserDataDir(userDataDir))) {\n throw new Error('The profile you provided is not in a ' +\n 'user-data-dir. The changes cannot be kept. Please either ' +\n 'remove --keep-profile-changes or use a profile in a ' +\n 'user-data-dir directory');\n }\n } else if (!this.params.keepProfileChanges) {\n // the user provided an existing profile directory but doesn't want\n // the changes to be kept. we copy this directory to a temporary\n // user data dir.\n const tmpDir = new TempDir();\n await tmpDir.create();\n const tmpDirPath = tmpDir.path();\n\n if (userDataDir && profileDirName) {\n // copy profile dir to this temp user data dir.\n await fs.copy(path.join(\n userDataDir,\n profileDirName), path.join(\n tmpDirPath,\n profileDirName),\n );\n } else if (userDataDir) {\n await fs.copy(userDataDir, tmpDirPath);\n }\n userDataDir = tmpDirPath;\n }\n\n if (profileDirName) {\n chromeFlags.push(`--profile-directory=${profileDirName}`);\n }\n\n let startingUrl;\n if (this.params.startUrl) {\n const startingUrls = Array.isArray(this.params.startUrl) ?\n this.params.startUrl : [this.params.startUrl];\n startingUrl = startingUrls.shift();\n chromeFlags.push(...startingUrls);\n }\n\n this.chromiumInstance = await this.chromiumLaunch({\n enableExtensions: true,\n chromePath: chromiumBinary,\n chromeFlags,\n startingUrl,\n userDataDir,\n // Ignore default flags to keep the extension enabled.\n ignoreDefaultFlags: true,\n });\n\n this.chromiumInstance.process.once('close', () => {\n this.chromiumInstance = null;\n\n if (!this.exiting) {\n log.info('Exiting on Chromium instance disconnected.');\n this.exit();\n }\n });\n }\n\n async wssBroadcast(data: Object): Promise<void> {\n return new Promise((resolve) => {\n const clients = this.wss ? new Set(this.wss.clients) : new Set();\n\n function cleanWebExtReloadComplete() {\n const client = this;\n client.removeEventListener('message', webExtReloadComplete);\n client.removeEventListener('close', cleanWebExtReloadComplete);\n clients.delete(client);\n }\n\n const webExtReloadComplete = async (message) => {\n const msg = JSON.parse(message.data);\n\n if (msg.type === 'webExtReloadExtensionComplete') {\n for (const client of clients) {\n cleanWebExtReloadComplete.call(client);\n }\n resolve();\n }\n };\n\n for (const client of clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.addEventListener('message', webExtReloadComplete);\n client.addEventListener('close', cleanWebExtReloadComplete);\n\n client.send(JSON.stringify(data));\n } else {\n clients.delete(client);\n }\n }\n\n if (clients.size === 0) {\n resolve();\n }\n });\n }\n\n async createReloadManagerExtension(): Promise<string> {\n const tmpDir = new TempDir();\n await tmpDir.create();\n this.registerCleanup(() => tmpDir.remove());\n\n const extPath = path.join(\n tmpDir.path(),\n `reload-manager-extension-${Date.now()}`\n );\n\n log.debug(`Creating reload-manager-extension in ${extPath}`);\n\n await asyncMkdirp(extPath);\n\n await fs.writeFile(\n path.join(extPath, 'manifest.json'),\n JSON.stringify({\n manifest_version: 2,\n name: 'web-ext Reload Manager Extension',\n version: '1.0',\n permissions: ['management', 'tabs'],\n background: {\n scripts: ['bg.js'],\n },\n })\n );\n\n // $FlowIgnore: this method is only called right after creating the server and so wss should be defined.\n const wssInfo = this.wss.address();\n\n const bgPage = `(function bgPage() {\n async function getAllDevExtensions() {\n const allExtensions = await new Promise(\n r => chrome.management.getAll(r));\n\n return allExtensions.filter((extension) => {\n return extension.enabled &&\n extension.installType === \"development\" &&\n extension.id !== chrome.runtime.id;\n });\n }\n\n const setEnabled = (extensionId, value) =>\n chrome.runtime.id == extensionId ?\n new Promise.resolve() :\n new Promise(r => chrome.management.setEnabled(extensionId, value, r));\n\n async function reloadExtension(extensionId) {\n await setEnabled(extensionId, false);\n await setEnabled(extensionId, true);\n }\n\n const ws = new window.WebSocket(\n \"ws://${wssInfo.address}:${wssInfo.port}\");\n\n ws.onmessage = async (evt) => {\n const msg = JSON.parse(evt.data);\n if (msg.type === 'webExtReloadAllExtensions') {\n const devExtensions = await getAllDevExtensions();\n await Promise.all(devExtensions.map(ext => reloadExtension(ext.id)));\n ws.send(JSON.stringify({ type: 'webExtReloadExtensionComplete' }));\n }\n };\n })()`;\n\n await fs.writeFile(path.join(extPath, 'bg.js'), bgPage);\n return extPath;\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\n await this.wssBroadcast({\n type: 'webExtReloadAllExtensions',\n });\n\n process.stdout.write(\n `\\rLast extension reload: ${(new Date()).toTimeString()}`);\n log.debug('\\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 // eslint-disable-line no-unused-vars\n ): Promise<Array<ExtensionRunnerReloadResult>> {\n // TODO(rpl): detect the extension ids assigned to the\n // target extensions and map it to the extensions source dir\n // (https://github.com/mozilla/web-ext/issues/1687).\n return this.reloadAllExtensions();\n }\n\n /**\n * Register a callback to be called when the runner has been exited\n * (e.g. the Chromium 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 Chromium instance.\n */\n async exit(): Promise<void> {\n this.exiting = true;\n\n // Wait for the setup to complete if the extension runner is already\n // being started.\n if (this._promiseSetupDone) {\n // Ignore initialization errors if any.\n await this._promiseSetupDone.catch((err) => {\n log.debug(`ignored setup error on chromium runner shutdown: ${err}`);\n });\n }\n\n if (this.chromiumInstance) {\n await this.chromiumInstance.kill();\n this.chromiumInstance = null;\n }\n\n if (this.wss) {\n // Close all websocket clients, closing the WebSocketServer\n // does not terminate the existing connection and it wouldn't\n // resolve until all of the existing connections are closed.\n for (const wssClient of this.wss?.clients || []) {\n if (wssClient.readyState === WebSocket.OPEN) {\n wssClient.terminate();\n }\n }\n await new Promise((resolve) =>\n this.wss ? this.wss.close(resolve) : resolve());\n this.wss = null;\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"],"mappings":";;AAEA;AACA;AACA;AACA;;AAEA,OAAOA,IAAI,MAAM,MAAM;AAEvB,OAAOC,EAAE,MAAM,UAAU;AACzB,OAAOC,WAAW,MAAM,QAAQ;AAChC,SACEC,QAAQ,IAAIC,cAAc,EAC1BC,MAAM,IAAIC,qBAAqB,QAC1B,iBAAiB;AACxB,OAAOC,SAAS,IAAGC,eAAe,QAAO,IAAI;AAE7C,SAAQC,YAAY,QAAO,mBAAmB;AAC9C,SAAQC,OAAO,QAAO,qBAAqB;AAK3C,OAAOC,WAAW,MAAM,yBAAyB;AACjD,OAAOC,UAAU,MAAM,wBAAwB;AAc/C,MAAMC,GAAG,GAAGJ,YAAY,CAACK,MAAM,CAACC,IAAI,CAACC,GAAG,CAAC;AAEzC,MAAMC,qBAAqB,GAAG,CAC5B,sBAAsB,EACtB,cAAc,CACf;AAED,OAAO,MAAMC,oBAAmC,GAAGd,cAAc,CAACe,YAAY,EAAE,CAC7EC,MAAM,CAAEC,IAAI,IAAK,CAACJ,qBAAqB,CAACK,QAAQ,CAACD,IAAI,CAAC,CAAC;;AAE1D;AACA;AACA;AACA,OAAO,MAAME,uBAAuB,CAAC;EAUnCC,WAAW,CAACC,MAAqC,EAAE;IACjD,MAAM;MACJC,cAAc,GAAGpB;IACnB,CAAC,GAAGmB,MAAM;IACV,IAAI,CAACA,MAAM,GAAGA,MAAM;IACpB,IAAI,CAACC,cAAc,GAAGA,cAAc;IACpC,IAAI,CAACC,gBAAgB,GAAG,IAAIC,GAAG,EAAE;EACnC;;EAEA;;EAEA;AACF;AACA;EACEC,OAAO,GAAW;IAChB,OAAO,UAAU;EACnB;EAEA,MAAMC,GAAG,GAAkB;IACzB;IACA,IAAI,CAACC,iBAAiB,GAAG,IAAI,CAACC,aAAa,EAAE;IAC7C,MAAM,IAAI,CAACD,iBAAiB;EAC9B;EAEA,aAAaE,aAAa,CAACC,OAAe,EAAoB;IAC5D,MAAMC,cAAc,GAAGnC,IAAI,CAACoC,IAAI,CAACF,OAAO,EAAE,aAAa,CAAC;IACxD,MAAMG,WAAW,GAAGrC,IAAI,CAACoC,IAAI,CAACF,OAAO,EAAE,SAAS,CAAC;IACjD;IACA,OAAO,CAAC,MAAMtB,UAAU,CAACuB,cAAc,CAAC,MAClC,MAAMxB,WAAW,CAAC0B,WAAW,CAAC,CAAC;EACvC;EAEA,aAAaC,YAAY,CAACJ,OAAe,EAAoB;IAC3D,MAAMK,qBAAqB,GAAGvC,IAAI,CAACoC,IAAI,CACrCF,OAAO,EAAE,oBAAoB,CAAC;IAChC;IACA,OAAO,MAAMtB,UAAU,CAAC2B,qBAAqB,CAAC;EAChD;EAEA,aAAaC,eAAe,CAACC,eAAwB,EAGlD;IACD,IAAI,CAACA,eAAe,EAAE;MACpB,OAAO;QACLC,WAAW,EAAE,IAAI;QACjBC,cAAc,EAAE;MAClB,CAAC;IACH;IAEA,MAAMC,0BAA0B,GAC9B,CAAC,MAAMrB,uBAAuB,CAACe,YAAY,CAACG,eAAe,CAAC,KACzD,EAAE,MAAMlB,uBAAuB,CAACU,aAAa,CAACQ,eAAe,CAAC,CAAC;IAEpE,IAAIG,0BAA0B,EAAE;MAC9B,MAAM;QAACC,GAAG,EAAEH,WAAW;QAAEI,IAAI,EAAEH;MAAc,CAAC,GAC5C3C,IAAI,CAAC+C,KAAK,CAACN,eAAe,CAAC;MAC7B,OAAO;QACLC,WAAW;QACXC;MACF,CAAC;IACH;IAEA,OAAO;MACLD,WAAW,EAAED,eAAe;MAC5BE,cAAc,EAAE;IAClB,CAAC;EAEH;;EAEA;AACF;AACA;EACE,MAAMX,aAAa,GAAkB;IACnC;IACA,IAAI,CAACgB,GAAG,GAAG,MAAM,IAAIC,OAAO,CAAEC,OAAO,IAAK;MACxC,MAAMC,MAAM,GAAG,IAAI3C,eAAe;MAChC;MACA;MACA;QAAC4C,IAAI,EAAE,CAAC;QAAEC,IAAI,EAAE,WAAW;QAAEC,cAAc,EAAE;MAAI,CAAC;MAClD;MACA;MACA,MAAMJ,OAAO,CAACC,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC;;IAEF;IACA;IACA,IAAI,CAACH,GAAG,CAACO,EAAE,CAAC,YAAY,EAAE,UAASC,MAAM,EAAE;MACzCA,MAAM,CAACD,EAAE,CAAC,OAAO,EAAGE,GAAG,IAAK;QAC1B5C,GAAG,CAAC6C,KAAK,CAAE,+BAA8BD,GAAI,EAAC,CAAC;MACjD,CAAC,CAAC;IACJ,CAAC,CAAC;;IAEF;IACA,IAAI,CAACE,sBAAsB,GAAG,MAAM,IAAI,CAACC,4BAA4B,EAAE;;IAEvE;IACA,MAAMC,UAAU,GAAG,CAAC,IAAI,CAACF,sBAAsB,CAAC,CAACG,MAAM,CACrD,IAAI,CAACrC,MAAM,CAACoC,UAAU,CAACE,GAAG,CAAC,CAAC;MAACC;IAAS,CAAC,KAAKA,SAAS,CAAC,CACvD,CAAC5B,IAAI,CAAC,GAAG,CAAC;IAEX,MAAM;MAAC6B;IAAc,CAAC,GAAG,IAAI,CAACxC,MAAM;IAEpCZ,GAAG,CAAC6C,KAAK,CAAC,+BAA+B,CAAC;IAE1C,IAAIO,cAAc,EAAE;MAClBpD,GAAG,CAAC6C,KAAK,CAAE,oBAAmBO,cAAe,GAAE,CAAC;IAClD;IAEA,MAAMC,WAAW,GAAG,CAAC,GAAGhD,oBAAoB,CAAC;IAE7CgD,WAAW,CAACC,IAAI,CAAE,oBAAmBN,UAAW,EAAC,CAAC;IAElD,IAAI,IAAI,CAACpC,MAAM,CAAC2C,IAAI,EAAE;MACpBF,WAAW,CAACC,IAAI,CAAC,GAAG,IAAI,CAAC1C,MAAM,CAAC2C,IAAI,CAAC;IACvC;;IAEA;IACA,IAAI;MAAC1B,WAAW;MAAEC;IAAc,CAAC,GAC/B,MAAMpB,uBAAuB,CAACiB,eAAe,CAC3C,IAAI,CAACf,MAAM,CAACgB,eAAe,CAAC;IAEhC,IAAIC,WAAW,IAAI,IAAI,CAACjB,MAAM,CAAC4C,kBAAkB,EAAE;MACjD,IAAI1B,cAAc,IACb,EAAE,MAAMpB,uBAAuB,CAACU,aAAa,CAACS,WAAW,CAAC,CAAC,EAAE;QAChE,MAAM,IAAI4B,KAAK,CAAC,uCAAuC,GACrD,2DAA2D,GAC3D,sDAAsD,GACtD,yBAAyB,CAAC;MAC9B;IACF,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC7C,MAAM,CAAC4C,kBAAkB,EAAE;MAC1C;MACA;MACA;MACA,MAAME,MAAM,GAAG,IAAI7D,OAAO,EAAE;MAC5B,MAAM6D,MAAM,CAACC,MAAM,EAAE;MACrB,MAAMC,UAAU,GAAGF,MAAM,CAACvE,IAAI,EAAE;MAEhC,IAAI0C,WAAW,IAAIC,cAAc,EAAE;QACjC;QACA,MAAM1C,EAAE,CAACyE,IAAI,CAAC1E,IAAI,CAACoC,IAAI,CACrBM,WAAW,EACXC,cAAc,CAAC,EAAE3C,IAAI,CAACoC,IAAI,CAC1BqC,UAAU,EACV9B,cAAc,CAAC,CAChB;MACH,CAAC,MAAM,IAAID,WAAW,EAAE;QACtB,MAAMzC,EAAE,CAACyE,IAAI,CAAChC,WAAW,EAAE+B,UAAU,CAAC;MACxC;MACA/B,WAAW,GAAG+B,UAAU;IAC1B;IAEA,IAAI9B,cAAc,EAAE;MAClBuB,WAAW,CAACC,IAAI,CAAE,uBAAsBxB,cAAe,EAAC,CAAC;IAC3D;IAEA,IAAIgC,WAAW;IACf,IAAI,IAAI,CAAClD,MAAM,CAACmD,QAAQ,EAAE;MACxB,MAAMC,YAAY,GAAGC,KAAK,CAACC,OAAO,CAAC,IAAI,CAACtD,MAAM,CAACmD,QAAQ,CAAC,GACtD,IAAI,CAACnD,MAAM,CAACmD,QAAQ,GAAG,CAAC,IAAI,CAACnD,MAAM,CAACmD,QAAQ,CAAC;MAC/CD,WAAW,GAAGE,YAAY,CAACG,KAAK,EAAE;MAClCd,WAAW,CAACC,IAAI,CAAC,GAAGU,YAAY,CAAC;IACnC;IAEA,IAAI,CAACI,gBAAgB,GAAG,MAAM,IAAI,CAACvD,cAAc,CAAC;MAChDwD,gBAAgB,EAAE,IAAI;MACtBC,UAAU,EAAElB,cAAc;MAC1BC,WAAW;MACXS,WAAW;MACXjC,WAAW;MACX;MACA0C,kBAAkB,EAAE;IACtB,CAAC,CAAC;IAEF,IAAI,CAACH,gBAAgB,CAACI,OAAO,CAACC,IAAI,CAAC,OAAO,EAAE,MAAM;MAChD,IAAI,CAACL,gBAAgB,GAAG,IAAI;MAE5B,IAAI,CAAC,IAAI,CAACM,OAAO,EAAE;QACjB1E,GAAG,CAAC2E,IAAI,CAAC,4CAA4C,CAAC;QACtD,IAAI,CAACC,IAAI,EAAE;MACb;IACF,CAAC,CAAC;EACJ;EAEA,MAAMC,YAAY,CAACC,IAAY,EAAiB;IAC9C,OAAO,IAAI1C,OAAO,CAAEC,OAAO,IAAK;MAC9B,MAAM0C,OAAO,GAAG,IAAI,CAAC5C,GAAG,GAAG,IAAIpB,GAAG,CAAC,IAAI,CAACoB,GAAG,CAAC4C,OAAO,CAAC,GAAG,IAAIhE,GAAG,EAAE;MAEhE,SAASiE,yBAAyB,GAAG;QACnC,MAAMC,MAAM,GAAG,IAAI;QACnBA,MAAM,CAACC,mBAAmB,CAAC,SAAS,EAAEC,oBAAoB,CAAC;QAC3DF,MAAM,CAACC,mBAAmB,CAAC,OAAO,EAAEF,yBAAyB,CAAC;QAC9DD,OAAO,CAACK,MAAM,CAACH,MAAM,CAAC;MACxB;MAEA,MAAME,oBAAoB,GAAG,MAAOE,OAAO,IAAK;QAC9C,MAAMC,GAAG,GAAGC,IAAI,CAACrD,KAAK,CAACmD,OAAO,CAACP,IAAI,CAAC;QAEpC,IAAIQ,GAAG,CAACE,IAAI,KAAK,+BAA+B,EAAE;UAChD,KAAK,MAAMP,MAAM,IAAIF,OAAO,EAAE;YAC5BC,yBAAyB,CAACS,IAAI,CAACR,MAAM,CAAC;UACxC;UACA5C,OAAO,EAAE;QACX;MACF,CAAC;MAED,KAAK,MAAM4C,MAAM,IAAIF,OAAO,EAAE;QAC5B,IAAIE,MAAM,CAACS,UAAU,KAAKhG,SAAS,CAACiG,IAAI,EAAE;UACxCV,MAAM,CAACW,gBAAgB,CAAC,SAAS,EAAET,oBAAoB,CAAC;UACxDF,MAAM,CAACW,gBAAgB,CAAC,OAAO,EAAEZ,yBAAyB,CAAC;UAE3DC,MAAM,CAACY,IAAI,CAACN,IAAI,CAACO,SAAS,CAAChB,IAAI,CAAC,CAAC;QACnC,CAAC,MAAM;UACLC,OAAO,CAACK,MAAM,CAACH,MAAM,CAAC;QACxB;MACF;MAEA,IAAIF,OAAO,CAACgB,IAAI,KAAK,CAAC,EAAE;QACtB1D,OAAO,EAAE;MACX;IACF,CAAC,CAAC;EACJ;EAEA,MAAMU,4BAA4B,GAAoB;IACpD,MAAMW,MAAM,GAAG,IAAI7D,OAAO,EAAE;IAC5B,MAAM6D,MAAM,CAACC,MAAM,EAAE;IACrB,IAAI,CAACqC,eAAe,CAAC,MAAMtC,MAAM,CAACuC,MAAM,EAAE,CAAC;IAE3C,MAAMC,OAAO,GAAG/G,IAAI,CAACoC,IAAI,CACvBmC,MAAM,CAACvE,IAAI,EAAE,EACZ,4BAA2BgH,IAAI,CAACC,GAAG,EAAG,EAAC,CACzC;IAEDpG,GAAG,CAAC6C,KAAK,CAAE,wCAAuCqD,OAAQ,EAAC,CAAC;IAE5D,MAAM7G,WAAW,CAAC6G,OAAO,CAAC;IAE1B,MAAM9G,EAAE,CAACiH,SAAS,CAChBlH,IAAI,CAACoC,IAAI,CAAC2E,OAAO,EAAE,eAAe,CAAC,EACnCX,IAAI,CAACO,SAAS,CAAC;MACbQ,gBAAgB,EAAE,CAAC;MACnBC,IAAI,EAAE,kCAAkC;MACxCC,OAAO,EAAE,KAAK;MACdC,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;MACnCC,UAAU,EAAE;QACVC,OAAO,EAAE,CAAC,OAAO;MACnB;IACF,CAAC,CAAC,CACH;;IAED;IACA,MAAMC,OAAO,GAAG,IAAI,CAACzE,GAAG,CAAC0E,OAAO,EAAE;IAElC,MAAMC,MAAM,GAAI;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgBF,OAAO,CAACC,OAAQ,IAAGD,OAAO,CAACrE,IAAK;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;IAEL,MAAMnD,EAAE,CAACiH,SAAS,CAAClH,IAAI,CAACoC,IAAI,CAAC2E,OAAO,EAAE,OAAO,CAAC,EAAEY,MAAM,CAAC;IACvD,OAAOZ,OAAO;EAChB;;EAEA;AACF;AACA;AACA;EACE,MAAMa,mBAAmB,GAAgD;IACvE,MAAMC,UAAU,GAAG,IAAI,CAAChG,OAAO,EAAE;IAEjC,MAAM,IAAI,CAAC6D,YAAY,CAAC;MACtBW,IAAI,EAAE;IACR,CAAC,CAAC;IAEFhB,OAAO,CAACyC,MAAM,CAACC,KAAK,CACjB,4BAA4B,IAAIf,IAAI,EAAE,CAAEgB,YAAY,EAAG,EAAC,CAAC;IAC5DnH,GAAG,CAAC6C,KAAK,CAAC,IAAI,CAAC;IAEf,OAAO,CAAC;MAACmE;IAAU,CAAC,CAAC;EACvB;;EAEA;AACF;AACA;AACA;EACE,MAAMI,0BAA0B,CAC9BC,kBAA0B,EACmB;IAC7C;IACA;IACA;IACA,OAAO,IAAI,CAACN,mBAAmB,EAAE;EACnC;;EAEA;AACF;AACA;AACA;AACA;EACEf,eAAe,CAACsB,EAAY,EAAQ;IAClC,IAAI,CAACxG,gBAAgB,CAACyG,GAAG,CAACD,EAAE,CAAC;EAC/B;;EAEA;AACF;AACA;EACE,MAAM1C,IAAI,GAAkB;IAC1B,IAAI,CAACF,OAAO,GAAG,IAAI;;IAEnB;IACA;IACA,IAAI,IAAI,CAACxD,iBAAiB,EAAE;MAC1B;MACA,MAAM,IAAI,CAACA,iBAAiB,CAACsG,KAAK,CAAE5E,GAAG,IAAK;QAC1C5C,GAAG,CAAC6C,KAAK,CAAE,oDAAmDD,GAAI,EAAC,CAAC;MACtE,CAAC,CAAC;IACJ;IAEA,IAAI,IAAI,CAACwB,gBAAgB,EAAE;MACzB,MAAM,IAAI,CAACA,gBAAgB,CAACqD,IAAI,EAAE;MAClC,IAAI,CAACrD,gBAAgB,GAAG,IAAI;IAC9B;IAEA,IAAI,IAAI,CAACjC,GAAG,EAAE;MACZ;MACA;MACA;MACA,KAAK,MAAMuF,SAAS,IAAI,kBAAI,CAACvF,GAAG,8CAAR,UAAU4C,OAAO,KAAI,EAAE,EAAE;QAAA;QAC/C,IAAI2C,SAAS,CAAChC,UAAU,KAAKhG,SAAS,CAACiG,IAAI,EAAE;UAC3C+B,SAAS,CAACC,SAAS,EAAE;QACvB;MACF;MACA,MAAM,IAAIvF,OAAO,CAAEC,OAAO,IACxB,IAAI,CAACF,GAAG,GAAG,IAAI,CAACA,GAAG,CAACyF,KAAK,CAACvF,OAAO,CAAC,GAAGA,OAAO,EAAE,CAAC;MACjD,IAAI,CAACF,GAAG,GAAG,IAAI;IACjB;;IAEA;IACA,KAAK,MAAMmF,EAAE,IAAI,IAAI,CAACxG,gBAAgB,EAAE;MACtC,IAAI;QACFwG,EAAE,EAAE;MACN,CAAC,CAAC,OAAOO,KAAK,EAAE;QACd7H,GAAG,CAAC6H,KAAK,CAACA,KAAK,CAAC;MAClB;IACF;EACF;AACF"}