web-ext 7.1.1 → 7.3.0

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 +30 -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 +75 -47
  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 +75 -77
  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 +19 -18
@@ -1,3 +1,4 @@
1
+
1
2
  import nodeFs from 'fs';
2
3
  import path from 'path';
3
4
  import { promisify } from 'util';
@@ -10,7 +11,8 @@ import { isErrorWithCode, UsageError, WebExtError } from '../errors.js';
10
11
  import { getPrefs as defaultPrefGetter } from './preferences.js';
11
12
  import { getManifestId } from '../util/manifest.js';
12
13
  import { findFreeTcpPort as defaultRemotePortFinder } from './remote.js';
13
- import { createLogger } from '../util/logger.js'; // Import flow types
14
+ import { createLogger } from '../util/logger.js';
15
+ // Import flow types
14
16
 
15
17
  const log = createLogger(import.meta.url);
16
18
  const defaultAsyncFsStat = fs.stat.bind(fs);
@@ -18,7 +20,9 @@ const defaultUserProfileCopier = FirefoxProfile.copyFromUserProfile;
18
20
  export const defaultFirefoxEnv = {
19
21
  XPCOM_DEBUG_BREAK: 'stack',
20
22
  NS_TRACE_MALLOC_DISABLE_STACKS: '1'
21
- }; // defaultRemotePortFinder types and implementation.
23
+ };
24
+
25
+ // defaultRemotePortFinder types and implementation.
22
26
 
