Skip to content

Commit 085481f

Browse files
committed
chore: Remove WebSocket-based reloading from chromium runner
The new CDP-based chrome extension loader does not need WebSockets to manage extension reloading logic. This patch removes all traces of WebSocket based extension reloading from web-ext, including unit tests that tested WebSocket-specific logic. The following commits will restore this functionality using CDP.
1 parent dbe56dc commit 085481f

File tree

5 files changed

+17
-379
lines changed

5 files changed

+17
-379
lines changed

package-lock.json

Lines changed: 0 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@
8484
"tmp": "0.2.3",
8585
"update-notifier": "7.3.1",
8686
"watchpack": "2.4.4",
87-
"ws": "8.18.2",
8887
"yargs": "17.7.2",
8988
"zip-dir": "2.0.0"
9089
},

src/extension-runners/chromium.js

Lines changed: 3 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
Launcher as ChromeLauncher,
1111
launch as defaultChromiumLaunch,
1212
} from 'chrome-launcher';
13-
import WebSocket, { WebSocketServer } from 'ws';
1413

1514
import { createLogger } from '../util/logger.js';
1615
import { TempDir } from '../util/temp-dir.js';
@@ -37,8 +36,6 @@ export class ChromiumExtensionRunner {
3736
params;
3837
chromiumInstance;
3938
chromiumLaunch;
40-
reloadManagerExtension;
41-
wss;
4239
exiting;
4340
_promiseSetupDone;
4441

@@ -110,32 +107,9 @@ export class ChromiumExtensionRunner {
110107
* Setup the Chromium Profile and run a Chromium instance.
111108
*/
112109
async setupInstance() {
113-
// Start a websocket server on a free localhost TCP port.
114-
this.wss = await new Promise((resolve) => {
115-
const server = new WebSocketServer(
116-
// Use a ipv4 host so we don't need to escape ipv6 address
117-
// https://github.com/mozilla/web-ext/issues/2331
118-
{ port: 0, host: '127.0.0.1', clientTracking: true },
119-
// Wait the server to be listening (so that the extension
120-
// runner can successfully retrieve server address and port).
121-
() => resolve(server),
122-
);
123-
});
124-
125-
// Prevent unhandled socket error (e.g. when chrome
126-
// is exiting, See https://github.com/websockets/ws/issues/1256).
127-
this.wss.on('connection', function (socket) {
128-
socket.on('error', (err) => {
129-
log.debug(`websocket connection error: ${err}`);
130-
});
131-
});
132-
133-
// Create the extension that will manage the addon reloads
134-
this.reloadManagerExtension = await this.createReloadManagerExtension();
135-
136110
// Start chrome pointing it to a given profile dir
137-
const extensions = [this.reloadManagerExtension]
138-
.concat(this.params.extensions.map(({ sourceDir }) => sourceDir))
111+
const extensions = this.params.extensions
112+
.map(({ sourceDir }) => sourceDir)
139113
.join(',');
140114

141115
const { chromiumBinary } = this.params;
@@ -226,123 +200,14 @@ export class ChromiumExtensionRunner {
226200
});
227201
}
228202

229-
async wssBroadcast(data) {
230-
return new Promise((resolve) => {
231-
const clients = this.wss ? new Set(this.wss.clients) : new Set();
232-
233-
function cleanWebExtReloadComplete() {
234-
const client = this;
235-
client.removeEventListener('message', webExtReloadComplete);
236-
client.removeEventListener('close', cleanWebExtReloadComplete);
237-
clients.delete(client);
238-
}
239-
240-
const webExtReloadComplete = async (message) => {
241-
const msg = JSON.parse(message.data);
242-
243-
if (msg.type === 'webExtReloadExtensionComplete') {
244-
for (const client of clients) {
245-
cleanWebExtReloadComplete.call(client);
246-
}
247-
resolve();
248-
}
249-
};
250-
251-
for (const client of clients) {
252-
if (client.readyState === WebSocket.OPEN) {
253-
client.addEventListener('message', webExtReloadComplete);
254-
client.addEventListener('close', cleanWebExtReloadComplete);
255-
256-
client.send(JSON.stringify(data));
257-
} else {
258-
clients.delete(client);
259-
}
260-
}
261-
262-
if (clients.size === 0) {
263-
resolve();
264-
}
265-
});
266-
}
267-
268-
async createReloadManagerExtension() {
269-
const tmpDir = new TempDir();
270-
await tmpDir.create();
271-
this.registerCleanup(() => tmpDir.remove());
272-
273-
const extPath = path.join(
274-
tmpDir.path(),
275-
`reload-manager-extension-${Date.now()}`,
276-
);
277-
278-
log.debug(`Creating reload-manager-extension in ${extPath}`);
279-
280-
await fs.mkdir(extPath, { recursive: true });
281-
282-
await fs.writeFile(
283-
path.join(extPath, 'manifest.json'),
284-
JSON.stringify({
285-
manifest_version: 2,
286-
name: 'web-ext Reload Manager Extension',
287-
version: '1.0',
288-
permissions: ['management', 'tabs'],
289-
background: {
290-
scripts: ['bg.js'],
291-
},
292-
}),
293-
);
294-
295-
const wssInfo = this.wss.address();
296-
297-
const bgPage = `(function bgPage() {
298-
async function getAllDevExtensions() {
299-
const allExtensions = await new Promise(
300-
r => chrome.management.getAll(r));
301-
302-
return allExtensions.filter((extension) => {
303-
return extension.enabled &&
304-
extension.installType === "development" &&
305-
extension.id !== chrome.runtime.id;
306-
});
307-
}
308-
309-
const setEnabled = (extensionId, value) =>
310-
chrome.runtime.id == extensionId ?
311-
new Promise.resolve() :
312-
new Promise(r => chrome.management.setEnabled(extensionId, value, r));
313-
314-
async function reloadExtension(extensionId) {
315-
await setEnabled(extensionId, false);
316-
await setEnabled(extensionId, true);
317-
}
318-
319-
const ws = new window.WebSocket(
320-
"ws://${wssInfo.address}:${wssInfo.port}");
321-
322-
ws.onmessage = async (evt) => {
323-
const msg = JSON.parse(evt.data);
324-
if (msg.type === 'webExtReloadAllExtensions') {
325-
const devExtensions = await getAllDevExtensions();
326-
await Promise.all(devExtensions.map(ext => reloadExtension(ext.id)));
327-
ws.send(JSON.stringify({ type: 'webExtReloadExtensionComplete' }));
328-
}
329-
};
330-
})()`;
331-
332-
await fs.writeFile(path.join(extPath, 'bg.js'), bgPage);
333-
return extPath;
334-
}
335-
336203
/**
337204
* Reloads all the extensions, collect any reload error and resolves to
338205
* an array composed by a single ExtensionRunnerReloadResult object.
339206
*/
340207
async reloadAllExtensions() {
341208
const runnerName = this.getName();
342209

343-
await this.wssBroadcast({
344-
type: 'webExtReloadAllExtensions',
345-
});
210+
// TODO: Restore reload functionality using the remote debugging protocol.
346211

347212
process.stdout.write(
348213
`\rLast extension reload: ${new Date().toTimeString()}`,
@@ -394,21 +259,6 @@ export class ChromiumExtensionRunner {
394259
this.chromiumInstance = null;
395260
}
396261

397-
if (this.wss) {
398-
// Close all websocket clients, closing the WebSocketServer
399-
// does not terminate the existing connection and it wouldn't
400-
// resolve until all of the existing connections are closed.
401-
for (const wssClient of this.wss?.clients || []) {
402-
if (wssClient.readyState === WebSocket.OPEN) {
403-
wssClient.terminate();
404-
}
405-
}
406-
await new Promise((resolve) =>
407-
this.wss ? this.wss.close(resolve) : resolve(),
408-
);
409-
this.wss = null;
410-
}
411-
412262
// Call all the registered cleanup callbacks.
413263
for (const fn of this.cleanupCallbacks) {
414264
try {

tests/functional/test.cli.run-target-chromium.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ describe('web-ext run -t chromium', () => {
237237
});
238238

239239
it(`run real Chrome ${REAL_CHROME_PATH || ''}`, async function () {
240+
// TODO: Restore auto-reload functionality.
241+
this.skip();
240242
if (!process.env.TEST_WEBEXT_USE_REAL_CHROME) {
241243
this.skip();
242244
}

0 commit comments

Comments
 (0)