export async function installExtension()

in src/firefox/index.js [376:444]


export async function installExtension({
  asProxy = false,
  manifestData,
  profile,
  extensionPath,
  asyncFsStat = defaultAsyncFsStat,
}) {
  // This more or less follows
  // https://github.com/saadtazi/firefox-profile-js/blob/master/lib/firefox_profile.js#L531
  // (which is broken for web extensions).
  // TODO: maybe uplift a patch that supports web extensions instead?

  if (!profile.extensionsDir) {
    throw new WebExtError('profile.extensionsDir was unexpectedly empty');
  }

  try {
    await asyncFsStat(profile.extensionsDir);
  } catch (error) {
    if (isErrorWithCode('ENOENT', error)) {
      log.debug(`Creating extensions directory: ${profile.extensionsDir}`);
      await fs.mkdir(profile.extensionsDir);
    } else {
      throw error;
    }
  }

  const id = getManifestId(manifestData);
  if (!id) {
    throw new UsageError(
      'An explicit extension ID is required when installing to ' +
        'a profile (applications.gecko.id not found in manifest.json)',
    );
  }

  if (asProxy) {
    log.debug(`Installing as an extension proxy; source: ${extensionPath}`);

    const isDir = await isDirectory(extensionPath);
    if (!isDir) {
      throw new WebExtError(
        'proxy install: extensionPath must be the extension source ' +
          `directory; got: ${extensionPath}`,
      );
    }

    // Write a special extension proxy file containing the source
    // directory. See:
    // https://developer.mozilla.org/en-US/Add-ons/Setting_up_extension_development_environment#Firefox_extension_proxy_file
    const destPath = path.join(profile.extensionsDir, `${id}`);
    const writeStream = nodeFs.createWriteStream(destPath);
    writeStream.write(extensionPath);
    writeStream.end();
    return await fromEvent(writeStream, 'close');
  } else {
    // Write the XPI file to the profile.
    const readStream = nodeFs.createReadStream(extensionPath);
    const destPath = path.join(profile.extensionsDir, `${id}.xpi`);
    const writeStream = nodeFs.createWriteStream(destPath);

    log.debug(`Installing extension from ${extensionPath} to ${destPath}`);
    readStream.pipe(writeStream);

    return await Promise.all([
      fromEvent(readStream, 'close'),
      fromEvent(writeStream, 'close'),
    ]);
  }
}