23
27
  /*
24
28
  * Runs Firefox with the given profile object and resolves a promise on exit.
@@ -27,21 +31,45 @@ export async function run(profile, {
27
31
  fxRunner = defaultFxRunner,
28
32
  findRemotePort = defaultRemotePortFinder,
29
33
  firefoxBinary,
30
- binaryArgs
34
+ binaryArgs,
35
+ extensions,
36
+ devtools
31
37
  } = {}) {
32
38
  log.debug(`Running Firefox with profile at ${profile.path()}`);
33
39
  const remotePort = await findRemotePort();
40
+ if (firefoxBinary && firefoxBinary.startsWith('flatpak:')) {
41
+ const flatpakAppId = firefoxBinary.substring(8);
42
+ log.debug(`Configuring Firefox with flatpak: appId=${flatpakAppId}`);
43
+
44
+ // This should be resolved by the fx-runner.
45
+ firefoxBinary = 'flatpak';
46
+ binaryArgs = ['run', `--filesystem=${profile.path()}`, ...extensions.map(({
47
+ sourceDir
48
+ }) => `--filesystem=${sourceDir}:ro`),
49
+ // We need to share the network namespace because we want to connect to
50
+ // Firefox with the remote protocol. There is no way to tell flatpak to
51
+ // only expose a port AFAIK.
52
+ '--share=network',
53
+ // Kill the entire sandbox when the launching process dies, which is what
54
+ // we want since exiting web-ext involves `kill` and the process executed
55
+ // here is `flatpak run`.
56
+ '--die-with-parent', flatpakAppId].concat(...(binaryArgs || []));
57
+ }
34
58
  const results = await fxRunner({
35
59
  // if this is falsey, fxRunner tries to find the default one.
36
60
  'binary': firefoxBinary,
37
61
  'binary-args': binaryArgs,
62
+ // For Flatpak we need to respect the order of the command arguments because
63
+ // we have arguments for Flapack (first) and then Firefox.
64
+ 'binary-args-first': firefoxBinary === 'flatpak',
38
65
  // This ensures a new instance of Firefox is created. It has nothing
39
66
  // to do with the devtools remote debugger.
40
67
  'no-remote': true,
41
68
  'listen': remotePort,
42
69
  'foreground': true,
43
70
  'profile': profile.path(),
44
- 'env': { ...process.env,
71
+ 'env': {
72
+ ...process.env,
45
73
  ...defaultFirefoxEnv
46
74
  },
47
75
  'verbose': true
@@ -55,7 +83,13 @@ export async function run(profile, {
55
83
  log.error(`Firefox error: ${error}`);
56
84
  throw error;
57
85
  });
58
- log.info('Use --verbose or open Tools > Web Developer > Browser Console ' + 'to see logging');
86
+ if (!devtools) {
87
+ log.info('Use --verbose or --devtools to see logging');
88
+ }
89
+ if (devtools) {
90
+ log.info('More info about WebExtensions debugging:');
91
+ log.info('https://extensionworkshop.com/documentation/develop/debugging/');
92
+ }
59
93
  firefox.stderr.on('data', data => {
60
94
  log.debug(`Firefox stderr: ${data.toString().trim()}`);
61
95
  });
@@ -69,10 +103,11 @@ export async function run(profile, {
69
103
  firefox,
70
104
  debuggerPort: remotePort
71
105
  };
72
- } // isDefaultProfile types and implementation.
106
+ }
73
107
 
74
- const DEFAULT_PROFILES_NAMES = ['default', 'dev-edition-default'];
108
+ // isDefaultProfile types and implementation.
75
109
 
110
+ const DEFAULT_PROFILES_NAMES = ['default', 'dev-edition-default'];
76
111
  /*
77
112
  * Tests if a profile is a default Firefox profile (both as a profile name or
78
113
  * profile path).
@@ -83,56 +118,56 @@ export async function isDefaultProfile(profilePathOrName, ProfileFinder = Firefo
83
118
  if (DEFAULT_PROFILES_NAMES.includes(profilePathOrName)) {
84
119
  return true;
85
120
  }
86
-
87
121
  const baseProfileDir = ProfileFinder.locateUserDirectory();
88
122
  const profilesIniPath = path.join(baseProfileDir, 'profiles.ini');
89
-
90
123
  try {
91
124
  await fsStat(profilesIniPath);
92
125
  } catch (error) {
93
126
  if (isErrorWithCode('ENOENT', error)) {
94
- log.debug(`profiles.ini not found: ${error}`); // No profiles exist yet, default to false (the default profile name contains a
95
- // random generated component).
127
+ log.debug(`profiles.ini not found: ${error}`);
96
128
 
129
+ // No profiles exist yet, default to false (the default profile name contains a
130
+ // random generated component).
97
131
  return false;
98
- } // Re-throw any unexpected exception.
99
-
132
+ }
100
133
 
134
+ // Re-throw any unexpected exception.
101
135
  throw error;
102
- } // Check for profile dir path.
103
-
136
+ }
104
137
 
138
+ // Check for profile dir path.
105
139
  const finder = new ProfileFinder(baseProfileDir);
106
140
  const readProfiles = promisify((...args) => finder.readProfiles(...args));
107
141
  await readProfiles();
108
142
  const normalizedProfileDirPath = path.normalize(path.join(path.resolve(profilePathOrName), path.sep));
109
-
110
143
  for (const profile of finder.profiles) {
111
144
  // Check if the profile dir path or name is one of the default profiles
112
145
  // defined in the profiles.ini file.
113
146
  if (DEFAULT_PROFILES_NAMES.includes(profile.Name) || profile.Default === '1') {
114
- let profileFullPath; // Check for profile name.
147
+ let profileFullPath;
115
148
 
149
+ // Check for profile name.
116
150
  if (profile.Name === profilePathOrName) {
117
151
  return true;
118
- } // Check for profile path.
119
-
152
+ }
120
153
 
154
+ // Check for profile path.
121
155
  if (profile.IsRelative === '1') {
122
156
  profileFullPath = path.join(baseProfileDir, profile.Path, path.sep);
123
157
  } else {
124
158
  profileFullPath = path.join(profile.Path, path.sep);
125
159
  }
126
-
127
160
  if (path.normalize(profileFullPath) === normalizedProfileDirPath) {
128
161
  return true;
129
162
  }
130
163
  }
131
- } // Profile directory not found.
132
-
164
+ }
133
165
 
166
+ // Profile directory not found.
134
167
  return false;
135
- } // configureProfile types and implementation.
168
+ }
169
+
170
+ // configureProfile types and implementation.
136
171
 
137
172
  /*
138
173
  * Configures a profile with common preferences that are required to
@@ -151,7 +186,6 @@ export function configureProfile(profile, {
151
186
  Object.keys(prefs).forEach(pref => {
152
187
  profile.setPreference(pref, prefs[pref]);
153
188
  });
154
-
155
189
  if (Object.keys(customPrefs).length > 0) {
156
190
  const customPrefsStr = JSON.stringify(customPrefs, null, 2);
157
191
  log.info(`Setting custom Firefox preferences: ${customPrefsStr}`);
@@ -159,7 +193,6 @@ export function configureProfile(profile, {
159
193
  profile.setPreference(custom, customPrefs[custom]);
160
194
  });
161
195
  }
162
-
163
196
  profile.updatePreferences();
164
197
  return Promise.resolve(profile);
165
198
  }
@@ -174,7 +207,6 @@ export function defaultCreateProfileFinder({
174
207
  try {
175
208
  await readProfiles();
176
209
  const hasProfileName = finder.profiles.filter(profileDef => profileDef.Name === profileName).length !== 0;
177
-
178
210
  if (hasProfileName) {
179
211
  return await getPath(profileName);
180
212
  }
@@ -182,13 +214,15 @@ export function defaultCreateProfileFinder({
182
214
  if (!isErrorWithCode('ENOENT', error)) {
183
215
  throw error;
184
216
  }
185
-
186
217
  log.warn('Unable to find Firefox profiles.ini');
187
218
  }
188
219
  };
189
- } // useProfile types and implementation.
220
+ }
221
+
222
+ // useProfile types and implementation.
190
223
 
191
224
  // Use the target path as a Firefox profile without cloning it
225
+
192
226
  export async function useProfile(profilePath, {
193
227
  app,
194
228
  configureThisProfile = configureProfile,
@@ -197,27 +231,22 @@ export async function useProfile(profilePath, {
197
231
  createProfileFinder = defaultCreateProfileFinder
198
232
  } = {}) {
199
233
  const isForbiddenProfile = await isFirefoxDefaultProfile(profilePath);
200
-
201
234
  if (isForbiddenProfile) {
202
235
  throw new UsageError('Cannot use --keep-profile-changes on a default profile' + ` ("${profilePath}")` + ' because web-ext will make it insecure and unsuitable for daily use.' + '\nSee https://github.com/mozilla/web-ext/issues/1005');
203
236
  }
204
-
205
237
  let destinationDirectory;
206
238
  const getProfilePath = createProfileFinder();
207
239
  const profileIsDirPath = await isDirectory(profilePath);
208
-
209
240
  if (profileIsDirPath) {
210
241
  log.debug(`Using profile directory "${profilePath}"`);
211
242
  destinationDirectory = profilePath;
212
243
  } else {
213
244
  log.debug(`Assuming ${profilePath} is a named profile`);
214
245
  destinationDirectory = await getProfilePath(profilePath);
215
-
216
246
  if (!destinationDirectory) {
217
247
  throw new UsageError(`The request "${profilePath}" profile name ` + 'cannot be resolved to a profile path');
218
248
  }
219
249
  }
220
-
221
250
  const profile = new FirefoxProfile({
222
251
  destinationDirectory
223
252
  });
@@ -225,7 +254,9 @@ export async function useProfile(profilePath, {
225
254
  app,
226
255
  customPrefs
227
256
  });
228
- } // createProfile types and implementation.
257
+ }
258
+
259
+ // createProfile types and implementation.
229
260
 
230
261
  /*
231
262
  * Creates a new temporary profile and resolves with the profile object.
@@ -242,7 +273,9 @@ export async function createProfile({
242
273
  app,
243
274
  customPrefs
244
275
  });
245
- } // copyProfile types and implementation.
276
+ }
277
+
278
+ // copyProfile types and implementation.
246
279
 
247
280
  /*
248
281
  * Copies an existing Firefox profile and creates a new temporary profile.
@@ -264,11 +297,9 @@ export async function copyProfile(profileDirectory, {
264
297
  } = {}) {
265
298
  const copy = promisify(FirefoxProfile.copy);
266
299
  const copyByName = promisify(copyFromUserProfile);
267
-
268
300
  try {
269
301
  const dirExists = await isDirectory(profileDirectory);
270
302
  let profile;
271
-
272
303
  if (dirExists) {
273
304
  log.debug(`Copying profile directory from "${profileDirectory}"`);
274
305
  profile = await copy({
@@ -280,7 +311,6 @@ export async function copyProfile(profileDirectory, {
280
311
  name: profileDirectory
281
312
  });
282
313
  }
283
-
284
314
  return configureThisProfile(profile, {
285
315
  app,
286
316
  customPrefs
@@ -288,7 +318,9 @@ export async function copyProfile(profileDirectory, {
288
318
  } catch (error) {
289
319
  throw new WebExtError(`Could not copy Firefox profile from ${profileDirectory}: ${error}`);
290
320
  }
291
- } // installExtension types and implementation.
321
+ }
322
+
323
+ // installExtension types and implementation.
292
324
 
293
325
  /*
294
326
  * Installs an extension into the given Firefox profile object.
@@ -312,10 +344,10 @@ export async function installExtension({
312
344
  // https://github.com/saadtazi/firefox-profile-js/blob/master/lib/firefox_profile.js#L531
313
345
  // (which is broken for web extensions).
314
346
  // TODO: maybe uplift a patch that supports web extensions instead?
347
+
315
348
  if (!profile.extensionsDir) {
316
349
  throw new WebExtError('profile.extensionsDir was unexpectedly empty');
317
350
  }
318
-
319
351
  try {
320
352
  await asyncFsStat(profile.extensionsDir);
321
353
  } catch (error) {
@@ -326,24 +358,20 @@ export async function installExtension({
326
358
  throw error;
327
359
  }
328
360
  }
329
-
330
361
  const id = getManifestId(manifestData);
331
-
332
362
  if (!id) {
333
363
  throw new UsageError('An explicit extension ID is required when installing to ' + 'a profile (applications.gecko.id not found in manifest.json)');
334
364
  }
335
-
336
365
  if (asProxy) {
337
366
  log.debug(`Installing as an extension proxy; source: ${extensionPath}`);
338
367
  const isDir = await isDirectory(extensionPath);
339
-
340
368
  if (!isDir) {
341
369
  throw new WebExtError('proxy install: extensionPath must be the extension source ' + `directory; got: ${extensionPath}`);
342
- } // Write a special extension proxy file containing the source
370
+ }
371
+
372
+ // Write a special extension proxy file containing the source
343
373
  // directory. See:
344
374
  // https://developer.mozilla.org/en-US/Add-ons/Setting_up_extension_development_environment#Firefox_extension_proxy_file
345
-
346
-
347
375
  const destPath = path.join(profile.extensionsDir, `${id}`);
348
376
  const writeStream = nodeFs.createWriteStream(destPath);
349
377
  writeStream.write(extensionPath);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["nodeFs","path","promisify","default","defaultFxRunner","FirefoxProfile","fs","fromEvent","isDirectory","isErrorWithCode","UsageError","WebExtError","getPrefs","defaultPrefGetter","getManifestId","findFreeTcpPort","defaultRemotePortFinder","createLogger","log","import","meta","url","defaultAsyncFsStat","stat","bind","defaultUserProfileCopier","copyFromUserProfile","defaultFirefoxEnv","XPCOM_DEBUG_BREAK","NS_TRACE_MALLOC_DISABLE_STACKS","run","profile","fxRunner","findRemotePort","firefoxBinary","binaryArgs","debug","remotePort","results","process","env","firefox","binary","args","join","on","error","info","stderr","data","toString","trim","stdout","debuggerPort","DEFAULT_PROFILES_NAMES","isDefaultProfile","profilePathOrName","ProfileFinder","Finder","fsStat","includes","baseProfileDir","locateUserDirectory","profilesIniPath","finder","readProfiles","normalizedProfileDirPath","normalize","resolve","sep","profiles","Name","Default","profileFullPath","IsRelative","Path","configureProfile","app","customPrefs","prefs","Object","keys","forEach","pref","setPreference","length","customPrefsStr","JSON","stringify","custom","updatePreferences","Promise","defaultCreateProfileFinder","userDirectoryPath","FxProfile","getPath","profileName","hasProfileName","filter","profileDef","warn","useProfile","profilePath","configureThisProfile","isFirefoxDefaultProfile","createProfileFinder","isForbiddenProfile","destinationDirectory","getProfilePath","profileIsDirPath","createProfile","copyProfile","profileDirectory","copy","copyByName","dirExists","name","installExtension","asProxy","manifestData","extensionPath","asyncFsStat","extensionsDir","mkdir","id","isDir","destPath","writeStream","createWriteStream","write","end","readStream","createReadStream","pipe","all"],"sources":["../../src/firefox/index.js"],"sourcesContent":["/* @flow */\nimport nodeFs from 'fs';\nimport path from 'path';\nimport {promisify} from 'util';\n\nimport {default as defaultFxRunner} from 'fx-runner';\nimport FirefoxProfile from 'firefox-profile';\nimport {fs} from 'mz';\nimport fromEvent from 'promise-toolbox/fromEvent';\n\nimport isDirectory from '../util/is-directory.js';\nimport {isErrorWithCode, UsageError, WebExtError} from '../errors.js';\nimport {getPrefs as defaultPrefGetter} from './preferences.js';\nimport {getManifestId} from '../util/manifest.js';\nimport {findFreeTcpPort as defaultRemotePortFinder} from './remote.js';\nimport {createLogger} from '../util/logger.js';\n// Import flow types\nimport type {\n PreferencesAppName,\n PreferencesGetterFn,\n FirefoxPreferences,\n} from './preferences';\nimport type {ExtensionManifest} from '../util/manifest.js';\n\n\nconst log = createLogger(import.meta.url);\n\nconst defaultAsyncFsStat: typeof fs.stat = fs.stat.bind(fs);\n\nconst defaultUserProfileCopier = FirefoxProfile.copyFromUserProfile;\n\nexport const defaultFirefoxEnv = {\n XPCOM_DEBUG_BREAK: 'stack',\n NS_TRACE_MALLOC_DISABLE_STACKS: '1',\n};\n\n// defaultRemotePortFinder types and implementation.\n\n\nexport type RemotePortFinderFn =\n () => Promise<number>;\n\n// Declare the needed 'fx-runner' module flow types.\n\nexport type FirefoxRunnerParams = {|\n binary: ?string,\n profile?: string,\n 'new-instance'?: boolean,\n 'no-remote'?: boolean,\n 'foreground'?: boolean,\n 'listen': number,\n 'binary-args'?: Array<string> | string,\n 'env'?: {\n // This match the flowtype signature for process.env (and prevent flow\n // from complaining about differences between their type signature)\n [key: string]: string | void\n },\n 'verbose'?: boolean,\n|};\n\nexport interface FirefoxProcess extends events$EventEmitter {\n stderr: events$EventEmitter;\n stdout: events$EventEmitter;\n kill: Function;\n}\n\nexport type FirefoxRunnerResults = {|\n process: FirefoxProcess,\n binary: string,\n args: Array<string>,\n|}\n\nexport type FirefoxRunnerFn =\n (params: FirefoxRunnerParams) => Promise<FirefoxRunnerResults>;\n\n\nexport type FirefoxInfo = {|\n firefox: FirefoxProcess,\n debuggerPort: number,\n|}\n\n// Run command types and implementaion.\n\nexport type FirefoxRunOptions = {\n fxRunner?: FirefoxRunnerFn,\n findRemotePort?: RemotePortFinderFn,\n firefoxBinary?: string,\n binaryArgs?: Array<string>,\n args?: Array<any>,\n};\n\n/*\n * Runs Firefox with the given profile object and resolves a promise on exit.\n */\nexport async function run(\n profile: FirefoxProfile,\n {\n fxRunner = defaultFxRunner,\n findRemotePort = defaultRemotePortFinder,\n firefoxBinary, binaryArgs,\n }: FirefoxRunOptions = {}\n): Promise<FirefoxInfo> {\n\n log.debug(`Running Firefox with profile at ${profile.path()}`);\n\n const remotePort = await findRemotePort();\n\n const results = await fxRunner({\n // if this is falsey, fxRunner tries to find the default one.\n 'binary': firefoxBinary,\n 'binary-args': binaryArgs,\n // This ensures a new instance of Firefox is created. It has nothing\n // to do with the devtools remote debugger.\n 'no-remote': true,\n 'listen': remotePort,\n 'foreground': true,\n 'profile': profile.path(),\n 'env': {\n ...process.env,\n ...defaultFirefoxEnv,\n },\n 'verbose': true,\n });\n\n const firefox = results.process;\n\n log.debug(`Executing Firefox binary: ${results.binary}`);\n log.debug(`Firefox args: ${results.args.join(' ')}`);\n\n firefox.on('error', (error) => {\n // TODO: show a nice error when it can't find Firefox.\n // if (/No such file/.test(err) || err.code === 'ENOENT') {\n log.error(`Firefox error: ${error}`);\n throw error;\n });\n\n log.info(\n 'Use --verbose or open Tools > Web Developer > Browser Console ' +\n 'to see logging');\n\n firefox.stderr.on('data', (data) => {\n log.debug(`Firefox stderr: ${data.toString().trim()}`);\n });\n\n firefox.stdout.on('data', (data) => {\n log.debug(`Firefox stdout: ${data.toString().trim()}`);\n });\n\n firefox.on('close', () => {\n log.debug('Firefox closed');\n });\n\n return { firefox, debuggerPort: remotePort };\n}\n\n\n// isDefaultProfile types and implementation.\n\nconst DEFAULT_PROFILES_NAMES = [\n 'default',\n 'dev-edition-default',\n];\n\nexport type IsDefaultProfileFn = (\n profilePathOrName: string,\n ProfileFinder?: typeof FirefoxProfile.Finder,\n fsStat?: typeof fs.stat,\n) => Promise<boolean>;\n\n/*\n * Tests if a profile is a default Firefox profile (both as a profile name or\n * profile path).\n *\n * Returns a promise that resolves to true if the profile is one of default Firefox profile.\n */\nexport async function isDefaultProfile(\n profilePathOrName: string,\n ProfileFinder?: typeof FirefoxProfile.Finder = FirefoxProfile.Finder,\n fsStat?: typeof fs.stat = fs.stat,\n): Promise<boolean> {\n if (DEFAULT_PROFILES_NAMES.includes(profilePathOrName)) {\n return true;\n }\n\n const baseProfileDir = ProfileFinder.locateUserDirectory();\n const profilesIniPath = path.join(baseProfileDir, 'profiles.ini');\n try {\n await fsStat(profilesIniPath);\n } catch (error) {\n if (isErrorWithCode('ENOENT', error)) {\n log.debug(`profiles.ini not found: ${error}`);\n\n // No profiles exist yet, default to false (the default profile name contains a\n // random generated component).\n return false;\n }\n\n // Re-throw any unexpected exception.\n throw error;\n }\n\n // Check for profile dir path.\n const finder = new ProfileFinder(baseProfileDir);\n const readProfiles = promisify((...args) => finder.readProfiles(...args));\n\n await readProfiles();\n\n const normalizedProfileDirPath = path.normalize(\n path.join(path.resolve(profilePathOrName), path.sep)\n );\n\n for (const profile of finder.profiles) {\n // Check if the profile dir path or name is one of the default profiles\n // defined in the profiles.ini file.\n if (DEFAULT_PROFILES_NAMES.includes(profile.Name) ||\n profile.Default === '1') {\n let profileFullPath;\n\n // Check for profile name.\n if (profile.Name === profilePathOrName) {\n return true;\n }\n\n // Check for profile path.\n if (profile.IsRelative === '1') {\n profileFullPath = path.join(baseProfileDir, profile.Path, path.sep);\n } else {\n profileFullPath = path.join(profile.Path, path.sep);\n }\n\n if (path.normalize(profileFullPath) === normalizedProfileDirPath) {\n return true;\n }\n }\n }\n\n // Profile directory not found.\n return false;\n}\n\n// configureProfile types and implementation.\n\nexport type ConfigureProfileOptions = {\n app?: PreferencesAppName,\n getPrefs?: PreferencesGetterFn,\n customPrefs?: FirefoxPreferences,\n};\n\nexport type ConfigureProfileFn = (\n profile: FirefoxProfile,\n options?: ConfigureProfileOptions\n) => Promise<FirefoxProfile>;\n\n/*\n * Configures a profile with common preferences that are required to\n * activate extension development.\n *\n * Returns a promise that resolves with the original profile object.\n */\nexport function configureProfile(\n profile: FirefoxProfile,\n {\n app = 'firefox',\n getPrefs = defaultPrefGetter,\n customPrefs = {},\n }: ConfigureProfileOptions = {},\n): Promise<FirefoxProfile> {\n // Set default preferences. Some of these are required for the add-on to\n // operate, such as disabling signatures.\n const prefs = getPrefs(app);\n Object.keys(prefs).forEach((pref) => {\n profile.setPreference(pref, prefs[pref]);\n });\n if (Object.keys(customPrefs).length > 0) {\n const customPrefsStr = JSON.stringify(customPrefs, null, 2);\n log.info(`Setting custom Firefox preferences: ${customPrefsStr}`);\n Object.keys(customPrefs).forEach((custom) => {\n profile.setPreference(custom, customPrefs[custom]);\n });\n }\n profile.updatePreferences();\n return Promise.resolve(profile);\n}\n\nexport type getProfileFn = (profileName: string) => Promise<string | void>;\n\nexport type CreateProfileFinderParams = {\n userDirectoryPath?: string,\n FxProfile?: typeof FirefoxProfile\n}\n\nexport function defaultCreateProfileFinder(\n {\n userDirectoryPath,\n FxProfile = FirefoxProfile,\n }: CreateProfileFinderParams = {}\n): getProfileFn {\n const finder = new FxProfile.Finder(userDirectoryPath);\n const readProfiles = promisify((...args) => finder.readProfiles(...args));\n const getPath = promisify((...args) => finder.getPath(...args));\n return async (profileName: string): Promise<string | void> => {\n try {\n await readProfiles();\n const hasProfileName = finder.profiles.filter(\n (profileDef) => profileDef.Name === profileName).length !== 0;\n if (hasProfileName) {\n return await getPath(profileName);\n }\n } catch (error) {\n if (!isErrorWithCode('ENOENT', error)) {\n throw error;\n }\n log.warn('Unable to find Firefox profiles.ini');\n }\n };\n}\n\n// useProfile types and implementation.\n\nexport type UseProfileParams = {\n app?: PreferencesAppName,\n configureThisProfile?: ConfigureProfileFn,\n isFirefoxDefaultProfile?: IsDefaultProfileFn,\n customPrefs?: FirefoxPreferences,\n createProfileFinder?: typeof defaultCreateProfileFinder,\n};\n\n// Use the target path as a Firefox profile without cloning it\n\nexport async function useProfile(\n profilePath: string,\n {\n app,\n configureThisProfile = configureProfile,\n isFirefoxDefaultProfile = isDefaultProfile,\n customPrefs = {},\n createProfileFinder = defaultCreateProfileFinder,\n }: UseProfileParams = {},\n): Promise<FirefoxProfile> {\n const isForbiddenProfile = await isFirefoxDefaultProfile(profilePath);\n if (isForbiddenProfile) {\n throw new UsageError(\n 'Cannot use --keep-profile-changes on a default profile' +\n ` (\"${profilePath}\")` +\n ' because web-ext will make it insecure and unsuitable for daily use.' +\n '\\nSee https://github.com/mozilla/web-ext/issues/1005'\n );\n }\n\n let destinationDirectory;\n const getProfilePath = createProfileFinder();\n\n const profileIsDirPath = await isDirectory(profilePath);\n if (profileIsDirPath) {\n log.debug(`Using profile directory \"${profilePath}\"`);\n destinationDirectory = profilePath;\n } else {\n log.debug(`Assuming ${profilePath} is a named profile`);\n destinationDirectory = await getProfilePath(profilePath);\n if (!destinationDirectory) {\n throw new UsageError(\n `The request \"${profilePath}\" profile name ` +\n 'cannot be resolved to a profile path'\n );\n }\n }\n\n const profile = new FirefoxProfile({destinationDirectory});\n return await configureThisProfile(profile, {app, customPrefs});\n}\n\n\n// createProfile types and implementation.\n\nexport type CreateProfileParams = {\n app?: PreferencesAppName,\n configureThisProfile?: ConfigureProfileFn,\n customPrefs?: FirefoxPreferences,\n};\n\n/*\n * Creates a new temporary profile and resolves with the profile object.\n *\n * The profile will be deleted when the system process exits.\n */\nexport async function createProfile(\n {\n app,\n configureThisProfile = configureProfile,\n customPrefs = {},\n }: CreateProfileParams = {},\n): Promise<FirefoxProfile> {\n const profile = new FirefoxProfile();\n return await configureThisProfile(profile, {app, customPrefs});\n}\n\n\n// copyProfile types and implementation.\n\nexport type CopyProfileOptions = {\n app?: PreferencesAppName,\n configureThisProfile?: ConfigureProfileFn,\n copyFromUserProfile?: Function,\n customPrefs?: FirefoxPreferences,\n};\n\n/*\n * Copies an existing Firefox profile and creates a new temporary profile.\n * The new profile will be configured with some preferences required to\n * activate extension development.\n *\n * It resolves with the new profile object.\n *\n * The temporary profile will be deleted when the system process exits.\n *\n * The existing profile can be specified as a directory path or a name of\n * one that exists in the current user's Firefox directory.\n */\nexport async function copyProfile(\n profileDirectory: string,\n {\n app,\n configureThisProfile = configureProfile,\n copyFromUserProfile = defaultUserProfileCopier,\n customPrefs = {},\n }: CopyProfileOptions = {},\n): Promise<FirefoxProfile> {\n\n const copy = promisify(FirefoxProfile.copy);\n const copyByName = promisify(copyFromUserProfile);\n\n try {\n const dirExists = await isDirectory(profileDirectory);\n\n let profile;\n\n if (dirExists) {\n log.debug(`Copying profile directory from \"${profileDirectory}\"`);\n profile = await copy({profileDirectory});\n } else {\n log.debug(`Assuming ${profileDirectory} is a named profile`);\n profile = await copyByName({name: profileDirectory});\n }\n\n return configureThisProfile(profile, {app, customPrefs});\n } catch (error) {\n throw new WebExtError(\n `Could not copy Firefox profile from ${profileDirectory}: ${error}`);\n }\n}\n\n\n// installExtension types and implementation.\n\nexport type InstallExtensionParams = {|\n asProxy?: boolean,\n manifestData: ExtensionManifest,\n profile: FirefoxProfile,\n extensionPath: string,\n asyncFsStat?: typeof defaultAsyncFsStat,\n|};\n\n/*\n * Installs an extension into the given Firefox profile object.\n * Resolves when complete.\n *\n * The extension is copied into a special location and you need to turn\n * on some preferences to allow this. See extensions.autoDisableScopes in\n * ./preferences.js.\n *\n * When asProxy is true, a special proxy file will be installed. This is a\n * text file that contains the path to the extension source.\n */\nexport async function installExtension(\n {\n asProxy = false,\n manifestData,\n profile,\n extensionPath,\n asyncFsStat = defaultAsyncFsStat,\n }: InstallExtensionParams): Promise<any> {\n // This more or less follows\n // https://github.com/saadtazi/firefox-profile-js/blob/master/lib/firefox_profile.js#L531\n // (which is broken for web extensions).\n // TODO: maybe uplift a patch that supports web extensions instead?\n\n if (!profile.extensionsDir) {\n throw new WebExtError('profile.extensionsDir was unexpectedly empty');\n }\n\n try {\n await asyncFsStat(profile.extensionsDir);\n } catch (error) {\n if (isErrorWithCode('ENOENT', error)) {\n log.debug(`Creating extensions directory: ${profile.extensionsDir}`);\n await fs.mkdir(profile.extensionsDir);\n } else {\n throw error;\n }\n }\n\n const id = getManifestId(manifestData);\n if (!id) {\n throw new UsageError(\n 'An explicit extension ID is required when installing to ' +\n 'a profile (applications.gecko.id not found in manifest.json)');\n }\n\n if (asProxy) {\n log.debug(`Installing as an extension proxy; source: ${extensionPath}`);\n\n const isDir = await isDirectory(extensionPath);\n if (!isDir) {\n throw new WebExtError(\n 'proxy install: extensionPath must be the extension source ' +\n `directory; got: ${extensionPath}`);\n }\n\n // Write a special extension proxy file containing the source\n // directory. See:\n // https://developer.mozilla.org/en-US/Add-ons/Setting_up_extension_development_environment#Firefox_extension_proxy_file\n const destPath = path.join(profile.extensionsDir, `${id}`);\n const writeStream = nodeFs.createWriteStream(destPath);\n writeStream.write(extensionPath);\n writeStream.end();\n return await fromEvent(writeStream, 'close');\n } else {\n // Write the XPI file to the profile.\n const readStream = nodeFs.createReadStream(extensionPath);\n const destPath = path.join(profile.extensionsDir, `${id}.xpi`);\n const writeStream = nodeFs.createWriteStream(destPath);\n\n log.debug(`Installing extension from ${extensionPath} to ${destPath}`);\n readStream.pipe(writeStream);\n\n return await Promise.all([\n fromEvent(readStream, 'close'),\n fromEvent(writeStream, 'close'),\n ]);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["nodeFs","path","promisify","default","defaultFxRunner","FirefoxProfile","fs","fromEvent","isDirectory","isErrorWithCode","UsageError","WebExtError","getPrefs","defaultPrefGetter","getManifestId","findFreeTcpPort","defaultRemotePortFinder","createLogger","log","import","meta","url","defaultAsyncFsStat","stat","bind","defaultUserProfileCopier","copyFromUserProfile","defaultFirefoxEnv","XPCOM_DEBUG_BREAK","NS_TRACE_MALLOC_DISABLE_STACKS","run","profile","fxRunner","findRemotePort","firefoxBinary","binaryArgs","extensions","devtools","debug","remotePort","startsWith","flatpakAppId","substring","map","sourceDir","concat","results","process","env","firefox","binary","args","join","on","error","info","stderr","data","toString","trim","stdout","debuggerPort","DEFAULT_PROFILES_NAMES","isDefaultProfile","profilePathOrName","ProfileFinder","Finder","fsStat","includes","baseProfileDir","locateUserDirectory","profilesIniPath","finder","readProfiles","normalizedProfileDirPath","normalize","resolve","sep","profiles","Name","Default","profileFullPath","IsRelative","Path","configureProfile","app","customPrefs","prefs","Object","keys","forEach","pref","setPreference","length","customPrefsStr","JSON","stringify","custom","updatePreferences","Promise","defaultCreateProfileFinder","userDirectoryPath","FxProfile","getPath","profileName","hasProfileName","filter","profileDef","warn","useProfile","profilePath","configureThisProfile","isFirefoxDefaultProfile","createProfileFinder","isForbiddenProfile","destinationDirectory","getProfilePath","profileIsDirPath","createProfile","copyProfile","profileDirectory","copy","copyByName","dirExists","name","installExtension","asProxy","manifestData","extensionPath","asyncFsStat","extensionsDir","mkdir","id","isDir","destPath","writeStream","createWriteStream","write","end","readStream","createReadStream","pipe","all"],"sources":["../../src/firefox/index.js"],"sourcesContent":["/* @flow */\nimport nodeFs from 'fs';\nimport path from 'path';\nimport {promisify} from 'util';\n\nimport {default as defaultFxRunner} from 'fx-runner';\nimport FirefoxProfile from 'firefox-profile';\nimport {fs} from 'mz';\nimport fromEvent from 'promise-toolbox/fromEvent';\n\nimport isDirectory from '../util/is-directory.js';\nimport {isErrorWithCode, UsageError, WebExtError} from '../errors.js';\nimport {getPrefs as defaultPrefGetter} from './preferences.js';\nimport {getManifestId} from '../util/manifest.js';\nimport {findFreeTcpPort as defaultRemotePortFinder} from './remote.js';\nimport {createLogger} from '../util/logger.js';\n// Import flow types\nimport type {\n PreferencesAppName,\n PreferencesGetterFn,\n FirefoxPreferences,\n} from './preferences';\nimport type {ExtensionManifest} from '../util/manifest.js';\nimport type {Extension} from '../extension-runners/base.js';\n\n\nconst log = createLogger(import.meta.url);\n\nconst defaultAsyncFsStat: typeof fs.stat = fs.stat.bind(fs);\n\nconst defaultUserProfileCopier = FirefoxProfile.copyFromUserProfile;\n\nexport const defaultFirefoxEnv = {\n XPCOM_DEBUG_BREAK: 'stack',\n NS_TRACE_MALLOC_DISABLE_STACKS: '1',\n};\n\n// defaultRemotePortFinder types and implementation.\n\n\nexport type RemotePortFinderFn =\n () => Promise<number>;\n\n// Declare the needed 'fx-runner' module flow types.\n\nexport type FirefoxRunnerParams = {|\n binary: ?string,\n profile?: string,\n 'new-instance'?: boolean,\n 'no-remote'?: boolean,\n 'foreground'?: boolean,\n 'listen': number,\n 'binary-args'?: Array<string> | string,\n 'binary-args-first'?: boolean,\n 'env'?: {\n // This match the flowtype signature for process.env (and prevent flow\n // from complaining about differences between their type signature)\n [key: string]: string | void\n },\n 'verbose'?: boolean,\n|};\n\nexport interface FirefoxProcess extends events$EventEmitter {\n stderr: events$EventEmitter;\n stdout: events$EventEmitter;\n kill: Function;\n}\n\nexport type FirefoxRunnerResults = {|\n process: FirefoxProcess,\n binary: string,\n args: Array<string>,\n|}\n\nexport type FirefoxRunnerFn =\n (params: FirefoxRunnerParams) => Promise<FirefoxRunnerResults>;\n\n\nexport type FirefoxInfo = {|\n firefox: FirefoxProcess,\n debuggerPort: number,\n|}\n\n// Run command types and implementaion.\n\nexport type FirefoxRunOptions = {\n fxRunner?: FirefoxRunnerFn,\n findRemotePort?: RemotePortFinderFn,\n firefoxBinary?: string,\n binaryArgs?: Array<string>,\n args?: Array<any>,\n extensions: Array<Extension>,\n devtools: boolean,\n};\n\n/*\n * Runs Firefox with the given profile object and resolves a promise on exit.\n */\nexport async function run(\n profile: FirefoxProfile,\n {\n fxRunner = defaultFxRunner,\n findRemotePort = defaultRemotePortFinder,\n firefoxBinary,\n binaryArgs,\n extensions,\n devtools,\n }: FirefoxRunOptions = {}\n): Promise<FirefoxInfo> {\n\n log.debug(`Running Firefox with profile at ${profile.path()}`);\n\n const remotePort = await findRemotePort();\n\n if (firefoxBinary && firefoxBinary.startsWith('flatpak:')) {\n const flatpakAppId = firefoxBinary.substring(8);\n log.debug(`Configuring Firefox with flatpak: appId=${flatpakAppId}`);\n\n // This should be resolved by the fx-runner.\n firefoxBinary = 'flatpak';\n binaryArgs = [\n 'run',\n `--filesystem=${profile.path()}`,\n ...extensions.map(({ sourceDir }) => `--filesystem=${sourceDir}:ro`),\n // We need to share the network namespace because we want to connect to\n // Firefox with the remote protocol. There is no way to tell flatpak to\n // only expose a port AFAIK.\n '--share=network',\n // Kill the entire sandbox when the launching process dies, which is what\n // we want since exiting web-ext involves `kill` and the process executed\n // here is `flatpak run`.\n '--die-with-parent',\n flatpakAppId,\n ].concat(...(binaryArgs || []));\n }\n\n const results = await fxRunner({\n // if this is falsey, fxRunner tries to find the default one.\n 'binary': firefoxBinary,\n 'binary-args': binaryArgs,\n // For Flatpak we need to respect the order of the command arguments because\n // we have arguments for Flapack (first) and then Firefox.\n 'binary-args-first': firefoxBinary === 'flatpak',\n // This ensures a new instance of Firefox is created. It has nothing\n // to do with the devtools remote debugger.\n 'no-remote': true,\n 'listen': remotePort,\n 'foreground': true,\n 'profile': profile.path(),\n 'env': {\n ...process.env,\n ...defaultFirefoxEnv,\n },\n 'verbose': true,\n });\n\n const firefox = results.process;\n\n log.debug(`Executing Firefox binary: ${results.binary}`);\n log.debug(`Firefox args: ${results.args.join(' ')}`);\n\n firefox.on('error', (error) => {\n // TODO: show a nice error when it can't find Firefox.\n // if (/No such file/.test(err) || err.code === 'ENOENT') {\n log.error(`Firefox error: ${error}`);\n throw error;\n });\n\n if (!devtools) {\n log.info('Use --verbose or --devtools to see logging');\n }\n if (devtools) {\n log.info('More info about WebExtensions debugging:');\n log.info('https://extensionworkshop.com/documentation/develop/debugging/');\n }\n\n firefox.stderr.on('data', (data) => {\n log.debug(`Firefox stderr: ${data.toString().trim()}`);\n });\n\n firefox.stdout.on('data', (data) => {\n log.debug(`Firefox stdout: ${data.toString().trim()}`);\n });\n\n firefox.on('close', () => {\n log.debug('Firefox closed');\n });\n\n return { firefox, debuggerPort: remotePort };\n}\n\n\n// isDefaultProfile types and implementation.\n\nconst DEFAULT_PROFILES_NAMES = [\n 'default',\n 'dev-edition-default',\n];\n\nexport type IsDefaultProfileFn = (\n profilePathOrName: string,\n ProfileFinder?: typeof FirefoxProfile.Finder,\n fsStat?: typeof fs.stat,\n) => Promise<boolean>;\n\n/*\n * Tests if a profile is a default Firefox profile (both as a profile name or\n * profile path).\n *\n * Returns a promise that resolves to true if the profile is one of default Firefox profile.\n */\nexport async function isDefaultProfile(\n profilePathOrName: string,\n ProfileFinder?: typeof FirefoxProfile.Finder = FirefoxProfile.Finder,\n fsStat?: typeof fs.stat = fs.stat,\n): Promise<boolean> {\n if (DEFAULT_PROFILES_NAMES.includes(profilePathOrName)) {\n return true;\n }\n\n const baseProfileDir = ProfileFinder.locateUserDirectory();\n const profilesIniPath = path.join(baseProfileDir, 'profiles.ini');\n try {\n await fsStat(profilesIniPath);\n } catch (error) {\n if (isErrorWithCode('ENOENT', error)) {\n log.debug(`profiles.ini not found: ${error}`);\n\n // No profiles exist yet, default to false (the default profile name contains a\n // random generated component).\n return false;\n }\n\n // Re-throw any unexpected exception.\n throw error;\n }\n\n // Check for profile dir path.\n const finder = new ProfileFinder(baseProfileDir);\n const readProfiles = promisify((...args) => finder.readProfiles(...args));\n\n await readProfiles();\n\n const normalizedProfileDirPath = path.normalize(\n path.join(path.resolve(profilePathOrName), path.sep)\n );\n\n for (const profile of finder.profiles) {\n // Check if the profile dir path or name is one of the default profiles\n // defined in the profiles.ini file.\n if (DEFAULT_PROFILES_NAMES.includes(profile.Name) ||\n profile.Default === '1') {\n let profileFullPath;\n\n // Check for profile name.\n if (profile.Name === profilePathOrName) {\n return true;\n }\n\n // Check for profile path.\n if (profile.IsRelative === '1') {\n profileFullPath = path.join(baseProfileDir, profile.Path, path.sep);\n } else {\n profileFullPath = path.join(profile.Path, path.sep);\n }\n\n if (path.normalize(profileFullPath) === normalizedProfileDirPath) {\n return true;\n }\n }\n }\n\n // Profile directory not found.\n return false;\n}\n\n// configureProfile types and implementation.\n\nexport type ConfigureProfileOptions = {\n app?: PreferencesAppName,\n getPrefs?: PreferencesGetterFn,\n customPrefs?: FirefoxPreferences,\n};\n\nexport type ConfigureProfileFn = (\n profile: FirefoxProfile,\n options?: ConfigureProfileOptions\n) => Promise<FirefoxProfile>;\n\n/*\n * Configures a profile with common preferences that are required to\n * activate extension development.\n *\n * Returns a promise that resolves with the original profile object.\n */\nexport function configureProfile(\n profile: FirefoxProfile,\n {\n app = 'firefox',\n getPrefs = defaultPrefGetter,\n customPrefs = {},\n }: ConfigureProfileOptions = {},\n): Promise<FirefoxProfile> {\n // Set default preferences. Some of these are required for the add-on to\n // operate, such as disabling signatures.\n const prefs = getPrefs(app);\n Object.keys(prefs).forEach((pref) => {\n profile.setPreference(pref, prefs[pref]);\n });\n if (Object.keys(customPrefs).length > 0) {\n const customPrefsStr = JSON.stringify(customPrefs, null, 2);\n log.info(`Setting custom Firefox preferences: ${customPrefsStr}`);\n Object.keys(customPrefs).forEach((custom) => {\n profile.setPreference(custom, customPrefs[custom]);\n });\n }\n profile.updatePreferences();\n return Promise.resolve(profile);\n}\n\nexport type getProfileFn = (profileName: string) => Promise<string | void>;\n\nexport type CreateProfileFinderParams = {\n userDirectoryPath?: string,\n FxProfile?: typeof FirefoxProfile\n}\n\nexport function defaultCreateProfileFinder(\n {\n userDirectoryPath,\n FxProfile = FirefoxProfile,\n }: CreateProfileFinderParams = {}\n): getProfileFn {\n const finder = new FxProfile.Finder(userDirectoryPath);\n const readProfiles = promisify((...args) => finder.readProfiles(...args));\n const getPath = promisify((...args) => finder.getPath(...args));\n return async (profileName: string): Promise<string | void> => {\n try {\n await readProfiles();\n const hasProfileName = finder.profiles.filter(\n (profileDef) => profileDef.Name === profileName).length !== 0;\n if (hasProfileName) {\n return await getPath(profileName);\n }\n } catch (error) {\n if (!isErrorWithCode('ENOENT', error)) {\n throw error;\n }\n log.warn('Unable to find Firefox profiles.ini');\n }\n };\n}\n\n// useProfile types and implementation.\n\nexport type UseProfileParams = {\n app?: PreferencesAppName,\n configureThisProfile?: ConfigureProfileFn,\n isFirefoxDefaultProfile?: IsDefaultProfileFn,\n customPrefs?: FirefoxPreferences,\n createProfileFinder?: typeof defaultCreateProfileFinder,\n};\n\n// Use the target path as a Firefox profile without cloning it\n\nexport async function useProfile(\n profilePath: string,\n {\n app,\n configureThisProfile = configureProfile,\n isFirefoxDefaultProfile = isDefaultProfile,\n customPrefs = {},\n createProfileFinder = defaultCreateProfileFinder,\n }: UseProfileParams = {},\n): Promise<FirefoxProfile> {\n const isForbiddenProfile = await isFirefoxDefaultProfile(profilePath);\n if (isForbiddenProfile) {\n throw new UsageError(\n 'Cannot use --keep-profile-changes on a default profile' +\n ` (\"${profilePath}\")` +\n ' because web-ext will make it insecure and unsuitable for daily use.' +\n '\\nSee https://github.com/mozilla/web-ext/issues/1005'\n );\n }\n\n let destinationDirectory;\n const getProfilePath = createProfileFinder();\n\n const profileIsDirPath = await isDirectory(profilePath);\n if (profileIsDirPath) {\n log.debug(`Using profile directory \"${profilePath}\"`);\n destinationDirectory = profilePath;\n } else {\n log.debug(`Assuming ${profilePath} is a named profile`);\n destinationDirectory = await getProfilePath(profilePath);\n if (!destinationDirectory) {\n throw new UsageError(\n `The request \"${profilePath}\" profile name ` +\n 'cannot be resolved to a profile path'\n );\n }\n }\n\n const profile = new FirefoxProfile({destinationDirectory});\n return await configureThisProfile(profile, {app, customPrefs});\n}\n\n\n// createProfile types and implementation.\n\nexport type CreateProfileParams = {\n app?: PreferencesAppName,\n configureThisProfile?: ConfigureProfileFn,\n customPrefs?: FirefoxPreferences,\n};\n\n/*\n * Creates a new temporary profile and resolves with the profile object.\n *\n * The profile will be deleted when the system process exits.\n */\nexport async function createProfile(\n {\n app,\n configureThisProfile = configureProfile,\n customPrefs = {},\n }: CreateProfileParams = {},\n): Promise<FirefoxProfile> {\n const profile = new FirefoxProfile();\n return await configureThisProfile(profile, {app, customPrefs});\n}\n\n\n// copyProfile types and implementation.\n\nexport type CopyProfileOptions = {\n app?: PreferencesAppName,\n configureThisProfile?: ConfigureProfileFn,\n copyFromUserProfile?: Function,\n customPrefs?: FirefoxPreferences,\n};\n\n/*\n * Copies an existing Firefox profile and creates a new temporary profile.\n * The new profile will be configured with some preferences required to\n * activate extension development.\n *\n * It resolves with the new profile object.\n *\n * The temporary profile will be deleted when the system process exits.\n *\n * The existing profile can be specified as a directory path or a name of\n * one that exists in the current user's Firefox directory.\n */\nexport async function copyProfile(\n profileDirectory: string,\n {\n app,\n configureThisProfile = configureProfile,\n copyFromUserProfile = defaultUserProfileCopier,\n customPrefs = {},\n }: CopyProfileOptions = {},\n): Promise<FirefoxProfile> {\n\n const copy = promisify(FirefoxProfile.copy);\n const copyByName = promisify(copyFromUserProfile);\n\n try {\n const dirExists = await isDirectory(profileDirectory);\n\n let profile;\n\n if (dirExists) {\n log.debug(`Copying profile directory from \"${profileDirectory}\"`);\n profile = await copy({profileDirectory});\n } else {\n log.debug(`Assuming ${profileDirectory} is a named profile`);\n profile = await copyByName({name: profileDirectory});\n }\n\n return configureThisProfile(profile, {app, customPrefs});\n } catch (error) {\n throw new WebExtError(\n `Could not copy Firefox profile from ${profileDirectory}: ${error}`);\n }\n}\n\n\n// installExtension types and implementation.\n\nexport type InstallExtensionParams = {|\n asProxy?: boolean,\n manifestData: ExtensionManifest,\n profile: FirefoxProfile,\n extensionPath: string,\n asyncFsStat?: typeof defaultAsyncFsStat,\n|};\n\n/*\n * Installs an extension into the given Firefox profile object.\n * Resolves when complete.\n *\n * The extension is copied into a special location and you need to turn\n * on some preferences to allow this. See extensions.autoDisableScopes in\n * ./preferences.js.\n *\n * When asProxy is true, a special proxy file will be installed. This is a\n * text file that contains the path to the extension source.\n */\nexport async function installExtension(\n {\n asProxy = false,\n manifestData,\n profile,\n extensionPath,\n asyncFsStat = defaultAsyncFsStat,\n }: InstallExtensionParams): Promise<any> {\n // This more or less follows\n // https://github.com/saadtazi/firefox-profile-js/blob/master/lib/firefox_profile.js#L531\n // (which is broken for web extensions).\n // TODO: maybe uplift a patch that supports web extensions instead?\n\n if (!profile.extensionsDir) {\n throw new WebExtError('profile.extensionsDir was unexpectedly empty');\n }\n\n try {\n await asyncFsStat(profile.extensionsDir);\n } catch (error) {\n if (isErrorWithCode('ENOENT', error)) {\n log.debug(`Creating extensions directory: ${profile.extensionsDir}`);\n await fs.mkdir(profile.extensionsDir);\n } else {\n throw error;\n }\n }\n\n const id = getManifestId(manifestData);\n if (!id) {\n throw new UsageError(\n 'An explicit extension ID is required when installing to ' +\n 'a profile (applications.gecko.id not found in manifest.json)');\n }\n\n if (asProxy) {\n log.debug(`Installing as an extension proxy; source: ${extensionPath}`);\n\n const isDir = await isDirectory(extensionPath);\n if (!isDir) {\n throw new WebExtError(\n 'proxy install: extensionPath must be the extension source ' +\n `directory; got: ${extensionPath}`);\n }\n\n // Write a special extension proxy file containing the source\n // directory. See:\n // https://developer.mozilla.org/en-US/Add-ons/Setting_up_extension_development_environment#Firefox_extension_proxy_file\n const destPath = path.join(profile.extensionsDir, `${id}`);\n const writeStream = nodeFs.createWriteStream(destPath);\n writeStream.write(extensionPath);\n writeStream.end();\n return await fromEvent(writeStream, 'close');\n } else {\n // Write the XPI file to the profile.\n const readStream = nodeFs.createReadStream(extensionPath);\n const destPath = path.join(profile.extensionsDir, `${id}.xpi`);\n const writeStream = nodeFs.createWriteStream(destPath);\n\n log.debug(`Installing extension from ${extensionPath} to ${destPath}`);\n readStream.pipe(writeStream);\n\n return await Promise.all([\n fromEvent(readStream, 'close'),\n fromEvent(writeStream, 'close'),\n ]);\n }\n}\n"],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+
