extension-develop 3.5.0 → 3.6.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.
- package/README.md +30 -15
- package/dist/215.cjs +40 -22
- package/dist/323.cjs +123 -5
- package/dist/{547.cjs → 535.cjs} +2156 -461
- package/dist/928.cjs +10 -0
- package/dist/content-script-wrapper.cjs +72 -4
- package/dist/main-world-bridge.cjs +18 -0
- package/dist/minimum-script-file.cjs +7 -5
- package/dist/module.cjs +1112 -401
- package/dist/warn-no-default-export.cjs +32 -5
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -101,20 +101,31 @@ Options accepted by each command. Values shown are typical types or enumerations
|
|
|
101
101
|
|
|
102
102
|
### dev
|
|
103
103
|
|
|
104
|
-
| Option
|
|
105
|
-
|
|
|
106
|
-
| mode
|
|
107
|
-
| polyfill
|
|
108
|
-
| port
|
|
109
|
-
| source
|
|
110
|
-
| watchSource
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
|
114
|
-
|
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
|
|
|
104
|
+
| Option | Type / Values | Description |
|
|
105
|
+
| ------------------- | ----------------------------------- | --------------------------------------------------------------------------------- |
|
|
106
|
+
| mode | development, production, none | Build mode |
|
|
107
|
+
| polyfill | boolean | Include `webextension-polyfill` when possible |
|
|
108
|
+
| port | number or string | Dev server port |
|
|
109
|
+
| source | string | Inspect a source directory |
|
|
110
|
+
| watchSource | boolean | Watch the source directory |
|
|
111
|
+
| sourceFormat | pretty,json,ndjson | Output format for source HTML |
|
|
112
|
+
| sourceSummary | boolean | Output a compact summary instead of full HTML |
|
|
113
|
+
| sourceMeta | boolean | Output page metadata (readyState, viewport, frames) |
|
|
114
|
+
| sourceProbe | string[] | CSS selectors to probe for quick validation |
|
|
115
|
+
| sourceTree | off,root-only | Output a compact extension root tree |
|
|
116
|
+
| sourceConsole | boolean | Output console summary (best-effort) |
|
|
117
|
+
| sourceDom | boolean | Output DOM snapshots and diffs |
|
|
118
|
+
| sourceMaxBytes | number | Limit HTML output size in bytes (0 disables truncation) |
|
|
119
|
+
| sourceRedact | off,safe,strict | Redact sensitive content in HTML output |
|
|
120
|
+
| sourceIncludeShadow | off,open-only,all | Control Shadow DOM inclusion |
|
|
121
|
+
| sourceDiff | boolean | Include diff metadata on watch updates |
|
|
122
|
+
| logs | off,error,warn,info,debug,trace,all | Unified logger verbosity (all shows everything) |
|
|
123
|
+
| logContext | list or `all` | Comma-separated contexts (background,content,page,sidebar,popup,options,devtools) |
|
|
124
|
+
| logFormat | pretty,json,ndjson | Pretty text or JSON/NDJSON output |
|
|
125
|
+
| logTimestamps | boolean | Include timestamps in pretty output |
|
|
126
|
+
| logColor | boolean | Colorize pretty output |
|
|
127
|
+
| logUrl | string or /regex/flags | Filter by URL substring or JS-style regex literal |
|
|
128
|
+
| logTab | number | Filter by tabId |
|
|
118
129
|
|
|
119
130
|
### build
|
|
120
131
|
|
|
@@ -161,7 +172,7 @@ Options accepted by each command. Values shown are typical types or enumerations
|
|
|
161
172
|
- Supported sections:
|
|
162
173
|
- config(config: Configuration): mutate the assembled Rspack config. Supports a function or a plain object. When an object is provided, it is deep‑merged on top of the assembled config.
|
|
163
174
|
- commands.dev | .build | .start | .preview: per‑command options (browser, profile, binaries, flags, preferences, unified logger defaults, packaging). These defaults are applied for all respective commands.
|
|
164
|
-
|
|
175
|
+
- browser.chrome | .firefox | .edge | .chromium-based | .gecko-based: start flags, excluded flags, preferences, binaries, profile reuse (persistProfile), and per-browser `extensions`.
|
|
165
176
|
- extensions: load-only companion extensions (unpacked dirs) loaded alongside your extension in dev/preview/start.
|
|
166
177
|
- Example: { dir: "./extensions" } loads every "./extensions/\*" folder that contains a manifest.json.
|
|
167
178
|
- Precedence when composing options: browser._ → commands._ → CLI flags. CLI flags always win over config defaults.
|
|
@@ -180,9 +191,13 @@ Use this when you have other unpacked extensions you want loaded alongside your
|
|
|
180
191
|
- **How they’re loaded**: they’re appended into the browser runner’s `--load-extension` list (Chromium) / addon install list (Firefox) **before** your extension. Your extension is always loaded last for precedence.
|
|
181
192
|
- **Discovery**:
|
|
182
193
|
- `extensions.dir`: scans one level deep (e.g. `./extensions/*/manifest.json`)
|
|
194
|
+
- When `dir` points to `./extensions`, browser folders like `./extensions/chrome/*` and `./extensions/firefox/*` are also scanned.
|
|
183
195
|
- `extensions.paths`: explicit directories (absolute or relative to the project root)
|
|
184
196
|
- **Overrides**: top-level `extensions` applies to all commands, but `commands.<cmd>.extensions` overrides it for that command.
|
|
185
197
|
- **Invalid entries**: ignored. In author mode (`EXTENSION_AUTHOR_MODE=true`) we print a warning if `extensions` is configured but nothing resolves.
|
|
198
|
+
- **Store URLs**: entries pointing to Chrome Web Store, Edge Addons, or AMO are downloaded on-demand into `./extensions/<browser>/<id-or-slug>`.
|
|
199
|
+
- **Local paths**: only paths under `./extensions/` are accepted for companion extensions.
|
|
200
|
+
- **CLI**: use `--extensions <csv>` to provide a comma-separated list of paths or store URLs.
|
|
186
201
|
|
|
187
202
|
Example:
|
|
188
203
|
|
package/dist/215.cjs
CHANGED
|
@@ -74,7 +74,7 @@ exports.modules = {
|
|
|
74
74
|
return mainHTML;
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
async function getPageHTML(cdp, sessionId) {
|
|
77
|
+
async function getPageHTML(cdp, sessionId, includeShadow = 'open-only') {
|
|
78
78
|
try {
|
|
79
79
|
await cdp.evaluate(sessionId, 'document.title');
|
|
80
80
|
} catch {}
|
|
@@ -97,6 +97,7 @@ exports.modules = {
|
|
|
97
97
|
}
|
|
98
98
|
})()`);
|
|
99
99
|
const mainHTML = 'string' == typeof mainHTMLRaw ? mainHTMLRaw : String(mainHTMLRaw || '');
|
|
100
|
+
if ('off' === includeShadow) return mainHTML;
|
|
100
101
|
try {
|
|
101
102
|
const mergedHtmlRaw = await cdp.evaluate(sessionId, `(() => { try {
|
|
102
103
|
var cloned = document.documentElement.cloneNode(true);
|
|
@@ -199,7 +200,7 @@ exports.modules = {
|
|
|
199
200
|
while(Date.now() < deadline){
|
|
200
201
|
try {
|
|
201
202
|
const injected = await cdp.evaluate(sessionId, `(() => { try {
|
|
202
|
-
const hosts = Array.from(document.querySelectorAll('[data-extension-root="true"]'));
|
|
203
|
+
const hosts = Array.from(document.querySelectorAll('#extension-root,[data-extension-root="true"]'));
|
|
203
204
|
if (!hosts.length) return false;
|
|
204
205
|
const markers = ['iskilar_box','content_script','content_title','js-probe'];
|
|
205
206
|
for (const h of hosts) {
|
|
@@ -244,7 +245,7 @@ exports.modules = {
|
|
|
244
245
|
try {
|
|
245
246
|
this.targetWebSocketUrl = await (0, discovery.N)(this.host, this.port, this.isDev());
|
|
246
247
|
this.ws = await establishBrowserConnection(this.targetWebSocketUrl, this.isDev(), (data)=>this.handleMessage(data), (reason)=>{
|
|
247
|
-
this.pendingRequests.forEach(({ reject }, id)=>{
|
|
248
|
+
this.pendingRequests.forEach(({ reject, timeout }, id)=>{
|
|
248
249
|
try {
|
|
249
250
|
reject(new Error(reason));
|
|
250
251
|
} catch (error) {
|
|
@@ -253,6 +254,7 @@ exports.modules = {
|
|
|
253
254
|
console.warn(messages.r0s(String(err.message || err)));
|
|
254
255
|
}
|
|
255
256
|
}
|
|
257
|
+
if (timeout) clearTimeout(timeout);
|
|
256
258
|
this.pendingRequests.delete(id);
|
|
257
259
|
});
|
|
258
260
|
});
|
|
@@ -281,6 +283,7 @@ exports.modules = {
|
|
|
281
283
|
if (message.id) {
|
|
282
284
|
const pending = this.pendingRequests.get(message.id);
|
|
283
285
|
if (pending) {
|
|
286
|
+
if (pending.timeout) clearTimeout(pending.timeout);
|
|
284
287
|
this.pendingRequests.delete(message.id);
|
|
285
288
|
if (message.error) pending.reject(new Error(JSON.stringify(message.error)));
|
|
286
289
|
else pending.resolve(message.result);
|
|
@@ -299,7 +302,7 @@ exports.modules = {
|
|
|
299
302
|
}
|
|
300
303
|
}
|
|
301
304
|
}
|
|
302
|
-
async sendCommand(method, params = {}, sessionId) {
|
|
305
|
+
async sendCommand(method, params = {}, sessionId, timeoutMs = 12000) {
|
|
303
306
|
return new Promise((resolve, reject)=>{
|
|
304
307
|
if (!this.ws || this.ws.readyState !== external_ws_default().OPEN) return reject(new Error('WebSocket is not open'));
|
|
305
308
|
const id = ++this.messageId;
|
|
@@ -310,12 +313,22 @@ exports.modules = {
|
|
|
310
313
|
};
|
|
311
314
|
if (sessionId) message.sessionId = sessionId;
|
|
312
315
|
try {
|
|
316
|
+
const timeout = setTimeout(()=>{
|
|
317
|
+
const pending = this.pendingRequests.get(id);
|
|
318
|
+
if (!pending) return;
|
|
319
|
+
this.pendingRequests.delete(id);
|
|
320
|
+
pending.reject(new Error(`CDP command timed out (${timeoutMs}ms): ${String(pending.method || method)}`));
|
|
321
|
+
}, timeoutMs);
|
|
313
322
|
this.pendingRequests.set(id, {
|
|
314
323
|
resolve,
|
|
315
|
-
reject
|
|
324
|
+
reject,
|
|
325
|
+
timeout,
|
|
326
|
+
method
|
|
316
327
|
});
|
|
317
328
|
this.ws.send(JSON.stringify(message));
|
|
318
329
|
} catch (error) {
|
|
330
|
+
const pending = this.pendingRequests.get(id);
|
|
331
|
+
if (pending?.timeout) clearTimeout(pending.timeout);
|
|
319
332
|
this.pendingRequests.delete(id);
|
|
320
333
|
reject(error);
|
|
321
334
|
}
|
|
@@ -376,8 +389,8 @@ exports.modules = {
|
|
|
376
389
|
}, sessionId);
|
|
377
390
|
return response.result?.value;
|
|
378
391
|
}
|
|
379
|
-
async getPageHTML(sessionId) {
|
|
380
|
-
return getPageHTML(this, sessionId);
|
|
392
|
+
async getPageHTML(sessionId, includeShadow = 'open-only') {
|
|
393
|
+
return getPageHTML(this, sessionId, includeShadow);
|
|
381
394
|
}
|
|
382
395
|
async closeTarget(targetId) {
|
|
383
396
|
await this.sendCommand('Target.closeTarget', {
|
|
@@ -392,13 +405,14 @@ exports.modules = {
|
|
|
392
405
|
});
|
|
393
406
|
return true;
|
|
394
407
|
} catch (error) {
|
|
395
|
-
const attempts =
|
|
408
|
+
const attempts = 8;
|
|
396
409
|
for(let i = 0; i < attempts; i++){
|
|
397
410
|
try {
|
|
398
411
|
const ok = await this.reloadExtensionViaTargetEval(extensionId);
|
|
399
412
|
if (ok) return true;
|
|
400
413
|
} catch {}
|
|
401
|
-
|
|
414
|
+
const backoffMs = Math.min(1200, 150 * (i + 1));
|
|
415
|
+
await new Promise((r)=>setTimeout(r, backoffMs));
|
|
402
416
|
}
|
|
403
417
|
console.warn(messages.ccn(extensionId, error.message || String(error)));
|
|
404
418
|
return false;
|
|
@@ -417,24 +431,28 @@ exports.modules = {
|
|
|
417
431
|
const preferredOrder = [
|
|
418
432
|
'service_worker',
|
|
419
433
|
'background_page',
|
|
420
|
-
'worker'
|
|
434
|
+
'worker',
|
|
435
|
+
'page'
|
|
421
436
|
];
|
|
422
437
|
for (const type of preferredOrder){
|
|
423
|
-
const
|
|
438
|
+
const matchingTargets = (targets || []).filter((t)=>{
|
|
424
439
|
const url = String(t?.url || '');
|
|
425
440
|
const tt = String(t?.type || '');
|
|
426
|
-
|
|
441
|
+
const inExtensionScope = url.startsWith(`chrome-extension://${extensionId}/`);
|
|
442
|
+
return tt === type && inExtensionScope;
|
|
427
443
|
});
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
444
|
+
for (const target of matchingTargets){
|
|
445
|
+
const targetId = target?.targetId;
|
|
446
|
+
if (targetId) try {
|
|
447
|
+
const sessionId = await this.attachToTarget(targetId);
|
|
448
|
+
await this.sendCommand('Runtime.enable', {}, sessionId);
|
|
449
|
+
await this.sendCommand('Runtime.evaluate', {
|
|
450
|
+
expression: '(function(){ try { if (!chrome || !chrome.runtime || !chrome.runtime.reload) return false; chrome.runtime.reload(); return true; } catch (error) { return false; } })()',
|
|
451
|
+
returnByValue: true
|
|
452
|
+
}, sessionId);
|
|
453
|
+
return true;
|
|
454
|
+
} catch {}
|
|
455
|
+
}
|
|
438
456
|
}
|
|
439
457
|
return false;
|
|
440
458
|
} catch {
|
package/dist/323.cjs
CHANGED
|
@@ -12,11 +12,98 @@ exports.modules = {
|
|
|
12
12
|
var banner = __webpack_require__("./webpack/plugin-browsers/browsers-lib/banner.ts");
|
|
13
13
|
var external_path_ = __webpack_require__("path");
|
|
14
14
|
var external_fs_ = __webpack_require__("fs");
|
|
15
|
-
async function deriveExtensionIdFromTargetsHelper(cdp, outPath, maxRetries = 6, backoffMs = 150) {
|
|
15
|
+
async function deriveExtensionIdFromTargetsHelper(cdp, outPath, maxRetries = 6, backoffMs = 150, profilePath, extensionPaths) {
|
|
16
|
+
let expectedName;
|
|
17
|
+
let expectedVersion;
|
|
18
|
+
let expectedManifestVersion;
|
|
19
|
+
let expectedNameIsMsg = false;
|
|
20
|
+
try {
|
|
21
|
+
const manifest = JSON.parse(external_fs_.readFileSync(external_path_.join(outPath, 'manifest.json'), 'utf-8'));
|
|
22
|
+
expectedName = manifest?.name;
|
|
23
|
+
expectedVersion = manifest?.version;
|
|
24
|
+
expectedManifestVersion = manifest?.manifest_version;
|
|
25
|
+
expectedNameIsMsg = 'string' == typeof expectedName && /__MSG_/i.test(expectedName);
|
|
26
|
+
if (expectedNameIsMsg) {
|
|
27
|
+
const defaultLocale = String(manifest?.default_locale || '').trim();
|
|
28
|
+
const msgKeyMatch = String(expectedName || '').match(/__MSG_(.+)__/i);
|
|
29
|
+
const msgKey = msgKeyMatch ? msgKeyMatch[1] : '';
|
|
30
|
+
if (defaultLocale && msgKey) {
|
|
31
|
+
const messagesPath = external_path_.join(outPath, '_locales', defaultLocale, 'messages.json');
|
|
32
|
+
if (external_fs_.existsSync(messagesPath)) {
|
|
33
|
+
const messagesJson = JSON.parse(external_fs_.readFileSync(messagesPath, 'utf-8'));
|
|
34
|
+
const resolved = String(messagesJson?.[msgKey]?.message || '').trim();
|
|
35
|
+
if (resolved) {
|
|
36
|
+
expectedName = resolved;
|
|
37
|
+
expectedNameIsMsg = false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
} catch {}
|
|
43
|
+
const trimTrailingSep = (p)=>p.replace(/[\\\/]+$/g, '');
|
|
44
|
+
const normalizePath = (p)=>{
|
|
45
|
+
try {
|
|
46
|
+
const resolved = external_path_.resolve(p);
|
|
47
|
+
if (external_fs_.existsSync(resolved)) return trimTrailingSep(external_fs_.realpathSync(resolved));
|
|
48
|
+
return trimTrailingSep(resolved);
|
|
49
|
+
} catch {
|
|
50
|
+
return trimTrailingSep(external_path_.resolve(p));
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const resolvedOutPath = normalizePath(outPath);
|
|
54
|
+
const normalizedCandidates = Array.isArray(extensionPaths) ? extensionPaths.map((p)=>p ? normalizePath(p) : '').filter(Boolean) : [];
|
|
55
|
+
const resolvedCandidates = normalizedCandidates.length ? normalizedCandidates : [
|
|
56
|
+
resolvedOutPath
|
|
57
|
+
];
|
|
58
|
+
const platformIsCaseInsensitive = 'win32' === process.platform || 'darwin' === process.platform;
|
|
59
|
+
const normalizeForCompare = (p)=>platformIsCaseInsensitive ? p.toLowerCase() : p;
|
|
60
|
+
const matchesAnyCandidate = (p)=>{
|
|
61
|
+
const n = normalizeForCompare(p);
|
|
62
|
+
return resolvedCandidates.some((candidate)=>n === normalizeForCompare(candidate));
|
|
63
|
+
};
|
|
64
|
+
const deriveFromProfile = ()=>{
|
|
65
|
+
if (!profilePath) return null;
|
|
66
|
+
const candidates = [];
|
|
67
|
+
const pushPrefIfExists = (dir)=>{
|
|
68
|
+
const prefPath = external_path_.join(dir, 'Preferences');
|
|
69
|
+
if (external_fs_.existsSync(prefPath)) candidates.push(prefPath);
|
|
70
|
+
};
|
|
71
|
+
try {
|
|
72
|
+
pushPrefIfExists(profilePath);
|
|
73
|
+
pushPrefIfExists(external_path_.join(profilePath, 'Default'));
|
|
74
|
+
const entries = external_fs_.readdirSync(profilePath);
|
|
75
|
+
for (const entry of entries)if (/^Profile\s+\d+$/i.test(entry)) pushPrefIfExists(external_path_.join(profilePath, entry));
|
|
76
|
+
} catch {}
|
|
77
|
+
for (const prefPath of candidates)try {
|
|
78
|
+
if (!external_fs_.existsSync(prefPath)) continue;
|
|
79
|
+
const prefs = JSON.parse(external_fs_.readFileSync(prefPath, 'utf-8'));
|
|
80
|
+
const settings = prefs?.extensions?.settings;
|
|
81
|
+
if (!settings || 'object' != typeof settings) continue;
|
|
82
|
+
const entries = Object.entries(settings);
|
|
83
|
+
let fallbackId = null;
|
|
84
|
+
for (const [id, info] of entries){
|
|
85
|
+
const storedPath = String(info?.path || '');
|
|
86
|
+
if (!storedPath) continue;
|
|
87
|
+
const normalized = normalizePath(storedPath);
|
|
88
|
+
if (!matchesAnyCandidate(normalized)) continue;
|
|
89
|
+
const manifestName = String(info?.manifest?.name || '');
|
|
90
|
+
const manifestVersion = String(info?.manifest?.version || '');
|
|
91
|
+
if (expectedName && manifestName === expectedName) return id;
|
|
92
|
+
if (expectedVersion && manifestVersion === expectedVersion) return id;
|
|
93
|
+
fallbackId = id;
|
|
94
|
+
}
|
|
95
|
+
if (fallbackId) return fallbackId;
|
|
96
|
+
} catch {}
|
|
97
|
+
return null;
|
|
98
|
+
};
|
|
16
99
|
let retries = 0;
|
|
17
100
|
while(retries <= maxRetries){
|
|
18
101
|
try {
|
|
19
102
|
const targets = await cdp.getTargets();
|
|
103
|
+
const profileCandidateId = deriveFromProfile();
|
|
104
|
+
let firstEvalId = null;
|
|
105
|
+
let evalIdCount = 0;
|
|
106
|
+
let urlDerivedId = null;
|
|
20
107
|
for (const t of targets || []){
|
|
21
108
|
const url = String(t?.url || '');
|
|
22
109
|
const type = String(t?.type || '');
|
|
@@ -26,6 +113,8 @@ exports.modules = {
|
|
|
26
113
|
'worker'
|
|
27
114
|
].includes(type);
|
|
28
115
|
if (!typeOk) continue;
|
|
116
|
+
const urlMatch = url.match(/^chrome-extension:\/\/([^\/]+)/);
|
|
117
|
+
if (!urlDerivedId && urlMatch?.[1]) urlDerivedId = String(urlMatch[1]);
|
|
29
118
|
if (url && !url.startsWith('chrome-extension://')) continue;
|
|
30
119
|
const targetId = t?.targetId;
|
|
31
120
|
if (targetId) try {
|
|
@@ -35,9 +124,22 @@ exports.modules = {
|
|
|
35
124
|
const info = await cdp.evaluate(sessionId, '(()=>{try{const m=chrome.runtime.getManifest?.();return {id:chrome.runtime?.id||"",name:m?.name||"",version:m?.version||"",manifestVersion:m?.manifest_version||0}}catch(_){return null}})()');
|
|
36
125
|
const id = String(info?.id || '').trim();
|
|
37
126
|
if (!id) continue;
|
|
38
|
-
|
|
127
|
+
evalIdCount += 1;
|
|
128
|
+
if (!firstEvalId) firstEvalId = id;
|
|
129
|
+
if (profileCandidateId && id === profileCandidateId) return id;
|
|
130
|
+
const gotName = String(info?.name || '');
|
|
131
|
+
const gotVersion = String(info?.version || '');
|
|
132
|
+
const gotManifestVersion = Number(info?.manifestVersion || 0);
|
|
133
|
+
const nameMatches = expectedName && !expectedNameIsMsg ? gotName === expectedName : false;
|
|
134
|
+
const versionMatches = expectedVersion ? gotVersion === expectedVersion : false;
|
|
135
|
+
const manifestVersionMatches = expectedManifestVersion ? gotManifestVersion === expectedManifestVersion : false;
|
|
136
|
+
if (nameMatches && (!profileCandidateId || id === profileCandidateId)) return id;
|
|
137
|
+
if (expectedVersion && versionMatches && (expectedManifestVersion ? manifestVersionMatches : true) && (!profileCandidateId || id === profileCandidateId)) return id;
|
|
39
138
|
} catch {}
|
|
40
139
|
}
|
|
140
|
+
if (1 === evalIdCount && firstEvalId) return firstEvalId;
|
|
141
|
+
if (profileCandidateId) return profileCandidateId;
|
|
142
|
+
if (urlDerivedId) return urlDerivedId;
|
|
41
143
|
} catch {}
|
|
42
144
|
await new Promise((r)=>setTimeout(r, backoffMs));
|
|
43
145
|
retries++;
|
|
@@ -214,7 +316,7 @@ exports.modules = {
|
|
|
214
316
|
}
|
|
215
317
|
async deriveExtensionIdFromTargets(maxRetries = 20, backoffMs = 200) {
|
|
216
318
|
if (!this.cdp) return null;
|
|
217
|
-
return await deriveExtensionIdFromTargetsHelper(this.cdp, this.outPath, maxRetries, backoffMs);
|
|
319
|
+
return await deriveExtensionIdFromTargetsHelper(this.cdp, this.outPath, maxRetries, backoffMs, this.profilePath, this.extensionPaths);
|
|
218
320
|
}
|
|
219
321
|
async hardReload() {
|
|
220
322
|
if (!this.cdp || !this.extensionId) return false;
|
|
@@ -322,17 +424,25 @@ exports.modules = {
|
|
|
322
424
|
_define_property(this, "outPath", void 0);
|
|
323
425
|
_define_property(this, "browser", void 0);
|
|
324
426
|
_define_property(this, "cdpPort", void 0);
|
|
427
|
+
_define_property(this, "profilePath", void 0);
|
|
428
|
+
_define_property(this, "extensionPaths", void 0);
|
|
325
429
|
_define_property(this, "cdp", null);
|
|
326
430
|
_define_property(this, "extensionId", null);
|
|
327
431
|
this.outPath = args.outPath;
|
|
328
432
|
this.browser = args.browser;
|
|
329
433
|
this.cdpPort = args.cdpPort;
|
|
434
|
+
this.profilePath = args.profilePath;
|
|
435
|
+
this.extensionPaths = args.extensionPaths;
|
|
330
436
|
}
|
|
331
437
|
}
|
|
332
438
|
var extension_output_path = __webpack_require__("./webpack/plugin-browsers/run-chromium/chromium-launch/extension-output-path.ts");
|
|
333
439
|
async function setupCdpAfterLaunch(compilation, plugin, chromiumArgs) {
|
|
334
440
|
const loadExtensionFlag = chromiumArgs.find((flag)=>flag.startsWith('--load-extension='));
|
|
335
441
|
const extensionOutputPath = (0, extension_output_path.W)(compilation, loadExtensionFlag);
|
|
442
|
+
const extensionPaths = loadExtensionFlag ? loadExtensionFlag.replace('--load-extension=', '').split(',').map((s)=>s.trim()).filter(Boolean) : [];
|
|
443
|
+
const selectedExtensionPaths = extensionOutputPath && extensionOutputPath.length > 0 ? [
|
|
444
|
+
extensionOutputPath
|
|
445
|
+
] : extensionPaths;
|
|
336
446
|
const remoteDebugPortFlag = chromiumArgs.find((flag)=>flag.startsWith('--remote-debugging-port='));
|
|
337
447
|
const chromeRemoteDebugPort = remoteDebugPortFlag ? parseInt(remoteDebugPortFlag.split('=')[1], 10) : (0, shared_utils.jl)(plugin.port, plugin.instanceId);
|
|
338
448
|
const userDataDirFlag = chromiumArgs.find((flag)=>flag.startsWith('--user-data-dir='));
|
|
@@ -344,7 +454,9 @@ exports.modules = {
|
|
|
344
454
|
const cdpExtensionController = new CDPExtensionController({
|
|
345
455
|
outPath: extensionOutputPath,
|
|
346
456
|
browser: 'chromium-based' === plugin.browser ? 'chrome' : plugin.browser,
|
|
347
|
-
cdpPort: chromeRemoteDebugPort
|
|
457
|
+
cdpPort: chromeRemoteDebugPort,
|
|
458
|
+
profilePath: userDataDir || void 0,
|
|
459
|
+
extensionPaths: selectedExtensionPaths
|
|
348
460
|
});
|
|
349
461
|
const retryAsync = async (operation, attempts = 5, initialDelayMs = 150)=>{
|
|
350
462
|
let lastError;
|
|
@@ -361,7 +473,13 @@ exports.modules = {
|
|
|
361
473
|
if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(messages.M3V('127.0.0.1', chromeRemoteDebugPort));
|
|
362
474
|
let extensionControllerInfo = null;
|
|
363
475
|
try {
|
|
364
|
-
|
|
476
|
+
const ensureLoadedTimeoutMs = 10000;
|
|
477
|
+
extensionControllerInfo = await Promise.race([
|
|
478
|
+
cdpExtensionController.ensureLoaded(),
|
|
479
|
+
new Promise((_, reject)=>{
|
|
480
|
+
setTimeout(()=>reject(new Error(`ensureLoaded timeout (${ensureLoadedTimeoutMs}ms)`)), ensureLoadedTimeoutMs);
|
|
481
|
+
})
|
|
482
|
+
]);
|
|
365
483
|
} catch (error) {
|
|
366
484
|
if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.warn(`[CDP] ensureLoaded failed: ${String(error?.message || error)}`);
|
|
367
485
|
}
|