extension 3.14.2 → 3.14.3
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/dist/631.cjs +278 -150
- package/dist/browsers.cjs +34 -9
- package/dist/cli.cjs +34 -9
- package/dist/extension/browsers/browsers-lib/content-script-targets.d.ts +3 -0
- package/dist/extension/browsers/browsers-types.d.ts +1 -1
- package/dist/extension/browsers/run-chromium/chromium-source-inspection/cdp-client.d.ts +4 -0
- package/dist/extension/browsers/run-chromium/chromium-source-inspection/cdp-extension-controller/index.d.ts +27 -0
- package/package.json +4 -4
package/dist/631.cjs
CHANGED
|
@@ -14,153 +14,6 @@ exports.modules = {
|
|
|
14
14
|
var external_fs_ = __webpack_require__("fs");
|
|
15
15
|
var content_script_targets = __webpack_require__("./browsers/browsers-lib/content-script-targets.ts");
|
|
16
16
|
var content_script_contracts = __webpack_require__("./browsers/browsers-lib/content-script-contracts.ts");
|
|
17
|
-
async function deriveExtensionIdFromTargetsHelper(cdp, outPath, maxRetries = 6, backoffMs = 150, profilePath, extensionPaths) {
|
|
18
|
-
let expectedName;
|
|
19
|
-
let expectedVersion;
|
|
20
|
-
let expectedManifestVersion;
|
|
21
|
-
let expectedNameIsMsg = false;
|
|
22
|
-
try {
|
|
23
|
-
const manifest = JSON.parse(external_fs_.readFileSync(external_path_.join(outPath, 'manifest.json'), 'utf-8'));
|
|
24
|
-
expectedName = manifest?.name;
|
|
25
|
-
expectedVersion = manifest?.version;
|
|
26
|
-
expectedManifestVersion = manifest?.manifest_version;
|
|
27
|
-
expectedNameIsMsg = 'string' == typeof expectedName && /__MSG_/i.test(expectedName);
|
|
28
|
-
if (expectedNameIsMsg) {
|
|
29
|
-
const defaultLocale = String(manifest?.default_locale || '').trim();
|
|
30
|
-
const msgKeyMatch = String(expectedName || '').match(/__MSG_(.+)__/i);
|
|
31
|
-
const msgKey = msgKeyMatch ? msgKeyMatch[1] : '';
|
|
32
|
-
if (defaultLocale && msgKey) {
|
|
33
|
-
const messagesPath = external_path_.join(outPath, '_locales', defaultLocale, 'messages.json');
|
|
34
|
-
if (external_fs_.existsSync(messagesPath)) {
|
|
35
|
-
const messagesJson = JSON.parse(external_fs_.readFileSync(messagesPath, 'utf-8'));
|
|
36
|
-
const resolved = String(messagesJson?.[msgKey]?.message || '').trim();
|
|
37
|
-
if (resolved) {
|
|
38
|
-
expectedName = resolved;
|
|
39
|
-
expectedNameIsMsg = false;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
} catch {}
|
|
45
|
-
const trimTrailingSep = (p)=>{
|
|
46
|
-
let end = p.length;
|
|
47
|
-
while(end > 0 && ('/' === p[end - 1] || '\\' === p[end - 1]))end--;
|
|
48
|
-
return p.slice(0, end);
|
|
49
|
-
};
|
|
50
|
-
const normalizePath = (p)=>{
|
|
51
|
-
try {
|
|
52
|
-
const resolved = external_path_.resolve(p);
|
|
53
|
-
if (external_fs_.existsSync(resolved)) return trimTrailingSep(external_fs_.realpathSync(resolved));
|
|
54
|
-
return trimTrailingSep(resolved);
|
|
55
|
-
} catch {
|
|
56
|
-
return trimTrailingSep(external_path_.resolve(p));
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
const resolvedOutPath = normalizePath(outPath);
|
|
60
|
-
const normalizedCandidates = Array.isArray(extensionPaths) ? extensionPaths.map((p)=>p ? normalizePath(p) : '').filter(Boolean) : [];
|
|
61
|
-
const resolvedCandidates = normalizedCandidates.length ? normalizedCandidates : [
|
|
62
|
-
resolvedOutPath
|
|
63
|
-
];
|
|
64
|
-
const platformIsCaseInsensitive = 'win32' === process.platform || 'darwin' === process.platform;
|
|
65
|
-
const normalizeForCompare = (p)=>platformIsCaseInsensitive ? p.toLowerCase() : p;
|
|
66
|
-
const matchesAnyCandidate = (p)=>{
|
|
67
|
-
const n = normalizeForCompare(p);
|
|
68
|
-
return resolvedCandidates.some((candidate)=>n === normalizeForCompare(candidate));
|
|
69
|
-
};
|
|
70
|
-
const deriveFromProfile = ()=>{
|
|
71
|
-
if (!profilePath) return null;
|
|
72
|
-
const candidates = [];
|
|
73
|
-
const pushPrefIfExists = (dir)=>{
|
|
74
|
-
const prefPath = external_path_.join(dir, 'Preferences');
|
|
75
|
-
if (external_fs_.existsSync(prefPath)) candidates.push(prefPath);
|
|
76
|
-
};
|
|
77
|
-
try {
|
|
78
|
-
pushPrefIfExists(profilePath);
|
|
79
|
-
pushPrefIfExists(external_path_.join(profilePath, 'Default'));
|
|
80
|
-
const entries = external_fs_.readdirSync(profilePath);
|
|
81
|
-
for (const entry of entries)if (/^Profile\s+\d+$/i.test(entry)) pushPrefIfExists(external_path_.join(profilePath, entry));
|
|
82
|
-
} catch {}
|
|
83
|
-
for (const prefPath of candidates)try {
|
|
84
|
-
if (!external_fs_.existsSync(prefPath)) continue;
|
|
85
|
-
const prefs = JSON.parse(external_fs_.readFileSync(prefPath, 'utf-8'));
|
|
86
|
-
const settings = prefs?.extensions?.settings;
|
|
87
|
-
if (!settings || 'object' != typeof settings) continue;
|
|
88
|
-
const entries = Object.entries(settings);
|
|
89
|
-
let fallbackId = null;
|
|
90
|
-
for (const [id, info] of entries){
|
|
91
|
-
const storedPath = String(info?.path || '');
|
|
92
|
-
if (!storedPath) continue;
|
|
93
|
-
const normalized = normalizePath(storedPath);
|
|
94
|
-
if (!matchesAnyCandidate(normalized)) continue;
|
|
95
|
-
const manifestName = String(info?.manifest?.name || '');
|
|
96
|
-
const manifestVersion = String(info?.manifest?.version || '');
|
|
97
|
-
if (expectedName && manifestName === expectedName) return id;
|
|
98
|
-
if (expectedVersion && manifestVersion === expectedVersion) return id;
|
|
99
|
-
fallbackId = id;
|
|
100
|
-
}
|
|
101
|
-
if (fallbackId) return fallbackId;
|
|
102
|
-
} catch {}
|
|
103
|
-
return null;
|
|
104
|
-
};
|
|
105
|
-
let retries = 0;
|
|
106
|
-
let deferredFirstEvalId = null;
|
|
107
|
-
let deferredUrlDerivedId = null;
|
|
108
|
-
const hasExpectedManifestIdentity = Boolean(expectedName || expectedVersion || expectedManifestVersion);
|
|
109
|
-
while(retries <= maxRetries){
|
|
110
|
-
try {
|
|
111
|
-
const targets = await cdp.getTargets();
|
|
112
|
-
const profileCandidateId = deriveFromProfile();
|
|
113
|
-
let firstEvalId = null;
|
|
114
|
-
let evalIdCount = 0;
|
|
115
|
-
let urlDerivedId = null;
|
|
116
|
-
for (const t of targets || []){
|
|
117
|
-
const url = String(t?.url || '');
|
|
118
|
-
const type = String(t?.type || '');
|
|
119
|
-
const typeOk = [
|
|
120
|
-
'service_worker',
|
|
121
|
-
'background_page',
|
|
122
|
-
'worker'
|
|
123
|
-
].includes(type);
|
|
124
|
-
if (!typeOk) continue;
|
|
125
|
-
const urlMatch = url.match(/^chrome-extension:\/\/([^\/]+)/);
|
|
126
|
-
if (!urlDerivedId && urlMatch?.[1]) urlDerivedId = String(urlMatch[1]);
|
|
127
|
-
if (url && !url.startsWith('chrome-extension://')) continue;
|
|
128
|
-
const targetId = t?.targetId;
|
|
129
|
-
if (targetId) try {
|
|
130
|
-
const sessionId = await cdp.attachToTarget(targetId);
|
|
131
|
-
if (!sessionId) continue;
|
|
132
|
-
await cdp.sendCommand('Runtime.enable', {}, sessionId);
|
|
133
|
-
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}})()');
|
|
134
|
-
const id = String(info?.id || '').trim();
|
|
135
|
-
if (!id) continue;
|
|
136
|
-
evalIdCount += 1;
|
|
137
|
-
if (!firstEvalId) firstEvalId = id;
|
|
138
|
-
if (profileCandidateId && id === profileCandidateId) return id;
|
|
139
|
-
const gotName = String(info?.name || '');
|
|
140
|
-
const gotVersion = String(info?.version || '');
|
|
141
|
-
const gotManifestVersion = Number(info?.manifestVersion || 0);
|
|
142
|
-
const nameMatches = expectedName && !expectedNameIsMsg ? gotName === expectedName : false;
|
|
143
|
-
const versionMatches = expectedVersion ? gotVersion === expectedVersion : false;
|
|
144
|
-
const manifestVersionMatches = expectedManifestVersion ? gotManifestVersion === expectedManifestVersion : false;
|
|
145
|
-
if (nameMatches && (!profileCandidateId || id === profileCandidateId)) return id;
|
|
146
|
-
if (expectedVersion && versionMatches && (expectedManifestVersion ? manifestVersionMatches : true) && (!profileCandidateId || id === profileCandidateId)) return id;
|
|
147
|
-
} catch {}
|
|
148
|
-
}
|
|
149
|
-
if (1 === evalIdCount && firstEvalId) {
|
|
150
|
-
if (!hasExpectedManifestIdentity) return firstEvalId;
|
|
151
|
-
deferredFirstEvalId = deferredFirstEvalId || firstEvalId;
|
|
152
|
-
}
|
|
153
|
-
if (profileCandidateId) return profileCandidateId;
|
|
154
|
-
if (urlDerivedId) {
|
|
155
|
-
if (!hasExpectedManifestIdentity) return urlDerivedId;
|
|
156
|
-
deferredUrlDerivedId = deferredUrlDerivedId || urlDerivedId;
|
|
157
|
-
}
|
|
158
|
-
} catch {}
|
|
159
|
-
await new Promise((r)=>setTimeout(r, backoffMs));
|
|
160
|
-
retries++;
|
|
161
|
-
}
|
|
162
|
-
return deriveFromProfile() || deferredFirstEvalId || deferredUrlDerivedId;
|
|
163
|
-
}
|
|
164
17
|
var external_ws_ = __webpack_require__("ws");
|
|
165
18
|
var external_ws_default = /*#__PURE__*/ __webpack_require__.n(external_ws_);
|
|
166
19
|
var constants = __webpack_require__("./browsers/browsers-lib/constants.ts");
|
|
@@ -648,6 +501,17 @@ exports.modules = {
|
|
|
648
501
|
else obj[key] = value;
|
|
649
502
|
return obj;
|
|
650
503
|
}
|
|
504
|
+
const EXTENSION_AUTO_ATTACH_FILTER = [
|
|
505
|
+
{
|
|
506
|
+
type: 'page',
|
|
507
|
+
exclude: true
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
type: 'iframe',
|
|
511
|
+
exclude: true
|
|
512
|
+
},
|
|
513
|
+
{}
|
|
514
|
+
];
|
|
651
515
|
class CDPClient {
|
|
652
516
|
isDev() {
|
|
653
517
|
return 'true' === process.env.EXTENSION_AUTHOR_MODE;
|
|
@@ -1001,6 +865,153 @@ exports.modules = {
|
|
|
1001
865
|
this.host = host;
|
|
1002
866
|
}
|
|
1003
867
|
}
|
|
868
|
+
async function deriveExtensionIdFromTargetsHelper(cdp, outPath, maxRetries = 6, backoffMs = 150, profilePath, extensionPaths) {
|
|
869
|
+
let expectedName;
|
|
870
|
+
let expectedVersion;
|
|
871
|
+
let expectedManifestVersion;
|
|
872
|
+
let expectedNameIsMsg = false;
|
|
873
|
+
try {
|
|
874
|
+
const manifest = JSON.parse(external_fs_.readFileSync(external_path_.join(outPath, 'manifest.json'), 'utf-8'));
|
|
875
|
+
expectedName = manifest?.name;
|
|
876
|
+
expectedVersion = manifest?.version;
|
|
877
|
+
expectedManifestVersion = manifest?.manifest_version;
|
|
878
|
+
expectedNameIsMsg = 'string' == typeof expectedName && /__MSG_/i.test(expectedName);
|
|
879
|
+
if (expectedNameIsMsg) {
|
|
880
|
+
const defaultLocale = String(manifest?.default_locale || '').trim();
|
|
881
|
+
const msgKeyMatch = String(expectedName || '').match(/__MSG_(.+)__/i);
|
|
882
|
+
const msgKey = msgKeyMatch ? msgKeyMatch[1] : '';
|
|
883
|
+
if (defaultLocale && msgKey) {
|
|
884
|
+
const messagesPath = external_path_.join(outPath, '_locales', defaultLocale, 'messages.json');
|
|
885
|
+
if (external_fs_.existsSync(messagesPath)) {
|
|
886
|
+
const messagesJson = JSON.parse(external_fs_.readFileSync(messagesPath, 'utf-8'));
|
|
887
|
+
const resolved = String(messagesJson?.[msgKey]?.message || '').trim();
|
|
888
|
+
if (resolved) {
|
|
889
|
+
expectedName = resolved;
|
|
890
|
+
expectedNameIsMsg = false;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
} catch {}
|
|
896
|
+
const trimTrailingSep = (p)=>{
|
|
897
|
+
let end = p.length;
|
|
898
|
+
while(end > 0 && ('/' === p[end - 1] || '\\' === p[end - 1]))end--;
|
|
899
|
+
return p.slice(0, end);
|
|
900
|
+
};
|
|
901
|
+
const normalizePath = (p)=>{
|
|
902
|
+
try {
|
|
903
|
+
const resolved = external_path_.resolve(p);
|
|
904
|
+
if (external_fs_.existsSync(resolved)) return trimTrailingSep(external_fs_.realpathSync(resolved));
|
|
905
|
+
return trimTrailingSep(resolved);
|
|
906
|
+
} catch {
|
|
907
|
+
return trimTrailingSep(external_path_.resolve(p));
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
const resolvedOutPath = normalizePath(outPath);
|
|
911
|
+
const normalizedCandidates = Array.isArray(extensionPaths) ? extensionPaths.map((p)=>p ? normalizePath(p) : '').filter(Boolean) : [];
|
|
912
|
+
const resolvedCandidates = normalizedCandidates.length ? normalizedCandidates : [
|
|
913
|
+
resolvedOutPath
|
|
914
|
+
];
|
|
915
|
+
const platformIsCaseInsensitive = 'win32' === process.platform || 'darwin' === process.platform;
|
|
916
|
+
const normalizeForCompare = (p)=>platformIsCaseInsensitive ? p.toLowerCase() : p;
|
|
917
|
+
const matchesAnyCandidate = (p)=>{
|
|
918
|
+
const n = normalizeForCompare(p);
|
|
919
|
+
return resolvedCandidates.some((candidate)=>n === normalizeForCompare(candidate));
|
|
920
|
+
};
|
|
921
|
+
const deriveFromProfile = ()=>{
|
|
922
|
+
if (!profilePath) return null;
|
|
923
|
+
const candidates = [];
|
|
924
|
+
const pushPrefIfExists = (dir)=>{
|
|
925
|
+
const prefPath = external_path_.join(dir, 'Preferences');
|
|
926
|
+
if (external_fs_.existsSync(prefPath)) candidates.push(prefPath);
|
|
927
|
+
};
|
|
928
|
+
try {
|
|
929
|
+
pushPrefIfExists(profilePath);
|
|
930
|
+
pushPrefIfExists(external_path_.join(profilePath, 'Default'));
|
|
931
|
+
const entries = external_fs_.readdirSync(profilePath);
|
|
932
|
+
for (const entry of entries)if (/^Profile\s+\d+$/i.test(entry)) pushPrefIfExists(external_path_.join(profilePath, entry));
|
|
933
|
+
} catch {}
|
|
934
|
+
for (const prefPath of candidates)try {
|
|
935
|
+
if (!external_fs_.existsSync(prefPath)) continue;
|
|
936
|
+
const prefs = JSON.parse(external_fs_.readFileSync(prefPath, 'utf-8'));
|
|
937
|
+
const settings = prefs?.extensions?.settings;
|
|
938
|
+
if (!settings || 'object' != typeof settings) continue;
|
|
939
|
+
const entries = Object.entries(settings);
|
|
940
|
+
let fallbackId = null;
|
|
941
|
+
for (const [id, info] of entries){
|
|
942
|
+
const storedPath = String(info?.path || '');
|
|
943
|
+
if (!storedPath) continue;
|
|
944
|
+
const normalized = normalizePath(storedPath);
|
|
945
|
+
if (!matchesAnyCandidate(normalized)) continue;
|
|
946
|
+
const manifestName = String(info?.manifest?.name || '');
|
|
947
|
+
const manifestVersion = String(info?.manifest?.version || '');
|
|
948
|
+
if (expectedName && manifestName === expectedName) return id;
|
|
949
|
+
if (expectedVersion && manifestVersion === expectedVersion) return id;
|
|
950
|
+
fallbackId = id;
|
|
951
|
+
}
|
|
952
|
+
if (fallbackId) return fallbackId;
|
|
953
|
+
} catch {}
|
|
954
|
+
return null;
|
|
955
|
+
};
|
|
956
|
+
let retries = 0;
|
|
957
|
+
let deferredFirstEvalId = null;
|
|
958
|
+
let deferredUrlDerivedId = null;
|
|
959
|
+
const hasExpectedManifestIdentity = Boolean(expectedName || expectedVersion || expectedManifestVersion);
|
|
960
|
+
while(retries <= maxRetries){
|
|
961
|
+
try {
|
|
962
|
+
const targets = await cdp.getTargets();
|
|
963
|
+
const profileCandidateId = deriveFromProfile();
|
|
964
|
+
let firstEvalId = null;
|
|
965
|
+
let evalIdCount = 0;
|
|
966
|
+
let urlDerivedId = null;
|
|
967
|
+
for (const t of targets || []){
|
|
968
|
+
const url = String(t?.url || '');
|
|
969
|
+
const type = String(t?.type || '');
|
|
970
|
+
const typeOk = [
|
|
971
|
+
'service_worker',
|
|
972
|
+
'background_page',
|
|
973
|
+
'worker'
|
|
974
|
+
].includes(type);
|
|
975
|
+
if (!typeOk) continue;
|
|
976
|
+
const urlMatch = url.match(/^chrome-extension:\/\/([^\/]+)/);
|
|
977
|
+
if (!urlDerivedId && urlMatch?.[1]) urlDerivedId = String(urlMatch[1]);
|
|
978
|
+
if (url && !url.startsWith('chrome-extension://')) continue;
|
|
979
|
+
const targetId = t?.targetId;
|
|
980
|
+
if (targetId) try {
|
|
981
|
+
const sessionId = await cdp.attachToTarget(targetId);
|
|
982
|
+
if (!sessionId) continue;
|
|
983
|
+
await cdp.sendCommand('Runtime.enable', {}, sessionId);
|
|
984
|
+
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}})()');
|
|
985
|
+
const id = String(info?.id || '').trim();
|
|
986
|
+
if (!id) continue;
|
|
987
|
+
evalIdCount += 1;
|
|
988
|
+
if (!firstEvalId) firstEvalId = id;
|
|
989
|
+
if (profileCandidateId && id === profileCandidateId) return id;
|
|
990
|
+
const gotName = String(info?.name || '');
|
|
991
|
+
const gotVersion = String(info?.version || '');
|
|
992
|
+
const gotManifestVersion = Number(info?.manifestVersion || 0);
|
|
993
|
+
const nameMatches = expectedName && !expectedNameIsMsg ? gotName === expectedName : false;
|
|
994
|
+
const versionMatches = expectedVersion ? gotVersion === expectedVersion : false;
|
|
995
|
+
const manifestVersionMatches = expectedManifestVersion ? gotManifestVersion === expectedManifestVersion : false;
|
|
996
|
+
if (nameMatches && (!profileCandidateId || id === profileCandidateId)) return id;
|
|
997
|
+
if (expectedVersion && versionMatches && (expectedManifestVersion ? manifestVersionMatches : true) && (!profileCandidateId || id === profileCandidateId)) return id;
|
|
998
|
+
} catch {}
|
|
999
|
+
}
|
|
1000
|
+
if (1 === evalIdCount && firstEvalId) {
|
|
1001
|
+
if (!hasExpectedManifestIdentity) return firstEvalId;
|
|
1002
|
+
deferredFirstEvalId = deferredFirstEvalId || firstEvalId;
|
|
1003
|
+
}
|
|
1004
|
+
if (profileCandidateId) return profileCandidateId;
|
|
1005
|
+
if (urlDerivedId) {
|
|
1006
|
+
if (!hasExpectedManifestIdentity) return urlDerivedId;
|
|
1007
|
+
deferredUrlDerivedId = deferredUrlDerivedId || urlDerivedId;
|
|
1008
|
+
}
|
|
1009
|
+
} catch {}
|
|
1010
|
+
await new Promise((r)=>setTimeout(r, backoffMs));
|
|
1011
|
+
retries++;
|
|
1012
|
+
}
|
|
1013
|
+
return deriveFromProfile() || deferredFirstEvalId || deferredUrlDerivedId;
|
|
1014
|
+
}
|
|
1004
1015
|
function isRecoverableBootstrapError(error) {
|
|
1005
1016
|
const msg = String(error?.message || error || '').toLowerCase();
|
|
1006
1017
|
return msg.includes('econnreset') || msg.includes('websocket is not open') || msg.includes('cdp transport is not open') || msg.includes('cdp connection closed') || msg.includes('cdp pipe closed') || msg.includes('socket hang up') || msg.includes('timed out') || msg.includes('no cdp websocket url');
|
|
@@ -1015,7 +1026,8 @@ exports.modules = {
|
|
|
1015
1026
|
await cdp.sendCommand('Target.setAutoAttach', {
|
|
1016
1027
|
autoAttach: true,
|
|
1017
1028
|
waitForDebuggerOnStart: false,
|
|
1018
|
-
flatten: true
|
|
1029
|
+
flatten: true,
|
|
1030
|
+
filter: EXTENSION_AUTO_ATTACH_FILTER
|
|
1019
1031
|
});
|
|
1020
1032
|
return cdp;
|
|
1021
1033
|
} catch (error) {
|
|
@@ -1045,7 +1057,8 @@ exports.modules = {
|
|
|
1045
1057
|
await cdp.sendCommand('Target.setAutoAttach', {
|
|
1046
1058
|
autoAttach: true,
|
|
1047
1059
|
waitForDebuggerOnStart: false,
|
|
1048
|
-
flatten: true
|
|
1060
|
+
flatten: true,
|
|
1061
|
+
filter: EXTENSION_AUTO_ATTACH_FILTER
|
|
1049
1062
|
});
|
|
1050
1063
|
return cdp;
|
|
1051
1064
|
} catch (error) {
|
|
@@ -1265,6 +1278,117 @@ exports.modules = {
|
|
|
1265
1278
|
}
|
|
1266
1279
|
return reinjectedTabs;
|
|
1267
1280
|
}
|
|
1281
|
+
async registerContentScriptsForFutureNavigations(rules) {
|
|
1282
|
+
this.activeContentScriptRules = [
|
|
1283
|
+
...rules
|
|
1284
|
+
];
|
|
1285
|
+
if (!this.cdp) return;
|
|
1286
|
+
if (!this.contentScriptTargetListenerInstalled) {
|
|
1287
|
+
this.contentScriptTargetListenerInstalled = true;
|
|
1288
|
+
this.installContentScriptTargetListener();
|
|
1289
|
+
}
|
|
1290
|
+
try {
|
|
1291
|
+
const targets = await this.cdp.getTargets();
|
|
1292
|
+
for (const target of targets || []){
|
|
1293
|
+
if ('page' !== String(target?.type || '')) continue;
|
|
1294
|
+
const targetId = String(target?.targetId || '');
|
|
1295
|
+
const url = String(target?.url || '');
|
|
1296
|
+
if (targetId && url) {
|
|
1297
|
+
if (this.urlMatchesAnyActiveRule(url)) await this.ensureWatchedPageSession(targetId, url);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
} catch {}
|
|
1301
|
+
}
|
|
1302
|
+
installContentScriptTargetListener() {
|
|
1303
|
+
if (!this.cdp) return;
|
|
1304
|
+
this.cdp.onProtocolEvent((raw)=>{
|
|
1305
|
+
const method = String(raw.method || '');
|
|
1306
|
+
const params = raw.params;
|
|
1307
|
+
const sessionId = String(raw.sessionId || '');
|
|
1308
|
+
if ('Target.targetCreated' === method || 'Target.targetInfoChanged' === method) {
|
|
1309
|
+
const targetInfo = params?.targetInfo;
|
|
1310
|
+
if (!targetInfo || 'page' !== targetInfo.type) return;
|
|
1311
|
+
const targetId = String(targetInfo.targetId || '');
|
|
1312
|
+
const url = String(targetInfo.url || '');
|
|
1313
|
+
if (!targetId) return;
|
|
1314
|
+
if (!this.urlMatchesAnyActiveRule(url)) {
|
|
1315
|
+
for (const info of this.watchedPageSessions.values())if (info.targetId === targetId) info.url = url;
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
1318
|
+
this.ensureWatchedPageSession(targetId, url).catch(()=>{});
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
if ('Runtime.executionContextCreated' === method) {
|
|
1322
|
+
if (!sessionId) return;
|
|
1323
|
+
const session = this.watchedPageSessions.get(sessionId);
|
|
1324
|
+
if (!session) return;
|
|
1325
|
+
const context = params?.context;
|
|
1326
|
+
if (!context) return;
|
|
1327
|
+
this.evaluateContentScriptOnNewContext(sessionId, session, context).catch(()=>{});
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
if ('Target.detachedFromTarget' === method) {
|
|
1331
|
+
if (sessionId) this.watchedPageSessions.delete(sessionId);
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
urlMatchesAnyActiveRule(url) {
|
|
1336
|
+
if (!url || 0 === this.activeContentScriptRules.length) return false;
|
|
1337
|
+
return this.activeContentScriptRules.some((rule)=>(0, content_script_targets.lM)(url, [
|
|
1338
|
+
rule
|
|
1339
|
+
]));
|
|
1340
|
+
}
|
|
1341
|
+
async ensureWatchedPageSession(targetId, url) {
|
|
1342
|
+
if (!this.cdp) return;
|
|
1343
|
+
for (const info of this.watchedPageSessions.values())if (info.targetId === targetId) {
|
|
1344
|
+
info.url = url;
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
let sessionId;
|
|
1348
|
+
try {
|
|
1349
|
+
sessionId = await this.cdp.attachToTarget(targetId);
|
|
1350
|
+
} catch {
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
this.watchedPageSessions.set(sessionId, {
|
|
1354
|
+
targetId,
|
|
1355
|
+
url
|
|
1356
|
+
});
|
|
1357
|
+
try {
|
|
1358
|
+
await this.cdp.sendCommand('Runtime.enable', {}, sessionId);
|
|
1359
|
+
} catch {
|
|
1360
|
+
this.watchedPageSessions.delete(sessionId);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
async evaluateContentScriptOnNewContext(sessionId, session, context) {
|
|
1364
|
+
if (!this.cdp) return;
|
|
1365
|
+
const contextId = context.id;
|
|
1366
|
+
if ('number' != typeof contextId) return;
|
|
1367
|
+
if (!this.urlMatchesAnyActiveRule(session.url)) return;
|
|
1368
|
+
const auxData = context.auxData || {};
|
|
1369
|
+
const origin = String(context.origin || '');
|
|
1370
|
+
const extensionId = this.extensionId || await this.deriveExtensionIdFromTargets();
|
|
1371
|
+
const extensionOrigin = extensionId ? `chrome-extension://${extensionId}` : '';
|
|
1372
|
+
const matchingRules = this.activeContentScriptRules.filter((rule)=>{
|
|
1373
|
+
if (!(0, content_script_targets.lM)(session.url, [
|
|
1374
|
+
rule
|
|
1375
|
+
])) return false;
|
|
1376
|
+
if ('main' === rule.world) return 'default' === auxData.type && true === auxData.isDefault;
|
|
1377
|
+
return 'isolated' === auxData.type && origin === extensionOrigin;
|
|
1378
|
+
});
|
|
1379
|
+
if (0 === matchingRules.length) return;
|
|
1380
|
+
for (const rule of matchingRules){
|
|
1381
|
+
const bundlePath = (0, content_script_targets.nG)(this.outPath, rule.index, 'js');
|
|
1382
|
+
if (!bundlePath || !external_fs_.existsSync(bundlePath)) continue;
|
|
1383
|
+
const source = this.patchReinjectSourceForInvalidatedRuntime(external_fs_.readFileSync(bundlePath, 'utf-8'));
|
|
1384
|
+
if (!source.trim()) continue;
|
|
1385
|
+
const bundleId = (0, content_script_contracts.Y)(rule.index);
|
|
1386
|
+
const expression = this.buildReinjectExpression(bundleId, source, true);
|
|
1387
|
+
try {
|
|
1388
|
+
await this.cdp.evaluateInContext(sessionId, expression, contextId);
|
|
1389
|
+
} catch {}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1268
1392
|
async reinjectMatchingTabsViaExtensionRuntime(rules) {
|
|
1269
1393
|
if (!this.cdp || 0 === rules.length) {
|
|
1270
1394
|
this.lastRuntimeReinjectionReport = {
|
|
@@ -1482,7 +1606,8 @@ exports.modules = {
|
|
|
1482
1606
|
await this.cdp.sendCommand('Target.setAutoAttach', {
|
|
1483
1607
|
autoAttach: true,
|
|
1484
1608
|
waitForDebuggerOnStart: false,
|
|
1485
|
-
flatten: true
|
|
1609
|
+
flatten: true,
|
|
1610
|
+
filter: EXTENSION_AUTO_ATTACH_FILTER
|
|
1486
1611
|
});
|
|
1487
1612
|
} catch (error) {
|
|
1488
1613
|
if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.warn(messages.wXK(String(error?.message || error)));
|
|
@@ -1835,6 +1960,9 @@ exports.modules = {
|
|
|
1835
1960
|
cdp_extension_controller_define_property(this, "cdp", null);
|
|
1836
1961
|
cdp_extension_controller_define_property(this, "extensionId", null);
|
|
1837
1962
|
cdp_extension_controller_define_property(this, "lastRuntimeReinjectionReport", null);
|
|
1963
|
+
cdp_extension_controller_define_property(this, "activeContentScriptRules", []);
|
|
1964
|
+
cdp_extension_controller_define_property(this, "contentScriptTargetListenerInstalled", false);
|
|
1965
|
+
cdp_extension_controller_define_property(this, "watchedPageSessions", new Map());
|
|
1838
1966
|
this.outPath = args.outPath;
|
|
1839
1967
|
this.browser = args.browser;
|
|
1840
1968
|
this.cdpPort = args.cdpPort;
|
package/dist/browsers.cjs
CHANGED
|
@@ -227,12 +227,12 @@ var __webpack_modules__ = {
|
|
|
227
227
|
var fs__rspack_import_0 = __webpack_require__("fs");
|
|
228
228
|
var path__rspack_import_1 = __webpack_require__("path");
|
|
229
229
|
var _content_script_contracts__rspack_import_2 = __webpack_require__("./browsers/browsers-lib/content-script-contracts.ts");
|
|
230
|
-
function isCanonicalContentScriptEntryName(entryName) {
|
|
231
|
-
return 'string' == typeof entryName && entryName.startsWith(_content_script_contracts__rspack_import_2.F);
|
|
232
|
-
}
|
|
233
230
|
function parseCanonicalContentScriptEntryIndex(entryName) {
|
|
234
|
-
if (
|
|
235
|
-
const
|
|
231
|
+
if ('string' != typeof entryName) return;
|
|
232
|
+
const base = entryName.replace(/\.[a-f0-9]+\.(js|css)$/i, '').replace(/\.(js|css)$/i, '');
|
|
233
|
+
if (!base.startsWith(_content_script_contracts__rspack_import_2.F)) return;
|
|
234
|
+
const suffix = base.slice(_content_script_contracts__rspack_import_2.F.length);
|
|
235
|
+
if (!/^\d+$/.test(suffix)) return;
|
|
236
236
|
const index = Number(suffix);
|
|
237
237
|
return Number.isInteger(index) && index >= 0 ? index : void 0;
|
|
238
238
|
}
|
|
@@ -260,8 +260,8 @@ var __webpack_modules__ = {
|
|
|
260
260
|
}
|
|
261
261
|
function getContentScriptRulesFromManifest(manifest) {
|
|
262
262
|
const contentScripts = Array.isArray(manifest?.content_scripts) ? manifest.content_scripts : [];
|
|
263
|
-
return contentScripts.map((contentScript,
|
|
264
|
-
index,
|
|
263
|
+
return contentScripts.map((contentScript, arrayIndex)=>({
|
|
264
|
+
index: resolveCanonicalIndexFromEntry(contentScript) ?? arrayIndex,
|
|
265
265
|
world: contentScript?.world === 'MAIN' ? 'main' : 'extension',
|
|
266
266
|
matches: normalizeStringArray(contentScript?.matches),
|
|
267
267
|
excludeMatches: normalizeStringArray(contentScript?.exclude_matches),
|
|
@@ -269,6 +269,26 @@ var __webpack_modules__ = {
|
|
|
269
269
|
excludeGlobs: normalizeStringArray(contentScript?.exclude_globs)
|
|
270
270
|
}));
|
|
271
271
|
}
|
|
272
|
+
function resolveCanonicalIndexFromEntry(entry) {
|
|
273
|
+
const js = Array.isArray(entry?.js) ? entry.js : [];
|
|
274
|
+
for (const rawPath of js){
|
|
275
|
+
if ('string' != typeof rawPath) continue;
|
|
276
|
+
const parsed = parseCanonicalAssetPath(rawPath, 'js');
|
|
277
|
+
if (void 0 !== parsed) return parsed;
|
|
278
|
+
}
|
|
279
|
+
const css = Array.isArray(entry?.css) ? entry.css : [];
|
|
280
|
+
for (const rawPath of css){
|
|
281
|
+
if ('string' != typeof rawPath) continue;
|
|
282
|
+
const parsed = parseCanonicalAssetPath(rawPath, 'css');
|
|
283
|
+
if (void 0 !== parsed) return parsed;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function parseCanonicalAssetPath(assetPath, ext) {
|
|
287
|
+
const match = new RegExp(`^content_scripts\\/content-(\\d+)(?:\\.[a-f0-9]+)?\\.${ext}$`, 'i').exec(assetPath);
|
|
288
|
+
if (!match) return;
|
|
289
|
+
const index = Number(match[1]);
|
|
290
|
+
return Number.isInteger(index) && index >= 0 ? index : void 0;
|
|
291
|
+
}
|
|
272
292
|
function selectContentScriptRules(rules, entryNames) {
|
|
273
293
|
const selectedIndices = new Set();
|
|
274
294
|
for (const entryName of entryNames){
|
|
@@ -1500,7 +1520,8 @@ var __webpack_modules__ = {
|
|
|
1500
1520
|
'--no-pings',
|
|
1501
1521
|
'--enable-features=SidePanelUpdates',
|
|
1502
1522
|
'--disable-features=DisableLoadExtensionCommandLineSwitch',
|
|
1503
|
-
'--enable-unsafe-extension-debugging'
|
|
1523
|
+
'--enable-unsafe-extension-debugging',
|
|
1524
|
+
'--silent-debugger-extension-api'
|
|
1504
1525
|
];
|
|
1505
1526
|
function isPlainObject(value) {
|
|
1506
1527
|
return !!value && 'object' == typeof value && !Array.isArray(value);
|
|
@@ -4942,7 +4963,8 @@ var __webpack_exports__ = {};
|
|
|
4942
4963
|
}
|
|
4943
4964
|
function resolveContentScriptRulesForReload(compilationLike, extensionsToLoad, entries) {
|
|
4944
4965
|
if (!entries || 0 === entries.length) return [];
|
|
4945
|
-
const
|
|
4966
|
+
const outputPath = compilationLike?.options?.output?.path;
|
|
4967
|
+
const extensionRoot = outputPath || extensionsToLoad?.[0];
|
|
4946
4968
|
const rules = (0, _browsers_lib_content_script_targets__rspack_import_1.iw)(compilationLike, extensionRoot);
|
|
4947
4969
|
return (0, _browsers_lib_content_script_targets__rspack_import_1.Il)(rules, entries);
|
|
4948
4970
|
}
|
|
@@ -5011,6 +5033,9 @@ var __webpack_exports__ = {};
|
|
|
5011
5033
|
if ('function' == typeof ctrl.reloadMatchingTabsForContentScripts) {
|
|
5012
5034
|
const rules = resolveContentScriptRulesForReload(compilationLike, opts.extensionsToLoad, instruction.changedContentScriptEntries);
|
|
5013
5035
|
await ctrl.reloadMatchingTabsForContentScripts(rules);
|
|
5036
|
+
if ('function' == typeof ctrl.registerContentScriptsForFutureNavigations) try {
|
|
5037
|
+
await ctrl.registerContentScriptsForFutureNavigations(rules);
|
|
5038
|
+
} catch {}
|
|
5014
5039
|
return;
|
|
5015
5040
|
}
|
|
5016
5041
|
}
|
package/dist/cli.cjs
CHANGED
|
@@ -228,12 +228,12 @@ var __webpack_modules__ = {
|
|
|
228
228
|
var fs__rspack_import_0 = __webpack_require__("fs");
|
|
229
229
|
var path__rspack_import_1 = __webpack_require__("path");
|
|
230
230
|
var _content_script_contracts__rspack_import_2 = __webpack_require__("./browsers/browsers-lib/content-script-contracts.ts");
|
|
231
|
-
function isCanonicalContentScriptEntryName(entryName) {
|
|
232
|
-
return 'string' == typeof entryName && entryName.startsWith(_content_script_contracts__rspack_import_2.F);
|
|
233
|
-
}
|
|
234
231
|
function parseCanonicalContentScriptEntryIndex(entryName) {
|
|
235
|
-
if (
|
|
236
|
-
const
|
|
232
|
+
if ('string' != typeof entryName) return;
|
|
233
|
+
const base = entryName.replace(/\.[a-f0-9]+\.(js|css)$/i, '').replace(/\.(js|css)$/i, '');
|
|
234
|
+
if (!base.startsWith(_content_script_contracts__rspack_import_2.F)) return;
|
|
235
|
+
const suffix = base.slice(_content_script_contracts__rspack_import_2.F.length);
|
|
236
|
+
if (!/^\d+$/.test(suffix)) return;
|
|
237
237
|
const index = Number(suffix);
|
|
238
238
|
return Number.isInteger(index) && index >= 0 ? index : void 0;
|
|
239
239
|
}
|
|
@@ -261,8 +261,8 @@ var __webpack_modules__ = {
|
|
|
261
261
|
}
|
|
262
262
|
function getContentScriptRulesFromManifest(manifest) {
|
|
263
263
|
const contentScripts = Array.isArray(manifest?.content_scripts) ? manifest.content_scripts : [];
|
|
264
|
-
return contentScripts.map((contentScript,
|
|
265
|
-
index,
|
|
264
|
+
return contentScripts.map((contentScript, arrayIndex)=>({
|
|
265
|
+
index: resolveCanonicalIndexFromEntry(contentScript) ?? arrayIndex,
|
|
266
266
|
world: contentScript?.world === 'MAIN' ? 'main' : 'extension',
|
|
267
267
|
matches: normalizeStringArray(contentScript?.matches),
|
|
268
268
|
excludeMatches: normalizeStringArray(contentScript?.exclude_matches),
|
|
@@ -270,6 +270,26 @@ var __webpack_modules__ = {
|
|
|
270
270
|
excludeGlobs: normalizeStringArray(contentScript?.exclude_globs)
|
|
271
271
|
}));
|
|
272
272
|
}
|
|
273
|
+
function resolveCanonicalIndexFromEntry(entry) {
|
|
274
|
+
const js = Array.isArray(entry?.js) ? entry.js : [];
|
|
275
|
+
for (const rawPath of js){
|
|
276
|
+
if ('string' != typeof rawPath) continue;
|
|
277
|
+
const parsed = parseCanonicalAssetPath(rawPath, 'js');
|
|
278
|
+
if (void 0 !== parsed) return parsed;
|
|
279
|
+
}
|
|
280
|
+
const css = Array.isArray(entry?.css) ? entry.css : [];
|
|
281
|
+
for (const rawPath of css){
|
|
282
|
+
if ('string' != typeof rawPath) continue;
|
|
283
|
+
const parsed = parseCanonicalAssetPath(rawPath, 'css');
|
|
284
|
+
if (void 0 !== parsed) return parsed;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function parseCanonicalAssetPath(assetPath, ext) {
|
|
288
|
+
const match = new RegExp(`^content_scripts\\/content-(\\d+)(?:\\.[a-f0-9]+)?\\.${ext}$`, 'i').exec(assetPath);
|
|
289
|
+
if (!match) return;
|
|
290
|
+
const index = Number(match[1]);
|
|
291
|
+
return Number.isInteger(index) && index >= 0 ? index : void 0;
|
|
292
|
+
}
|
|
273
293
|
function selectContentScriptRules(rules, entryNames) {
|
|
274
294
|
const selectedIndices = new Set();
|
|
275
295
|
for (const entryName of entryNames){
|
|
@@ -1336,7 +1356,8 @@ var __webpack_modules__ = {
|
|
|
1336
1356
|
}
|
|
1337
1357
|
function resolveContentScriptRulesForReload(compilationLike, extensionsToLoad, entries) {
|
|
1338
1358
|
if (!entries || 0 === entries.length) return [];
|
|
1339
|
-
const
|
|
1359
|
+
const outputPath = compilationLike?.options?.output?.path;
|
|
1360
|
+
const extensionRoot = outputPath || extensionsToLoad?.[0];
|
|
1340
1361
|
const rules = (0, _browsers_lib_content_script_targets__rspack_import_1.iw)(compilationLike, extensionRoot);
|
|
1341
1362
|
return (0, _browsers_lib_content_script_targets__rspack_import_1.Il)(rules, entries);
|
|
1342
1363
|
}
|
|
@@ -1405,6 +1426,9 @@ var __webpack_modules__ = {
|
|
|
1405
1426
|
if ('function' == typeof ctrl.reloadMatchingTabsForContentScripts) {
|
|
1406
1427
|
const rules = resolveContentScriptRulesForReload(compilationLike, opts.extensionsToLoad, instruction.changedContentScriptEntries);
|
|
1407
1428
|
await ctrl.reloadMatchingTabsForContentScripts(rules);
|
|
1429
|
+
if ('function' == typeof ctrl.registerContentScriptsForFutureNavigations) try {
|
|
1430
|
+
await ctrl.registerContentScriptsForFutureNavigations(rules);
|
|
1431
|
+
} catch {}
|
|
1408
1432
|
return;
|
|
1409
1433
|
}
|
|
1410
1434
|
}
|
|
@@ -1702,7 +1726,8 @@ var __webpack_modules__ = {
|
|
|
1702
1726
|
'--no-pings',
|
|
1703
1727
|
'--enable-features=SidePanelUpdates',
|
|
1704
1728
|
'--disable-features=DisableLoadExtensionCommandLineSwitch',
|
|
1705
|
-
'--enable-unsafe-extension-debugging'
|
|
1729
|
+
'--enable-unsafe-extension-debugging',
|
|
1730
|
+
'--silent-debugger-extension-api'
|
|
1706
1731
|
];
|
|
1707
1732
|
function isPlainObject(value) {
|
|
1708
1733
|
return !!value && 'object' == typeof value && !Array.isArray(value);
|
|
@@ -14,8 +14,11 @@ type ManifestLike = {
|
|
|
14
14
|
exclude_matches?: string[];
|
|
15
15
|
include_globs?: string[];
|
|
16
16
|
exclude_globs?: string[];
|
|
17
|
+
js?: string[];
|
|
18
|
+
css?: string[];
|
|
17
19
|
}>;
|
|
18
20
|
};
|
|
21
|
+
export declare function parseCanonicalContentScriptEntryIndex(entryName: string): number | undefined;
|
|
19
22
|
export declare function isContentScriptEntryName(entryName: string): boolean;
|
|
20
23
|
export declare function isCanonicalContentScriptAsset(assetName: string): boolean;
|
|
21
24
|
/**
|
|
@@ -46,7 +46,7 @@ export interface BrowserConfig {
|
|
|
46
46
|
*
|
|
47
47
|
* Each flag disables or modifies a specific browser feature for a more controlled development environment.
|
|
48
48
|
*/
|
|
49
|
-
export type DefaultBrowserFlags = '--no-first-run' | '--disable-client-side-phishing-detection' | '--disable-component-extensions-with-background-pages' | '--disable-default-apps' | '--disable-features=InterestFeedContentSuggestions' | '--disable-features=Translate' | '--hide-scrollbars' | '--mute-audio' | '--no-default-browser-check' | '--ash-no-nudges' | '--disable-search-engine-choice-screen' | '--disable-features=MediaRoute' | '--use-mock-keychain' | '--disable-background-networking' | '--disable-breakpad' | '--disable-component-update' | '--disable-domain-reliability' | '--disable-features=AutofillServerCommunicatio' | '--disable-features=CertificateTransparencyComponentUpdate' | '--disable-sync' | '--disable-features=OptimizationHints' | '--disable-features=DialMediaRouteProvider' | '--no-pings' | '--enable-features=SidePanelUpdates' | '--enable-unsafe-extension-debugging';
|
|
49
|
+
export type DefaultBrowserFlags = '--no-first-run' | '--disable-client-side-phishing-detection' | '--disable-component-extensions-with-background-pages' | '--disable-default-apps' | '--disable-features=InterestFeedContentSuggestions' | '--disable-features=Translate' | '--hide-scrollbars' | '--mute-audio' | '--no-default-browser-check' | '--ash-no-nudges' | '--disable-search-engine-choice-screen' | '--disable-features=MediaRoute' | '--use-mock-keychain' | '--disable-background-networking' | '--disable-breakpad' | '--disable-component-update' | '--disable-domain-reliability' | '--disable-features=AutofillServerCommunicatio' | '--disable-features=CertificateTransparencyComponentUpdate' | '--disable-sync' | '--disable-features=OptimizationHints' | '--disable-features=DialMediaRouteProvider' | '--no-pings' | '--enable-features=SidePanelUpdates' | '--enable-unsafe-extension-debugging' | '--silent-debugger-extension-api';
|
|
50
50
|
/**
|
|
51
51
|
* Options for the browser plugin.
|
|
52
52
|
*/
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { Readable, Writable } from 'stream';
|
|
2
2
|
import { type ExtensionRootMetaPayload } from './page';
|
|
3
|
+
export declare const EXTENSION_AUTO_ATTACH_FILTER: Array<{
|
|
4
|
+
type?: string;
|
|
5
|
+
exclude?: boolean;
|
|
6
|
+
}>;
|
|
3
7
|
export declare class CDPClient {
|
|
4
8
|
private port;
|
|
5
9
|
private host;
|
|
@@ -17,6 +17,9 @@ export declare class CDPExtensionController {
|
|
|
17
17
|
private cdp;
|
|
18
18
|
private extensionId;
|
|
19
19
|
private lastRuntimeReinjectionReport;
|
|
20
|
+
private activeContentScriptRules;
|
|
21
|
+
private contentScriptTargetListenerInstalled;
|
|
22
|
+
private watchedPageSessions;
|
|
20
23
|
constructor(args: {
|
|
21
24
|
outPath: string;
|
|
22
25
|
browser: 'chrome' | 'edge' | 'chromium-based';
|
|
@@ -38,6 +41,30 @@ export declare class CDPExtensionController {
|
|
|
38
41
|
allowCoarseCleanup?: boolean;
|
|
39
42
|
sourceOverridesByBundleId?: Record<string, string>;
|
|
40
43
|
}): Promise<number>;
|
|
44
|
+
/**
|
|
45
|
+
* Install a persistent CDP listener that re-injects the latest content-
|
|
46
|
+
* script bundle into any page that navigates to a URL matching a rule —
|
|
47
|
+
* including fresh tabs, full page reloads, and same-tab URL changes.
|
|
48
|
+
*
|
|
49
|
+
* Chrome binds its static `content_scripts` list to the bytes it read when
|
|
50
|
+
* the extension was loaded, and those cached bytes don't change when
|
|
51
|
+
* Rspack rewrites the hashed bundle on edit. We can't reload the extension
|
|
52
|
+
* without losing SW state and closing popup/sidebar. So for every matching
|
|
53
|
+
* navigation we wait for Chrome to create the extension's isolated world
|
|
54
|
+
* (which happens at `document_start` just before the cached content script
|
|
55
|
+
* runs) and evaluate the fresh bundle source in that exact world. The
|
|
56
|
+
* wrapper's `__EXTENSIONJS_DEV_REINJECT__` registry keyed on the canonical
|
|
57
|
+
* bundle id unmounts the stale generation before mounting the new one, so
|
|
58
|
+
* what the user sees is the latest build.
|
|
59
|
+
*
|
|
60
|
+
* Called on every `content-scripts` reload instruction with the latest
|
|
61
|
+
* rules. Safe to call repeatedly — rules are simply replaced.
|
|
62
|
+
*/
|
|
63
|
+
registerContentScriptsForFutureNavigations(rules: ContentScriptTargetRule[]): Promise<void>;
|
|
64
|
+
private installContentScriptTargetListener;
|
|
65
|
+
private urlMatchesAnyActiveRule;
|
|
66
|
+
private ensureWatchedPageSession;
|
|
67
|
+
private evaluateContentScriptOnNewContext;
|
|
41
68
|
reinjectMatchingTabsViaExtensionRuntime(rules: ContentScriptTargetRule[]): Promise<number>;
|
|
42
69
|
private reloadPageTarget;
|
|
43
70
|
hardReload(): Promise<boolean>;
|
package/package.json
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"extension": "./bin/extension.cjs"
|
|
39
39
|
},
|
|
40
40
|
"name": "extension",
|
|
41
|
-
"version": "3.14.
|
|
41
|
+
"version": "3.14.3",
|
|
42
42
|
"description": "Create cross-browser extensions with no build configuration.",
|
|
43
43
|
"homepage": "https://extension.js.org/",
|
|
44
44
|
"bugs": {
|
|
@@ -100,9 +100,9 @@
|
|
|
100
100
|
"cross-spawn": "^7.0.6",
|
|
101
101
|
"edge-location": "2.2.0",
|
|
102
102
|
"firefox-location2": "3.0.0",
|
|
103
|
-
"extension-create": "3.14.
|
|
104
|
-
"extension-develop": "3.14.
|
|
105
|
-
"extension-install": "3.14.
|
|
103
|
+
"extension-create": "3.14.3",
|
|
104
|
+
"extension-develop": "3.14.3",
|
|
105
|
+
"extension-install": "3.14.3",
|
|
106
106
|
"commander": "^14.0.3",
|
|
107
107
|
"pintor": "0.3.0",
|
|
108
108
|
"semver": "^7.7.3",
|