2
+
1
3
  export default ['org.mozilla.fennec', 'org.mozilla.fenix', 'org.mozilla.geckoview_example', 'org.mozilla.geckoview', 'org.mozilla.firefox', 'org.mozilla.reference.browser'];
2
4
  export const defaultApkComponents = {
3
5
  'org.mozilla.reference.browser': '.BrowserActivity'
@@ -1 +1 @@
1
- {"version":3,"file":"package-identifiers.js","names":["defaultApkComponents"],"sources":["../../src/firefox/package-identifiers.js"],"sourcesContent":["/* @flow */\n\nexport default [\n 'org.mozilla.fennec',\n 'org.mozilla.fenix',\n 'org.mozilla.geckoview_example',\n 'org.mozilla.geckoview',\n 'org.mozilla.firefox',\n 'org.mozilla.reference.browser',\n];\n\nexport const defaultApkComponents = {\n 'org.mozilla.reference.browser': '.BrowserActivity',\n};\n"],"mappings":"AAEA,eAAe,CACb,oBADa,EAEb,mBAFa,EAGb,+BAHa,EAIb,uBAJa,EAKb,qBALa,EAMb,+BANa,CAAf;AASA,OAAO,MAAMA,oBAAoB,GAAG;EAClC,iCAAiC;AADC,CAA7B"}
1
+ {"version":3,"file":"package-identifiers.js","names":["defaultApkComponents"],"sources":["../../src/firefox/package-identifiers.js"],"sourcesContent":["/* @flow */\n\nexport default [\n 'org.mozilla.fennec',\n 'org.mozilla.fenix',\n 'org.mozilla.geckoview_example',\n 'org.mozilla.geckoview',\n 'org.mozilla.firefox',\n 'org.mozilla.reference.browser',\n];\n\nexport const defaultApkComponents = {\n 'org.mozilla.reference.browser': '.BrowserActivity',\n};\n"],"mappings":";;AAEA,eAAe,CACb,oBAAoB,EACpB,mBAAmB,EACnB,+BAA+B,EAC/B,uBAAuB,EACvB,qBAAqB,EACrB,+BAA+B,CAChC;AAED,OAAO,MAAMA,oBAAoB,GAAG;EAClC,+BAA+B,EAAE;AACnC,CAAC"}
@@ -1,9 +1,13 @@
1
+
1
2
  import { WebExtError, UsageError } from '../errors.js';
2
3
  import { createLogger } from '../util/logger.js';
3
4
  const log = createLogger(import.meta.url);
4
- export const nonOverridablePreferences = ['devtools.debugger.remote-enabled', 'devtools.debugger.prompt-connection', 'xpinstall.signatures.required']; // Flow Types
5
+ export const nonOverridablePreferences = ['devtools.debugger.remote-enabled', 'devtools.debugger.prompt-connection', 'xpinstall.signatures.required'];
6
+
7
+ // Flow Types
5
8
 
6
9
  // Preferences Maps
10
+
7
11
  const prefsCommon = {
8
12
  // Allow debug output via dump to be printed to the system console
9
13
  'browser.dom.window.dump.enabled': true,
@@ -42,14 +46,16 @@ const prefsCommon = {
42
46
  // https://github.com/saadtazi/firefox-profile-js/blob/cafc793d940a779d280103ae17d02a92de862efc/lib/firefox_profile.js#L32
43
47
  // Restore original value to avoid https://github.com/mozilla/web-ext/issues/1592
44
48
  'browser.link.open_newwindow': 3
45
- }; // Prefs specific to Firefox for Android.
49
+ };
46
50
 
51
+ // Prefs specific to Firefox for Android.
47
52
  const prefsFennec = {
48
53
  'browser.console.showInPanel': true,
49
54
  'browser.firstrun.show.uidiscovery': false,
50
55
  'devtools.remote.usb.enabled': true
51
- }; // Prefs specific to Firefox for desktop.
56
+ };
52
57
 
