async setupInstance()

in src/extension-runners/chromium.js [112:227]


  async setupInstance() {
    // Start a websocket server on a free localhost TCP port.
    this.wss = await new Promise((resolve) => {
      const server = new WebSocketServer(
        // Use a ipv4 host so we don't need to escape ipv6 address
        // https://github.com/mozilla/web-ext/issues/2331
        { port: 0, host: '127.0.0.1', clientTracking: true },
        // Wait the server to be listening (so that the extension
        // runner can successfully retrieve server address and port).
        () => resolve(server),
      );
    });

    // Prevent unhandled socket error (e.g. when chrome
    // is exiting, See https://github.com/websockets/ws/issues/1256).
    this.wss.on('connection', function (socket) {
      socket.on('error', (err) => {
        log.debug(`websocket connection error: ${err}`);
      });
    });

    // Create the extension that will manage the addon reloads
    this.reloadManagerExtension = await this.createReloadManagerExtension();

    // Start chrome pointing it to a given profile dir
    const extensions = [this.reloadManagerExtension]
      .concat(this.params.extensions.map(({ sourceDir }) => sourceDir))
      .join(',');

    const { chromiumBinary } = this.params;

    log.debug('Starting Chromium instance...');

    if (chromiumBinary) {
      log.debug(`(chromiumBinary: ${chromiumBinary})`);
    }

    const chromeFlags = [...DEFAULT_CHROME_FLAGS];

    chromeFlags.push(`--load-extension=${extensions}`);

    if (this.params.args) {
      chromeFlags.push(...this.params.args);
    }

    // eslint-disable-next-line prefer-const
    let { userDataDir, profileDirName } =
      await ChromiumExtensionRunner.getProfilePaths(
        this.params.chromiumProfile,
      );

    if (userDataDir && this.params.keepProfileChanges) {
      if (
        profileDirName &&
        !(await ChromiumExtensionRunner.isUserDataDir(userDataDir))
      ) {
        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',
        );
      }
    } else if (!this.params.keepProfileChanges) {
      // the user provided an existing profile directory but doesn't want
      // the changes to be kept. we copy this directory to a temporary
      // user data dir.
      const tmpDir = new TempDir();
      await tmpDir.create();
      const tmpDirPath = tmpDir.path();

      if (userDataDir && profileDirName) {
        // copy profile dir to this temp user data dir.
        await fs.cp(
          path.join(userDataDir, profileDirName),
          path.join(tmpDirPath, profileDirName),
          { recursive: true },
        );
      } else if (userDataDir) {
        await fs.cp(userDataDir, tmpDirPath, { recursive: true });
      }
      userDataDir = tmpDirPath;
    }

    if (profileDirName) {
      chromeFlags.push(`--profile-directory=${profileDirName}`);
    }

    let startingUrl;
    if (this.params.startUrl) {
      const startingUrls = Array.isArray(this.params.startUrl)
        ? this.params.startUrl
        : [this.params.startUrl];
      startingUrl = startingUrls.shift();
      chromeFlags.push(...startingUrls);
    }

    this.chromiumInstance = await this.chromiumLaunch({
      enableExtensions: true,
      chromePath: chromiumBinary,
      chromeFlags,
      startingUrl,
      userDataDir,
      // Ignore default flags to keep the extension enabled.
      ignoreDefaultFlags: true,
    });

    this.chromiumInstance.process.once('close', () => {
      this.chromiumInstance = null;

      if (!this.exiting) {
        log.info('Exiting on Chromium instance disconnected.');
        this.exit();
      }
    });
  }