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();
}
});
}