58
+ // Prefs specific to Firefox for desktop.
53
59
  const prefsFirefox = {
54
60
  'browser.startup.homepage': 'about:blank',
55
61
  'startup.homepage_welcome_url': 'about:blank',
@@ -77,50 +83,43 @@ const prefs = {
77
83
  common: prefsCommon,
78
84
  fennec: prefsFennec,
79
85
  firefox: prefsFirefox
80
- }; // Module exports
86
+ };
87
+
88
+ // Module exports
81
89
 
82
90
  export function getPrefs(app = 'firefox') {
83
91
  const appPrefs = prefs[app];
84
-
85
92
  if (!appPrefs) {
86
93
  throw new WebExtError(`Unsupported application: ${app}`);
87
94
  }
88
-
89
- return { ...prefsCommon,
95
+ return {
96
+ ...prefsCommon,
90
97
  ...appPrefs
91
98
  };
92
99
  }
93
100
  export function coerceCLICustomPreference(cliPrefs) {
94
101
  const customPrefs = {};
95
-
96
102
  for (const pref of cliPrefs) {
97
103
  const prefsAry = pref.split('=');
98
-
99
104
  if (prefsAry.length < 2) {
100
105
  throw new UsageError(`Incomplete custom preference: "${pref}". ` + 'Syntax expected: "prefname=prefvalue".');
101
106
  }
102
-
103
107
  const key = prefsAry[0];
104
108
  let value = prefsAry.slice(1).join('=');
105
-
106
109
  if (/[^\w{@}.-]/.test(key)) {
107
110
  throw new UsageError(`Invalid custom preference name: ${key}`);
108
111
  }
109
-
110
112
  if (value === `${parseInt(value)}`) {
111
113
  value = parseInt(value, 10);
112
114
  } else if (value === 'true' || value === 'false') {
113
115
  value = value === 'true';
114
116
  }
115
-
116
117
  if (nonOverridablePreferences.includes(key)) {
117
118
  log.warn(`'${key}' preference cannot be customized.`);
118
119
  continue;
119
120
  }
120
-
121
121
  customPrefs[`${key}`] = value;
122
122
  }
123
-
124
123
  return customPrefs;
125
124
  }
126
125
  //# sourceMappingURL=preferences.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"preferences.js","names":["WebExtError","UsageError","createLogger","log","import","meta","url","nonOverridablePreferences","prefsCommon","prefsFennec","prefsFirefox","prefs","common","fennec","firefox","getPrefs","app","appPrefs","coerceCLICustomPreference","cliPrefs","customPrefs","pref","prefsAry","split","length","key","value","slice","join","test","parseInt","includes","warn"],"sources":["../../src/firefox/preferences.js"],"sourcesContent":["/* @flow */\nimport {WebExtError, UsageError} from '../errors.js';\nimport {createLogger} from '../util/logger.js';\n\nconst log = createLogger(import.meta.url);\n\nexport const nonOverridablePreferences = [\n 'devtools.debugger.remote-enabled', 'devtools.debugger.prompt-connection',\n 'xpinstall.signatures.required',\n];\n\n// Flow Types\n\nexport type FirefoxPreferences = {\n [key: string]: boolean | string | number,\n};\n\nexport type PreferencesAppName = 'firefox' | 'fennec';\n\n\n// Preferences Maps\n\nconst prefsCommon: FirefoxPreferences = {\n // Allow debug output via dump to be printed to the system console\n 'browser.dom.window.dump.enabled': true,\n\n // From:\n // https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/internals/preferences.html#data-choices-notification\n // This is the data submission master kill switch. If disabled, no policy is shown or upload takes place, ever.\n 'datareporting.policy.dataSubmissionEnabled': false,\n\n // Allow remote connections to the debugger.\n 'devtools.debugger.remote-enabled': true,\n // Disable the prompt for allowing connections.\n 'devtools.debugger.prompt-connection': false,\n // Allow extensions to log messages on browser's console.\n 'devtools.browserconsole.contentMessages': true,\n\n // Turn off platform logging because it is a lot of info.\n 'extensions.logging.enabled': false,\n\n // Disable extension updates and notifications.\n 'extensions.checkCompatibility.nightly': false,\n 'extensions.update.enabled': false,\n 'extensions.update.notifyUser': false,\n\n // From:\n // http://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in//l372\n // Only load extensions from the application and user profile.\n // AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION\n 'extensions.enabledScopes': 5,\n // Disable metadata caching for installed add-ons by default.\n 'extensions.getAddons.cache.enabled': false,\n // Disable intalling any distribution add-ons.\n 'extensions.installDistroAddons': false,\n // Allow installing extensions dropped into the profile folder.\n 'extensions.autoDisableScopes': 10,\n\n // Disable app update.\n 'app.update.enabled': false,\n\n // Allow unsigned add-ons.\n 'xpinstall.signatures.required': false,\n\n // browser.link.open_newwindow is changed from 3 to 2 in:\n // https://github.com/saadtazi/firefox-profile-js/blob/cafc793d940a779d280103ae17d02a92de862efc/lib/firefox_profile.js#L32\n // Restore original value to avoid https://github.com/mozilla/web-ext/issues/1592\n 'browser.link.open_newwindow': 3,\n};\n\n// Prefs specific to Firefox for Android.\nconst prefsFennec: FirefoxPreferences = {\n 'browser.console.showInPanel': true,\n 'browser.firstrun.show.uidiscovery': false,\n 'devtools.remote.usb.enabled': true,\n};\n\n// Prefs specific to Firefox for desktop.\nconst prefsFirefox: FirefoxPreferences = {\n 'browser.startup.homepage': 'about:blank',\n 'startup.homepage_welcome_url': 'about:blank',\n 'startup.homepage_welcome_url.additional': '',\n 'devtools.errorconsole.enabled': true,\n 'devtools.chrome.enabled': true,\n\n // From:\n // http://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in//l388\n // Make url-classifier updates so rare that they won't affect tests.\n 'urlclassifier.updateinterval': 172800,\n // Point the url-classifier to a nonexistent local URL for fast failures.\n 'browser.safebrowsing.provider.0.gethashURL':\n 'http://localhost/safebrowsing-dummy/gethash',\n 'browser.safebrowsing.provider.0.keyURL':\n 'http://localhost/safebrowsing-dummy/newkey',\n 'browser.safebrowsing.provider.0.updateURL':\n 'http://localhost/safebrowsing-dummy/update',\n\n // Disable self repair/SHIELD\n 'browser.selfsupport.url': 'https://localhost/selfrepair',\n // Disable Reader Mode UI tour\n 'browser.reader.detectedFirstArticle': true,\n\n // Set the policy firstURL to an empty string to prevent\n // the privacy info page to be opened on every \"web-ext run\".\n // (See #1114 for rationale)\n 'datareporting.policy.firstRunURL': '',\n};\n\nconst prefs = {\n common: prefsCommon,\n fennec: prefsFennec,\n firefox: prefsFirefox,\n};\n\n\n// Module exports\n\nexport type PreferencesGetterFn =\n (appName: PreferencesAppName) => FirefoxPreferences;\n\nexport function getPrefs(\n app: PreferencesAppName = 'firefox'\n): FirefoxPreferences {\n const appPrefs = prefs[app];\n if (!appPrefs) {\n throw new WebExtError(`Unsupported application: ${app}`);\n }\n return {\n ...prefsCommon,\n ...appPrefs,\n };\n}\n\nexport function coerceCLICustomPreference(\n cliPrefs: Array<string>\n): FirefoxPreferences {\n const customPrefs = {};\n\n for (const pref of cliPrefs) {\n const prefsAry = pref.split('=');\n\n if (prefsAry.length < 2) {\n throw new UsageError(\n `Incomplete custom preference: \"${pref}\". ` +\n 'Syntax expected: \"prefname=prefvalue\".'\n );\n }\n\n const key = prefsAry[0];\n let value = prefsAry.slice(1).join('=');\n\n if (/[^\\w{@}.-]/.test(key)) {\n throw new UsageError(`Invalid custom preference name: ${key}`);\n }\n\n if (value === `${parseInt(value)}`) {\n value = parseInt(value, 10);\n } else if (value === 'true' || value === 'false') {\n value = (value === 'true');\n }\n\n if (nonOverridablePreferences.includes(key)) {\n log.warn(`'${key}' preference cannot be customized.`);\n continue;\n }\n customPrefs[`${key}`] = value;\n }\n\n return customPrefs;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"preferences.js","names":["WebExtError","UsageError","createLogger","log","import","meta","url","nonOverridablePreferences","prefsCommon","prefsFennec","prefsFirefox","prefs","common","fennec","firefox","getPrefs","app","appPrefs","coerceCLICustomPreference","cliPrefs","customPrefs","pref","prefsAry","split","length","key","value","slice","join","test","parseInt","includes","warn"],"sources":["../../src/firefox/preferences.js"],"sourcesContent":["/* @flow */\nimport {WebExtError, UsageError} from '../errors.js';\nimport {createLogger} from '../util/logger.js';\n\nconst log = createLogger(import.meta.url);\n\nexport const nonOverridablePreferences = [\n 'devtools.debugger.remote-enabled', 'devtools.debugger.prompt-connection',\n 'xpinstall.signatures.required',\n];\n\n// Flow Types\n\nexport type FirefoxPreferences = {\n [key: string]: boolean | string | number,\n};\n\nexport type PreferencesAppName = 'firefox' | 'fennec';\n\n\n// Preferences Maps\n\nconst prefsCommon: FirefoxPreferences = {\n // Allow debug output via dump to be printed to the system console\n 'browser.dom.window.dump.enabled': true,\n\n // From:\n // https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/internals/preferences.html#data-choices-notification\n // This is the data submission master kill switch. If disabled, no policy is shown or upload takes place, ever.\n 'datareporting.policy.dataSubmissionEnabled': false,\n\n // Allow remote connections to the debugger.\n 'devtools.debugger.remote-enabled': true,\n // Disable the prompt for allowing connections.\n 'devtools.debugger.prompt-connection': false,\n // Allow extensions to log messages on browser's console.\n 'devtools.browserconsole.contentMessages': true,\n\n // Turn off platform logging because it is a lot of info.\n 'extensions.logging.enabled': false,\n\n // Disable extension updates and notifications.\n 'extensions.checkCompatibility.nightly': false,\n 'extensions.update.enabled': false,\n 'extensions.update.notifyUser': false,\n\n // From:\n // http://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in//l372\n // Only load extensions from the application and user profile.\n // AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION\n 'extensions.enabledScopes': 5,\n // Disable metadata caching for installed add-ons by default.\n 'extensions.getAddons.cache.enabled': false,\n // Disable intalling any distribution add-ons.\n 'extensions.installDistroAddons': false,\n // Allow installing extensions dropped into the profile folder.\n 'extensions.autoDisableScopes': 10,\n\n // Disable app update.\n 'app.update.enabled': false,\n\n // Allow unsigned add-ons.\n 'xpinstall.signatures.required': false,\n\n // browser.link.open_newwindow is changed from 3 to 2 in:\n // https://github.com/saadtazi/firefox-profile-js/blob/cafc793d940a779d280103ae17d02a92de862efc/lib/firefox_profile.js#L32\n // Restore original value to avoid https://github.com/mozilla/web-ext/issues/1592\n 'browser.link.open_newwindow': 3,\n};\n\n// Prefs specific to Firefox for Android.\nconst prefsFennec: FirefoxPreferences = {\n 'browser.console.showInPanel': true,\n 'browser.firstrun.show.uidiscovery': false,\n 'devtools.remote.usb.enabled': true,\n};\n\n// Prefs specific to Firefox for desktop.\nconst prefsFirefox: FirefoxPreferences = {\n 'browser.startup.homepage': 'about:blank',\n 'startup.homepage_welcome_url': 'about:blank',\n 'startup.homepage_welcome_url.additional': '',\n 'devtools.errorconsole.enabled': true,\n 'devtools.chrome.enabled': true,\n\n // From:\n // http://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in//l388\n // Make url-classifier updates so rare that they won't affect tests.\n 'urlclassifier.updateinterval': 172800,\n // Point the url-classifier to a nonexistent local URL for fast failures.\n 'browser.safebrowsing.provider.0.gethashURL':\n 'http://localhost/safebrowsing-dummy/gethash',\n 'browser.safebrowsing.provider.0.keyURL':\n 'http://localhost/safebrowsing-dummy/newkey',\n 'browser.safebrowsing.provider.0.updateURL':\n 'http://localhost/safebrowsing-dummy/update',\n\n // Disable self repair/SHIELD\n 'browser.selfsupport.url': 'https://localhost/selfrepair',\n // Disable Reader Mode UI tour\n 'browser.reader.detectedFirstArticle': true,\n\n // Set the policy firstURL to an empty string to prevent\n // the privacy info page to be opened on every \"web-ext run\".\n // (See #1114 for rationale)\n 'datareporting.policy.firstRunURL': '',\n};\n\nconst prefs = {\n common: prefsCommon,\n fennec: prefsFennec,\n firefox: prefsFirefox,\n};\n\n\n// Module exports\n\nexport type PreferencesGetterFn =\n (appName: PreferencesAppName) => FirefoxPreferences;\n\nexport function getPrefs(\n app: PreferencesAppName = 'firefox'\n): FirefoxPreferences {\n const appPrefs = prefs[app];\n if (!appPrefs) {\n throw new WebExtError(`Unsupported application: ${app}`);\n }\n return {\n ...prefsCommon,\n ...appPrefs,\n };\n}\n\nexport function coerceCLICustomPreference(\n cliPrefs: Array<string>\n): FirefoxPreferences {\n const customPrefs = {};\n\n for (const pref of cliPrefs) {\n const prefsAry = pref.split('=');\n\n if (prefsAry.length < 2) {\n throw new UsageError(\n `Incomplete custom preference: \"${pref}\". ` +\n 'Syntax expected: \"prefname=prefvalue\".'\n );\n }\n\n const key = prefsAry[0];\n let value = prefsAry.slice(1).join('=');\n\n if (/[^\\w{@}.-]/.test(key)) {\n throw new UsageError(`Invalid custom preference name: ${key}`);\n }\n\n if (value === `${parseInt(value)}`) {\n value = parseInt(value, 10);\n } else if (value === 'true' || value === 'false') {\n value = (value === 'true');\n }\n\n if (nonOverridablePreferences.includes(key)) {\n log.warn(`'${key}' preference cannot be customized.`);\n continue;\n }\n customPrefs[`${key}`] = value;\n }\n\n return customPrefs;\n}\n"],"mappings":"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"}