@wenathlan/extension 1.1.47 → 1.1.49
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 +6 -4
- package/dist/emulation.d.ts +89 -0
- package/dist/emulation.d.ts.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +886 -4
- package/dist/index.js.map +4 -4
- package/dist/memory.d.ts +83 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/policy.d.ts +51 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/protocol.d.ts +65 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/sessions.d.ts +79 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/types.d.ts +250 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/extension/dist/background.js +1413 -8
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/manifest.json +1 -1
- package/extension/dist/pagebridge.js +288 -5
- package/extension/dist/pagebridge.js.map +3 -3
- package/extension/dist/popup.html +1 -1
- package/extension/dist/popup.js +24 -2
- package/extension/dist/popup.js.map +2 -2
- package/extension/dist/sidepanel.html +1 -1
- package/extension/dist/sidepanel.js +375 -2
- package/extension/dist/sidepanel.js.map +3 -3
- package/extension/dist/style.css +4 -0
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -333,6 +333,190 @@ function teardowncdpsession(input) {
|
|
|
333
333
|
};
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
+
// emulation.ts
|
|
337
|
+
var emulationkinds = ["emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission", "blackboxscripts"];
|
|
338
|
+
var browserpermissions = ["geolocation", "notifications", "camera", "microphone", "clipboard-read", "clipboard-write", "midi", "persistent-storage"];
|
|
339
|
+
var permissionstates = ["granted", "denied", "prompt"];
|
|
340
|
+
function familyofkind(kind) {
|
|
341
|
+
if (kind === "emulatedevice") return "device";
|
|
342
|
+
if (kind === "emulatenetwork") return "network";
|
|
343
|
+
if (kind === "emulatelocate") return "location";
|
|
344
|
+
if (kind === "setuseragent") return "agent";
|
|
345
|
+
if (kind === "overridepermission") return "permission";
|
|
346
|
+
if (kind === "blackboxscripts") return "blackbox";
|
|
347
|
+
return void 0;
|
|
348
|
+
}
|
|
349
|
+
function devicepresetof(value) {
|
|
350
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
351
|
+
const entry = value;
|
|
352
|
+
const name = typeof entry.name === "string" && entry.name.trim() ? entry.name.trim() : void 0;
|
|
353
|
+
const width = typeof entry.width === "number" && Number.isInteger(entry.width) && entry.width > 0 ? entry.width : void 0;
|
|
354
|
+
const height = typeof entry.height === "number" && Number.isInteger(entry.height) && entry.height > 0 ? entry.height : void 0;
|
|
355
|
+
const pixelratio = typeof entry.pixelratio === "number" && Number.isFinite(entry.pixelratio) && entry.pixelratio > 0 ? entry.pixelratio : void 0;
|
|
356
|
+
if (name === void 0 || width === void 0 || height === void 0 || pixelratio === void 0) return void 0;
|
|
357
|
+
return { name, width, height, pixelratio, mobile: entry.mobile === true };
|
|
358
|
+
}
|
|
359
|
+
function networkpresetof(value) {
|
|
360
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
361
|
+
const entry = value;
|
|
362
|
+
const name = typeof entry.name === "string" && entry.name.trim() ? entry.name.trim() : void 0;
|
|
363
|
+
const latency = typeof entry.latency === "number" && Number.isFinite(entry.latency) && entry.latency >= 0 ? entry.latency : void 0;
|
|
364
|
+
const download = typeof entry.download === "number" && Number.isFinite(entry.download) && entry.download >= 0 ? entry.download : void 0;
|
|
365
|
+
const upload = typeof entry.upload === "number" && Number.isFinite(entry.upload) && entry.upload >= 0 ? entry.upload : void 0;
|
|
366
|
+
if (name === void 0 || latency === void 0 || download === void 0 || upload === void 0) return void 0;
|
|
367
|
+
return { name, latency, download, upload, offline: entry.offline === true };
|
|
368
|
+
}
|
|
369
|
+
function locationpresetof(value) {
|
|
370
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
371
|
+
const entry = value;
|
|
372
|
+
const name = typeof entry.name === "string" && entry.name.trim() ? entry.name.trim() : void 0;
|
|
373
|
+
const latitude = typeof entry.latitude === "number" && Number.isFinite(entry.latitude) ? entry.latitude : void 0;
|
|
374
|
+
const longitude = typeof entry.longitude === "number" && Number.isFinite(entry.longitude) ? entry.longitude : void 0;
|
|
375
|
+
const accuracy = typeof entry.accuracy === "number" && Number.isFinite(entry.accuracy) && entry.accuracy >= 0 ? entry.accuracy : void 0;
|
|
376
|
+
if (name === void 0 || latitude === void 0 || longitude === void 0 || accuracy === void 0) return void 0;
|
|
377
|
+
if (!locationrangevalid(latitude, longitude)) return void 0;
|
|
378
|
+
return { name, latitude, longitude, accuracy };
|
|
379
|
+
}
|
|
380
|
+
function agentpresetof(value) {
|
|
381
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
382
|
+
const entry = value;
|
|
383
|
+
const name = typeof entry.name === "string" && entry.name.trim() ? entry.name.trim() : void 0;
|
|
384
|
+
const useragent = typeof entry.useragent === "string" ? entry.useragent : void 0;
|
|
385
|
+
const platform = typeof entry.platform === "string" && entry.platform.trim() ? entry.platform.trim() : void 0;
|
|
386
|
+
const brands = Array.isArray(entry.brands) ? entry.brands.filter((brand) => typeof brand === "string" && brand.trim().length > 0) : [];
|
|
387
|
+
if (name === void 0 || useragent === void 0 || platform === void 0 || brands.length === 0) return void 0;
|
|
388
|
+
if (!agentgrammarvalid(useragent)) return void 0;
|
|
389
|
+
return { name, useragent, platform, brands: [...new Set(brands)] };
|
|
390
|
+
}
|
|
391
|
+
function permissiongrantof(value) {
|
|
392
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
393
|
+
const entry = value;
|
|
394
|
+
const name = typeof entry.name === "string" && browserpermissions.includes(entry.name) ? entry.name : void 0;
|
|
395
|
+
const state = typeof entry.state === "string" && permissionstates.includes(entry.state) ? entry.state : void 0;
|
|
396
|
+
if (name === void 0 || state === void 0) return void 0;
|
|
397
|
+
return { name, state, runscope: entry.runscope !== false };
|
|
398
|
+
}
|
|
399
|
+
function blackboxruleof(value) {
|
|
400
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
401
|
+
const entry = value;
|
|
402
|
+
const urlpatterns = Array.isArray(entry.urlpatterns) ? entry.urlpatterns.filter((pattern) => typeof pattern === "string" && /^https:\/\//.test(pattern)) : [];
|
|
403
|
+
const tracescope = entry.tracescope;
|
|
404
|
+
if (urlpatterns.length === 0) return void 0;
|
|
405
|
+
if (tracescope !== "profiles" && tracescope !== "traces" && tracescope !== "both") return void 0;
|
|
406
|
+
return { urlpatterns: [...new Set(urlpatterns)], tracescope };
|
|
407
|
+
}
|
|
408
|
+
function revertplanof(value) {
|
|
409
|
+
const steps = Array.isArray(value) ? value.filter((step) => typeof step === "string" && step.trim().length > 0) : [];
|
|
410
|
+
return steps.length > 0 ? steps : void 0;
|
|
411
|
+
}
|
|
412
|
+
function newlayer(input) {
|
|
413
|
+
return { id: input.id, runid: input.runid, stepid: input.stepid, family: input.family, name: input.name, originscope: input.originscope, appliedat: input.at, ...input.prior !== void 0 ? { prior: input.prior } : {}, revertplan: [...input.revertplan] };
|
|
414
|
+
}
|
|
415
|
+
function emulationstateof(input) {
|
|
416
|
+
return { runid: input.runid, tabid: input.tabid, origin: input.origin, layers: [], updatedat: input.now };
|
|
417
|
+
}
|
|
418
|
+
function applylayer(state, layer, at) {
|
|
419
|
+
const layers = [...state.layers.filter((item) => item.id !== layer.id), layer];
|
|
420
|
+
return { ...state, layers, updatedat: at };
|
|
421
|
+
}
|
|
422
|
+
function revertlayer(state, layerid, at) {
|
|
423
|
+
const layers = state.layers.map((layer) => layer.id === layerid && layer.revertedat === void 0 ? { ...layer, revertedat: at } : layer);
|
|
424
|
+
return { ...state, layers, updatedat: at };
|
|
425
|
+
}
|
|
426
|
+
function revertalllayers(state, at) {
|
|
427
|
+
const reverted = [...state.layers].reverse().filter((layer) => layer.revertedat === void 0);
|
|
428
|
+
const layers = state.layers.map((layer) => layer.revertedat === void 0 ? { ...layer, revertedat: at } : layer);
|
|
429
|
+
return { state: { ...state, layers, updatedat: at }, reverted };
|
|
430
|
+
}
|
|
431
|
+
function activelayers(state) {
|
|
432
|
+
return state ? state.layers.filter((layer) => layer.revertedat === void 0) : [];
|
|
433
|
+
}
|
|
434
|
+
function layernames(state) {
|
|
435
|
+
return activelayers(state).map((layer) => layer.name);
|
|
436
|
+
}
|
|
437
|
+
function stackedcount(state) {
|
|
438
|
+
return activelayers(state).length;
|
|
439
|
+
}
|
|
440
|
+
function locationrangevalid(latitude, longitude) {
|
|
441
|
+
return Number.isFinite(latitude) && Number.isFinite(longitude) && latitude >= -90 && latitude <= 90 && longitude >= -180 && longitude <= 180;
|
|
442
|
+
}
|
|
443
|
+
function agentgrammarvalid(useragent) {
|
|
444
|
+
const text2 = useragent.trim();
|
|
445
|
+
if (text2.length === 0 || text2.length > 512) return false;
|
|
446
|
+
if (/[\r\n]/.test(text2)) return false;
|
|
447
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._+\-()/:; ,]*$/.test(text2)) return false;
|
|
448
|
+
return /\/\d/.test(text2) || /\d+\.\d+/.test(text2);
|
|
449
|
+
}
|
|
450
|
+
function permissiongrade(name) {
|
|
451
|
+
return name === "geolocation" || name === "camera" || name === "microphone" || name === "notifications" ? "powerful" : "standard";
|
|
452
|
+
}
|
|
453
|
+
function blackboxmatches(urlpattern, url) {
|
|
454
|
+
const patternmatch = /^(https:\/\/[^/]+)(\/.*)?$/.exec(urlpattern);
|
|
455
|
+
const urlmatch = /^(https:\/\/[^/]+)(\/.*)?$/.exec(url);
|
|
456
|
+
if (!patternmatch || !urlmatch) return false;
|
|
457
|
+
if (patternmatch[1] !== urlmatch[1]) return false;
|
|
458
|
+
const patternpath = (patternmatch[2] ?? "/").split("/").filter((segment) => segment.length > 0);
|
|
459
|
+
const urlpath = (urlmatch[2] ?? "/").split("/").filter((segment) => segment.length > 0);
|
|
460
|
+
const walk = (patternindex, urlindex) => {
|
|
461
|
+
if (patternindex >= patternpath.length) return urlindex >= urlpath.length;
|
|
462
|
+
const segment = patternpath[patternindex];
|
|
463
|
+
if (segment === void 0) return false;
|
|
464
|
+
if (segment === "**") return walk(patternindex + 1, urlindex) || urlindex < urlpath.length && walk(patternindex, urlindex + 1);
|
|
465
|
+
if (urlindex >= urlpath.length) return false;
|
|
466
|
+
if (segment !== "*" && segment !== urlpath[urlindex]) return false;
|
|
467
|
+
return walk(patternindex + 1, urlindex + 1);
|
|
468
|
+
};
|
|
469
|
+
return walk(0, 0);
|
|
470
|
+
}
|
|
471
|
+
function hideblackboxedframes(rules, frames) {
|
|
472
|
+
const patterns = rules.filter((rule) => rule.tracescope === "traces" || rule.tracescope === "both").flatMap((rule) => rule.urlpatterns);
|
|
473
|
+
if (patterns.length === 0) return frames;
|
|
474
|
+
return frames.filter((frame) => !patterns.some((pattern) => blackboxmatches(pattern, frame.url)));
|
|
475
|
+
}
|
|
476
|
+
function blackboxedurls(rules, urls) {
|
|
477
|
+
const patterns = rules.flatMap((rule) => rule.urlpatterns);
|
|
478
|
+
return urls.filter((url) => patterns.some((pattern) => blackboxmatches(pattern, url)));
|
|
479
|
+
}
|
|
480
|
+
function expirelayers(state, retention, now) {
|
|
481
|
+
if (retention === void 0) return state;
|
|
482
|
+
const layers = state.layers.map((layer) => {
|
|
483
|
+
if (layer.revertedat === void 0 || layer.prior === void 0 || layer.priorexpired === true) return layer;
|
|
484
|
+
if (now - layer.revertedat <= retention) return layer;
|
|
485
|
+
const { prior, ...metadata } = layer;
|
|
486
|
+
void prior;
|
|
487
|
+
return { ...metadata, priorexpired: true };
|
|
488
|
+
});
|
|
489
|
+
return { ...state, layers, updatedat: now };
|
|
490
|
+
}
|
|
491
|
+
function exportpresetlibrary(input) {
|
|
492
|
+
return { version: 1, devices: [...input.devices], networks: [...input.networks], locations: [...input.locations], agents: [...input.agents], exportedat: input.now };
|
|
493
|
+
}
|
|
494
|
+
function importpresetlibrary(value) {
|
|
495
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
496
|
+
const entry = value;
|
|
497
|
+
const devices = (Array.isArray(entry.devices) ? entry.devices : []).flatMap((preset) => {
|
|
498
|
+
const parsed = devicepresetof(preset);
|
|
499
|
+
return parsed !== void 0 ? [parsed] : [];
|
|
500
|
+
});
|
|
501
|
+
const networks = (Array.isArray(entry.networks) ? entry.networks : []).flatMap((preset) => {
|
|
502
|
+
const parsed = networkpresetof(preset);
|
|
503
|
+
return parsed !== void 0 ? [parsed] : [];
|
|
504
|
+
});
|
|
505
|
+
const locations = (Array.isArray(entry.locations) ? entry.locations : []).flatMap((preset) => {
|
|
506
|
+
const parsed = locationpresetof(preset);
|
|
507
|
+
return parsed !== void 0 ? [parsed] : [];
|
|
508
|
+
});
|
|
509
|
+
const agents = (Array.isArray(entry.agents) ? entry.agents : []).flatMap((preset) => {
|
|
510
|
+
const parsed = agentpresetof(preset);
|
|
511
|
+
return parsed !== void 0 ? [parsed] : [];
|
|
512
|
+
});
|
|
513
|
+
if (devices.length + networks.length + locations.length + agents.length === 0) return void 0;
|
|
514
|
+
return { version: typeof entry.version === "number" && Number.isInteger(entry.version) && entry.version >= 1 ? entry.version : 1, devices, networks, locations, agents, exportedat: typeof entry.exportedat === "number" ? entry.exportedat : Date.now() };
|
|
515
|
+
}
|
|
516
|
+
function locationconsentcovers(origin, latitude, longitude, consents) {
|
|
517
|
+
return consents.some((consent) => consent.origin === origin && consent.approved === true && consent.revokedat === void 0 && consent.latitude === latitude && consent.longitude === longitude);
|
|
518
|
+
}
|
|
519
|
+
|
|
336
520
|
// httpclient.ts
|
|
337
521
|
var httpkinds = ["fetchurl", "parsejson", "parsehtml", "callrest", "callgraphql"];
|
|
338
522
|
var redirectstatuses = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
@@ -1147,6 +1331,212 @@ function expireprofilerecords(input) {
|
|
|
1147
1331
|
};
|
|
1148
1332
|
}
|
|
1149
1333
|
|
|
1334
|
+
// sessions.ts
|
|
1335
|
+
var sessionkinds = ["persiststate", "capturesession", "restoresession", "namedsessions", "diffsessions", "searchsessions", "exportsessions", "importsessions"];
|
|
1336
|
+
var sessionfileversion = 1;
|
|
1337
|
+
var snapshotsections = ["tabs", "scroll", "forms", "storage", "cookies"];
|
|
1338
|
+
var searchfields = ["urls", "titles", "names", "text"];
|
|
1339
|
+
function checksumtext(payload) {
|
|
1340
|
+
let hash = 2166136261;
|
|
1341
|
+
for (let index = 0; index < payload.length; index += 1) {
|
|
1342
|
+
hash ^= payload.charCodeAt(index);
|
|
1343
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
1344
|
+
}
|
|
1345
|
+
return hash.toString(16).padStart(8, "0");
|
|
1346
|
+
}
|
|
1347
|
+
function taskstatechecksum(runid, stepcursor, outputs) {
|
|
1348
|
+
return checksumtext(`${runid}:${stepcursor}:${outputs.length}:${outputs.map((output) => `${output.stepid}:${output.ok}:${output.summary.length}`).join("|")}`);
|
|
1349
|
+
}
|
|
1350
|
+
function taskstateof(input) {
|
|
1351
|
+
return { runid: input.runid, stepcursor: input.stepcursor, outputs: input.outputs, checkpointat: input.checkpointat, checksum: taskstatechecksum(input.runid, input.stepcursor, input.outputs) };
|
|
1352
|
+
}
|
|
1353
|
+
function taskstatevalid(state) {
|
|
1354
|
+
if (!state || typeof state.runid !== "string" || !state.runid.trim()) return false;
|
|
1355
|
+
if (typeof state.stepcursor !== "number" || !Number.isInteger(state.stepcursor) || state.stepcursor < 0) return false;
|
|
1356
|
+
if (typeof state.checkpointat !== "number" || !Number.isFinite(state.checkpointat)) return false;
|
|
1357
|
+
if (!Array.isArray(state.outputs)) return false;
|
|
1358
|
+
return state.checksum === taskstatechecksum(state.runid, state.stepcursor, state.outputs);
|
|
1359
|
+
}
|
|
1360
|
+
function sessiontabof(value) {
|
|
1361
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1362
|
+
const candidate = value;
|
|
1363
|
+
if (typeof candidate.url !== "string" || !candidate.url.trim()) return void 0;
|
|
1364
|
+
if (typeof candidate.title !== "string") return void 0;
|
|
1365
|
+
if (typeof candidate.index !== "number" || !Number.isInteger(candidate.index) || candidate.index < 0) return void 0;
|
|
1366
|
+
const scrollx = typeof candidate.scrollx === "number" && Number.isFinite(candidate.scrollx) ? candidate.scrollx : 0;
|
|
1367
|
+
const scrolly = typeof candidate.scrolly === "number" && Number.isFinite(candidate.scrolly) ? candidate.scrolly : 0;
|
|
1368
|
+
const forms = Array.isArray(candidate.forms) ? candidate.forms.flatMap((entry) => {
|
|
1369
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
|
|
1370
|
+
const form = entry;
|
|
1371
|
+
if (typeof form.selector !== "string" || !form.selector.trim()) return [];
|
|
1372
|
+
return [{ selector: form.selector, value: typeof form.value === "string" ? form.value : "" }];
|
|
1373
|
+
}) : [];
|
|
1374
|
+
return { url: candidate.url, title: candidate.title, index: candidate.index, scrollx, scrolly, forms };
|
|
1375
|
+
}
|
|
1376
|
+
function autointervalof(value) {
|
|
1377
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1378
|
+
const candidate = value;
|
|
1379
|
+
if (typeof candidate.period !== "number" || !Number.isFinite(candidate.period) || candidate.period <= 0) return void 0;
|
|
1380
|
+
if (typeof candidate.maxsnapshots !== "number" || !Number.isInteger(candidate.maxsnapshots) || candidate.maxsnapshots < 1) return void 0;
|
|
1381
|
+
if (typeof candidate.expiry !== "number" || !Number.isFinite(candidate.expiry) || candidate.expiry < 0) return void 0;
|
|
1382
|
+
return { period: candidate.period, maxsnapshots: candidate.maxsnapshots, expiry: candidate.expiry };
|
|
1383
|
+
}
|
|
1384
|
+
function snapshotplanof(value) {
|
|
1385
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1386
|
+
const candidate = value;
|
|
1387
|
+
if (candidate.scope !== "tab" && candidate.scope !== "run" && candidate.scope !== "all") return void 0;
|
|
1388
|
+
const sections = Array.isArray(candidate.sections) ? candidate.sections.flatMap((section) => typeof section === "string" && snapshotsections.includes(section) ? [section] : []) : [];
|
|
1389
|
+
if (sections.length === 0) return void 0;
|
|
1390
|
+
if (typeof candidate.captures !== "boolean") return void 0;
|
|
1391
|
+
const auto = candidate.auto === void 0 ? void 0 : autointervalof(candidate.auto);
|
|
1392
|
+
if (candidate.auto !== void 0 && auto === void 0) return void 0;
|
|
1393
|
+
return { scope: candidate.scope, sections, captures: candidate.captures, ...auto !== void 0 ? { auto } : {} };
|
|
1394
|
+
}
|
|
1395
|
+
function restoreplanof(value) {
|
|
1396
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1397
|
+
const candidate = value;
|
|
1398
|
+
if (candidate.tabpolicy !== "reopen" && candidate.tabpolicy !== "skip") return void 0;
|
|
1399
|
+
if (candidate.formpolicy !== "restore" && candidate.formpolicy !== "skip") return void 0;
|
|
1400
|
+
if (candidate.capturepolicy !== "link" && candidate.capturepolicy !== "skip") return void 0;
|
|
1401
|
+
return { tabpolicy: candidate.tabpolicy, formpolicy: candidate.formpolicy, capturepolicy: candidate.capturepolicy };
|
|
1402
|
+
}
|
|
1403
|
+
function searchqueryof(value) {
|
|
1404
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1405
|
+
const candidate = value;
|
|
1406
|
+
const terms = Array.isArray(candidate.terms) ? candidate.terms.flatMap((term) => typeof term === "string" && term.trim() ? [term.trim()] : []) : [];
|
|
1407
|
+
if (terms.length === 0) return void 0;
|
|
1408
|
+
const fields = Array.isArray(candidate.fields) ? candidate.fields.flatMap((field) => typeof field === "string" && searchfields.includes(field) ? [field] : []) : [...searchfields];
|
|
1409
|
+
if (fields.length === 0) return void 0;
|
|
1410
|
+
const from = typeof candidate.from === "number" && Number.isFinite(candidate.from) ? candidate.from : void 0;
|
|
1411
|
+
const to = typeof candidate.to === "number" && Number.isFinite(candidate.to) ? candidate.to : void 0;
|
|
1412
|
+
if (from !== void 0 && to !== void 0 && from > to) return void 0;
|
|
1413
|
+
return { terms, fields, ...from !== void 0 ? { from } : {}, ...to !== void 0 ? { to } : {} };
|
|
1414
|
+
}
|
|
1415
|
+
function sessionfolderof(value) {
|
|
1416
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1417
|
+
const candidate = value;
|
|
1418
|
+
if (typeof candidate.name !== "string" || !candidate.name.trim()) return void 0;
|
|
1419
|
+
const parent = typeof candidate.parent === "string" && candidate.parent.trim() ? candidate.parent : void 0;
|
|
1420
|
+
const tags = Array.isArray(candidate.tags) ? candidate.tags.flatMap((tag) => typeof tag === "string" && tag.trim() ? [tag] : []) : [];
|
|
1421
|
+
return { name: candidate.name, ...parent !== void 0 ? { parent } : {}, tags };
|
|
1422
|
+
}
|
|
1423
|
+
function newsessionrecord(input) {
|
|
1424
|
+
return { id: input.id, name: input.name, createdat: input.createdat, tabs: input.tabs, captures: input.captures, storage: input.storage, cookies: input.cookies, ...input.folder !== void 0 ? { folder: input.folder } : {}, tags: input.tags ?? [], ...input.auto === true ? { auto: true } : {} };
|
|
1425
|
+
}
|
|
1426
|
+
function diffsessionrecords(left, right) {
|
|
1427
|
+
const changes = [];
|
|
1428
|
+
const leftbyindex = new Map(left.tabs.map((tab) => [tab.index, tab]));
|
|
1429
|
+
const rightbyindex = new Map(right.tabs.map((tab) => [tab.index, tab]));
|
|
1430
|
+
for (const tab of right.tabs) {
|
|
1431
|
+
const prior = leftbyindex.get(tab.index);
|
|
1432
|
+
if (!prior) {
|
|
1433
|
+
changes.push({ class: "added", subject: "tab", detail: `Tab ${tab.index} added: ${tab.url}` });
|
|
1434
|
+
continue;
|
|
1435
|
+
}
|
|
1436
|
+
if (prior.url !== tab.url) changes.push({ class: "changed", subject: "url", detail: `Tab ${tab.index} moved from ${prior.url} to ${tab.url}` });
|
|
1437
|
+
if (prior.title !== tab.title) changes.push({ class: "changed", subject: "tab", detail: `Tab ${tab.index} title changed from "${prior.title}" to "${tab.title}"` });
|
|
1438
|
+
const priorforms = new Map(prior.forms.map((form) => [form.selector, form.value]));
|
|
1439
|
+
for (const form of tab.forms) {
|
|
1440
|
+
const before = priorforms.get(form.selector);
|
|
1441
|
+
if (before === void 0) {
|
|
1442
|
+
changes.push({ class: "added", subject: "form", detail: `Form field ${form.selector} of tab ${tab.index} added with a value` });
|
|
1443
|
+
continue;
|
|
1444
|
+
}
|
|
1445
|
+
if (before !== form.value) changes.push({ class: "changed", subject: "form", detail: `Form field ${form.selector} of tab ${tab.index} changed its captured value` });
|
|
1446
|
+
}
|
|
1447
|
+
for (const form of prior.forms) if (!tab.forms.some((entry) => entry.selector === form.selector)) changes.push({ class: "removed", subject: "form", detail: `Form field ${form.selector} of tab ${tab.index} removed` });
|
|
1448
|
+
}
|
|
1449
|
+
for (const tab of left.tabs) if (!rightbyindex.has(tab.index)) changes.push({ class: "removed", subject: "tab", detail: `Tab ${tab.index} removed: ${tab.url}` });
|
|
1450
|
+
const leftstorage = new Map(left.storage.map((entry) => [entry.origin, entry]));
|
|
1451
|
+
for (const entry of right.storage) {
|
|
1452
|
+
const prior = leftstorage.get(entry.origin);
|
|
1453
|
+
if (!prior) {
|
|
1454
|
+
changes.push({ class: "added", subject: "storage", detail: `Local storage of ${entry.origin} captured with ${entry.keys.length} keys` });
|
|
1455
|
+
continue;
|
|
1456
|
+
}
|
|
1457
|
+
if (prior.keys.join("|") !== entry.keys.join("|") || prior.values.join("|") !== entry.values.join("|")) changes.push({ class: "changed", subject: "storage", detail: `Local storage of ${entry.origin} changed its captured keys or values` });
|
|
1458
|
+
}
|
|
1459
|
+
for (const entry of left.storage) if (!right.storage.some((candidate) => candidate.origin === entry.origin)) changes.push({ class: "removed", subject: "storage", detail: `Local storage of ${entry.origin} left the capture` });
|
|
1460
|
+
return changes;
|
|
1461
|
+
}
|
|
1462
|
+
function newsessiondiff(input) {
|
|
1463
|
+
return { id: input.id, leftid: input.left.id, rightid: input.right.id, changes: diffsessionrecords(input.left, input.right), at: input.at };
|
|
1464
|
+
}
|
|
1465
|
+
function searchsessionrecords(query, records) {
|
|
1466
|
+
const matches = [];
|
|
1467
|
+
for (const record2 of records) {
|
|
1468
|
+
if (query.from !== void 0 && record2.createdat < query.from) continue;
|
|
1469
|
+
if (query.to !== void 0 && record2.createdat > query.to) continue;
|
|
1470
|
+
const haystacks = [
|
|
1471
|
+
{ field: "urls", text: record2.tabs.map((tab) => tab.url).join(" ") },
|
|
1472
|
+
{ field: "titles", text: record2.tabs.map((tab) => tab.title).join(" ") },
|
|
1473
|
+
{ field: "names", text: [record2.name, record2.folder ?? "", ...record2.tags].join(" ") },
|
|
1474
|
+
{ field: "text", text: record2.tabs.flatMap((tab) => tab.forms.map((form) => form.value)).join(" ") }
|
|
1475
|
+
];
|
|
1476
|
+
for (const haystack of haystacks) {
|
|
1477
|
+
if (!query.fields.includes(haystack.field)) continue;
|
|
1478
|
+
const lower = haystack.text.toLowerCase();
|
|
1479
|
+
for (const term of query.terms) {
|
|
1480
|
+
const at = lower.indexOf(term.toLowerCase());
|
|
1481
|
+
if (at < 0) continue;
|
|
1482
|
+
const start = Math.max(0, at - 30);
|
|
1483
|
+
matches.push({ sessionid: record2.id, field: haystack.field, term, at: record2.createdat, excerpt: haystack.text.slice(start, start + 80).trim() });
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
return matches;
|
|
1488
|
+
}
|
|
1489
|
+
function exportsessionfile(records, now) {
|
|
1490
|
+
const recordids = records.map((record2) => record2.id);
|
|
1491
|
+
const payload = JSON.stringify(records);
|
|
1492
|
+
return { formatversion: sessionfileversion, records, recordids, bytesize: payload.length, checksum: checksumtext(`${sessionfileversion}:${recordids.join(",")}:${payload.length}`), exportedat: now };
|
|
1493
|
+
}
|
|
1494
|
+
function importsessionfile(value) {
|
|
1495
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1496
|
+
const candidate = value;
|
|
1497
|
+
if (candidate.formatversion !== sessionfileversion) return void 0;
|
|
1498
|
+
const records = Array.isArray(candidate.records) ? candidate.records.flatMap((record2) => sessionrecordvalid(record2) ? [record2] : []) : [];
|
|
1499
|
+
if (records.length === 0) return void 0;
|
|
1500
|
+
if (!Array.isArray(candidate.recordids) || candidate.recordids.length !== records.length || !candidate.recordids.every((id, index) => id === records[index]?.id)) return void 0;
|
|
1501
|
+
const bytesize = typeof candidate.bytesize === "number" && Number.isFinite(candidate.bytesize) ? candidate.bytesize : -1;
|
|
1502
|
+
if (bytesize < 0) return void 0;
|
|
1503
|
+
const checksum = typeof candidate.checksum === "string" ? candidate.checksum : "";
|
|
1504
|
+
if (checksum !== checksumtext(`${sessionfileversion}:${candidate.recordids.join(",")}:${bytesize}`)) return void 0;
|
|
1505
|
+
return { formatversion: sessionfileversion, records, recordids: candidate.recordids, bytesize, checksum, exportedat: typeof candidate.exportedat === "number" && Number.isFinite(candidate.exportedat) ? candidate.exportedat : 0 };
|
|
1506
|
+
}
|
|
1507
|
+
function sessionrecordvalid(value) {
|
|
1508
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1509
|
+
const candidate = value;
|
|
1510
|
+
if (typeof candidate.id !== "string" || !candidate.id.trim()) return false;
|
|
1511
|
+
if (typeof candidate.name !== "string" || !candidate.name.trim()) return false;
|
|
1512
|
+
if (typeof candidate.createdat !== "number" || !Number.isFinite(candidate.createdat)) return false;
|
|
1513
|
+
if (!Array.isArray(candidate.tabs) || !candidate.tabs.every((tab) => sessiontabof(tab) !== void 0)) return false;
|
|
1514
|
+
if (!Array.isArray(candidate.captures) || !candidate.captures.every((id) => typeof id === "string")) return false;
|
|
1515
|
+
if (!Array.isArray(candidate.tags) || !candidate.tags.every((tag) => typeof tag === "string")) return false;
|
|
1516
|
+
return true;
|
|
1517
|
+
}
|
|
1518
|
+
function expiresessions(records, retention, now) {
|
|
1519
|
+
if (retention === void 0 || !Number.isFinite(retention)) return records;
|
|
1520
|
+
return records.map((record2) => {
|
|
1521
|
+
if (record2.sectionsexpired || now - record2.createdat < retention) return record2;
|
|
1522
|
+
return { id: record2.id, name: record2.name, createdat: record2.createdat, tabs: [], captures: record2.captures, storage: [], cookies: [], ...record2.folder !== void 0 ? { folder: record2.folder } : {}, tags: record2.tags, ...record2.auto === true ? { auto: true } : {}, ...record2.restoredat !== void 0 ? { restoredat: record2.restoredat } : {}, sectionsexpired: true };
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
function filteredsessions(records, filter) {
|
|
1526
|
+
return records.filter((record2) => {
|
|
1527
|
+
if (filter.name !== void 0 && !record2.name.toLowerCase().includes(filter.name.toLowerCase())) return false;
|
|
1528
|
+
if (filter.folder !== void 0 && record2.folder !== filter.folder) return false;
|
|
1529
|
+
if (filter.from !== void 0 && record2.createdat < filter.from) return false;
|
|
1530
|
+
if (filter.to !== void 0 && record2.createdat > filter.to) return false;
|
|
1531
|
+
return true;
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
function crashinterrupted(state, plansteps, now) {
|
|
1535
|
+
if (!state) return void 0;
|
|
1536
|
+
if (state.stepcursor >= plansteps) return state;
|
|
1537
|
+
return { ...state, interrupted: true, crashat: state.crashat ?? now };
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1150
1540
|
// memory.ts
|
|
1151
1541
|
var sessionmemory = class {
|
|
1152
1542
|
constructor(adapter) {
|
|
@@ -2517,6 +2907,169 @@ var sessionmemory = class {
|
|
|
2517
2907
|
await this.adapter.set("sourcemapconsents", updated);
|
|
2518
2908
|
return revoked;
|
|
2519
2909
|
}
|
|
2910
|
+
/** Stores the emulation state of one run keyed by its run id; the reverted layer prior states expire after the user configured retention window while the layer history always survives. */
|
|
2911
|
+
async setemulationstate(state) {
|
|
2912
|
+
const retention = (await this.getsettings())?.emulationretention;
|
|
2913
|
+
await this.adapter.set(`emulationstate${state.runid}`, expirelayers(state, retention, Date.now()));
|
|
2914
|
+
}
|
|
2915
|
+
/** Returns the persisted emulation state of one run so the layers survive service worker restarts. */
|
|
2916
|
+
async getemulationstate(runid) {
|
|
2917
|
+
return this.adapter.get(`emulationstate${runid}`);
|
|
2918
|
+
}
|
|
2919
|
+
/** Returns the active and past layers of one run, newest last in apply order; the listlayers accessor of the emulation memory. */
|
|
2920
|
+
async listlayers(runid) {
|
|
2921
|
+
const state = await this.getemulationstate(runid);
|
|
2922
|
+
return state?.layers ?? [];
|
|
2923
|
+
}
|
|
2924
|
+
/** Stores one user curated device preset by its name so the preset library stays user data instead of a hardcoded list. */
|
|
2925
|
+
async setdevicepreset(preset) {
|
|
2926
|
+
const records = (await this.adapter.get("devicepresets") ?? []).filter((item) => item.name !== preset.name);
|
|
2927
|
+
await this.adapter.set("devicepresets", [...records, preset]);
|
|
2928
|
+
}
|
|
2929
|
+
/** Returns every user curated device preset. */
|
|
2930
|
+
async getdevicepresets() {
|
|
2931
|
+
return await this.adapter.get("devicepresets") ?? [];
|
|
2932
|
+
}
|
|
2933
|
+
/** Stores one user curated network preset by its name with editable values. */
|
|
2934
|
+
async setnetworkpreset(preset) {
|
|
2935
|
+
const records = (await this.adapter.get("networkpresets") ?? []).filter((item) => item.name !== preset.name);
|
|
2936
|
+
await this.adapter.set("networkpresets", [...records, preset]);
|
|
2937
|
+
}
|
|
2938
|
+
/** Returns every user curated network preset. */
|
|
2939
|
+
async getnetworkpresets() {
|
|
2940
|
+
return await this.adapter.get("networkpresets") ?? [];
|
|
2941
|
+
}
|
|
2942
|
+
/** Stores one user curated location preset by its name. */
|
|
2943
|
+
async setlocationpreset(preset) {
|
|
2944
|
+
const records = (await this.adapter.get("locationpresets") ?? []).filter((item) => item.name !== preset.name);
|
|
2945
|
+
await this.adapter.set("locationpresets", [...records, preset]);
|
|
2946
|
+
}
|
|
2947
|
+
/** Returns every user curated location preset. */
|
|
2948
|
+
async getlocationpresets() {
|
|
2949
|
+
return await this.adapter.get("locationpresets") ?? [];
|
|
2950
|
+
}
|
|
2951
|
+
/** Stores one user curated agent preset by its name. */
|
|
2952
|
+
async setagentpreset(preset) {
|
|
2953
|
+
const records = (await this.adapter.get("agentpresets") ?? []).filter((item) => item.name !== preset.name);
|
|
2954
|
+
await this.adapter.set("agentpresets", [...records, preset]);
|
|
2955
|
+
}
|
|
2956
|
+
/** Returns every user curated agent preset. */
|
|
2957
|
+
async getagentpresets() {
|
|
2958
|
+
return await this.adapter.get("agentpresets") ?? [];
|
|
2959
|
+
}
|
|
2960
|
+
/** Replaces the blackbox rule set of one origin so third party script blackboxing stays scoped per origin. */
|
|
2961
|
+
async setblackboxrules(origin, rules) {
|
|
2962
|
+
const records = (await this.adapter.get("blackboxrules") ?? []).filter((item) => item.origin !== origin);
|
|
2963
|
+
await this.adapter.set("blackboxrules", [...records, { origin, rules }]);
|
|
2964
|
+
}
|
|
2965
|
+
/** Returns every stored blackbox rule set with its origin. */
|
|
2966
|
+
async getblackboxrules() {
|
|
2967
|
+
return await this.adapter.get("blackboxrules") ?? [];
|
|
2968
|
+
}
|
|
2969
|
+
/** Records one permission override of a run with its prior state captured for the exact restore. */
|
|
2970
|
+
async addpermissionoverride(record2) {
|
|
2971
|
+
const records = (await this.adapter.get("permissionoverrides") ?? []).filter((item) => item.id !== record2.id);
|
|
2972
|
+
await this.adapter.set("permissionoverrides", [record2, ...records]);
|
|
2973
|
+
}
|
|
2974
|
+
/** Returns the permission override history with restore states, newest first. */
|
|
2975
|
+
async getpermissionoverrides() {
|
|
2976
|
+
return await this.adapter.get("permissionoverrides") ?? [];
|
|
2977
|
+
}
|
|
2978
|
+
/** Stores one location consent decision per origin, replacing the previous decision of its id. */
|
|
2979
|
+
async setlocationconsent(consent) {
|
|
2980
|
+
const records = (await this.adapter.get("locationconsents") ?? []).filter((item) => item.id !== consent.id);
|
|
2981
|
+
await this.adapter.set("locationconsents", [consent, ...records]);
|
|
2982
|
+
}
|
|
2983
|
+
/** Returns every location consent decision, newest first. */
|
|
2984
|
+
async getlocationconsents() {
|
|
2985
|
+
return await this.adapter.get("locationconsents") ?? [];
|
|
2986
|
+
}
|
|
2987
|
+
/** Returns the persisted task state checkpoint of one run so the run resumes after a service worker restart. */
|
|
2988
|
+
async gettaskstate(runid) {
|
|
2989
|
+
return this.adapter.get(`taskstate${runid}`);
|
|
2990
|
+
}
|
|
2991
|
+
/** Persists one task state checkpoint per run with its corruption checksum. */
|
|
2992
|
+
async settaskstate(state) {
|
|
2993
|
+
return this.adapter.set(`taskstate${state.runid}`, state);
|
|
2994
|
+
}
|
|
2995
|
+
/** Returns the session event history with timestamps, newest first. */
|
|
2996
|
+
async getsessionevents() {
|
|
2997
|
+
return await this.adapter.get("sessionevents") ?? [];
|
|
2998
|
+
}
|
|
2999
|
+
/** Records one session event of the run with its timestamp and detail. */
|
|
3000
|
+
async addsessionevent(event) {
|
|
3001
|
+
const records = await this.getsessionevents();
|
|
3002
|
+
await this.adapter.set("sessionevents", [event, ...records]);
|
|
3003
|
+
}
|
|
3004
|
+
/** Returns every saved session record with its sections, newest first. */
|
|
3005
|
+
async getsessionrecords() {
|
|
3006
|
+
return await this.adapter.get("sessionrecords") ?? [];
|
|
3007
|
+
}
|
|
3008
|
+
/** Adds one saved session record to the library. */
|
|
3009
|
+
async addsessionrecord(record2) {
|
|
3010
|
+
const records = await this.getsessionrecords();
|
|
3011
|
+
await this.adapter.set("sessionrecords", [record2, ...records]);
|
|
3012
|
+
}
|
|
3013
|
+
/** Replaces one saved session record by its id after a filing or restore touches it. */
|
|
3014
|
+
async updatesessionrecord(record2) {
|
|
3015
|
+
const records = await this.getsessionrecords();
|
|
3016
|
+
await this.adapter.set("sessionrecords", records.map((item) => item.id === record2.id ? record2 : item));
|
|
3017
|
+
}
|
|
3018
|
+
/** Lists saved sessions filtered by name substring, folder and time window; the filter stays a user choice with no result cap. */
|
|
3019
|
+
async listsessions(filter) {
|
|
3020
|
+
return filteredsessions(await this.getsessionrecords(), filter);
|
|
3021
|
+
}
|
|
3022
|
+
/** Returns one saved session with every section; an expired record carries its metadata only. */
|
|
3023
|
+
async getsessionrecord(id) {
|
|
3024
|
+
return (await this.getsessionrecords()).find((record2) => record2.id === id);
|
|
3025
|
+
}
|
|
3026
|
+
/** Runs the reviewed search query across every stored session and returns the matches with their session ids and time windows. */
|
|
3027
|
+
async searchmemory(query) {
|
|
3028
|
+
return searchsessionrecords(query, await this.getsessionrecords());
|
|
3029
|
+
}
|
|
3030
|
+
/** Returns the folder tree of the session library. */
|
|
3031
|
+
async getsessionfolders() {
|
|
3032
|
+
return await this.adapter.get("sessionfolders") ?? [];
|
|
3033
|
+
}
|
|
3034
|
+
/** Replaces the folder tree after a reviewed filing adds or moves one folder. */
|
|
3035
|
+
async setsessionfolders(folders) {
|
|
3036
|
+
return this.adapter.set("sessionfolders", folders);
|
|
3037
|
+
}
|
|
3038
|
+
/** Returns every stored session diff result, newest first. */
|
|
3039
|
+
async getsessiondiffs() {
|
|
3040
|
+
return await this.adapter.get("sessiondiffs") ?? [];
|
|
3041
|
+
}
|
|
3042
|
+
/** Stores one session diff result for later review. */
|
|
3043
|
+
async addsessiondiff(diff) {
|
|
3044
|
+
const records = await this.getsessiondiffs();
|
|
3045
|
+
await this.adapter.set("sessiondiffs", [diff, ...records]);
|
|
3046
|
+
}
|
|
3047
|
+
/** Returns the persisted auto snapshot state with the reviewed interval, the last snapshot time and the snapshot count. */
|
|
3048
|
+
async getautosnapshot() {
|
|
3049
|
+
return await this.adapter.get("autosnapshot") ?? void 0;
|
|
3050
|
+
}
|
|
3051
|
+
/** Stores the auto snapshot state of the reviewed interval. */
|
|
3052
|
+
async setautosnapshot(state) {
|
|
3053
|
+
return this.adapter.set("autosnapshot", state);
|
|
3054
|
+
}
|
|
3055
|
+
/** Clears the auto snapshot interval so on demand captures stay the only source of records. */
|
|
3056
|
+
async clearautosnapshot() {
|
|
3057
|
+
return this.adapter.set("autosnapshot", null);
|
|
3058
|
+
}
|
|
3059
|
+
/** Expires the heavy sections of saved sessions after the reviewed retention window while the record metadata survives. */
|
|
3060
|
+
async applysessionexpiry(retention, now) {
|
|
3061
|
+
const records = expiresessions(await this.getsessionrecords(), retention, now);
|
|
3062
|
+
await this.adapter.set("sessionrecords", records);
|
|
3063
|
+
return records;
|
|
3064
|
+
}
|
|
3065
|
+
/** Returns the crash marker of a run interrupted by a browser restart. */
|
|
3066
|
+
async getcrashflag() {
|
|
3067
|
+
return await this.adapter.get("crashed") ?? false;
|
|
3068
|
+
}
|
|
3069
|
+
/** Sets the crash marker so the sessions view offers the crash restore inside the consent model. */
|
|
3070
|
+
async setcrashflag(value) {
|
|
3071
|
+
return this.adapter.set("crashed", value);
|
|
3072
|
+
}
|
|
2520
3073
|
};
|
|
2521
3074
|
function mediakindof(record2) {
|
|
2522
3075
|
if ("pages" in record2) return "pdf";
|
|
@@ -3463,9 +4016,9 @@ function polldecision(input) {
|
|
|
3463
4016
|
}
|
|
3464
4017
|
|
|
3465
4018
|
// policy.ts
|
|
3466
|
-
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles", "attachcdp", "detachcdp", "cdpcmd", "overridescript", "heapshot", "profilecpu", "capturesourcemaps"]);
|
|
4019
|
+
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles", "attachcdp", "detachcdp", "cdpcmd", "overridescript", "heapshot", "profilecpu", "capturesourcemaps", "emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission", "restoresession", "exportsessions", "importsessions"]);
|
|
3467
4020
|
var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction", "capturebodies", "setbreakpoint", "stepcode", "watchexpr"]);
|
|
3468
|
-
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures", "shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet", "capturepdf", "captureframe", "readmedia", "readassets", "probestream", "timelapse", "shotcanvas", "convertimage", "makethumbs", "fetchurl", "parsejson", "parsehtml", "opensocket", "waitmessage", "watchrequests", "readheaders", "mapapi", "subscribesse", "longpoll", "extractapi", "readcookies", "watchconsole", "watcherrors", "watchtasks", "watchcdp", "measureflow", "trackmemory", "watchshifts", "traceload", "annotatetrace", "replaytrace"]);
|
|
4021
|
+
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures", "shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet", "capturepdf", "captureframe", "readmedia", "readassets", "probestream", "timelapse", "shotcanvas", "convertimage", "makethumbs", "fetchurl", "parsejson", "parsehtml", "opensocket", "waitmessage", "watchrequests", "readheaders", "mapapi", "subscribesse", "longpoll", "extractapi", "readcookies", "watchconsole", "watcherrors", "watchtasks", "watchcdp", "measureflow", "trackmemory", "watchshifts", "traceload", "annotatetrace", "replaytrace", "blackboxscripts", "persiststate", "capturesession", "namedsessions", "diffsessions", "searchsessions"]);
|
|
3469
4022
|
var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
|
|
3470
4023
|
var watchactions = /* @__PURE__ */ new Set(["watchmutate", "watchbanner", "watchfocus", "watchtab"]);
|
|
3471
4024
|
var targetactions = /* @__PURE__ */ new Set(["inspect", "focus", "click", "type", "scroll", "select", "hover", "clickdeep", "rightclick", "doubleclick", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "highlight", "setattribute", "removeattribute", "waitfor", "shiftclick", "typetime", "appendtext", "setvalue", "typeedit", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "expanddetails", "verifyvisible", "verifyenabled", "pierceshadow", "deriveselector", "fingerprintsection", "submitform", "retryform", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcode", "consentpassword", "scrapetable", "paginateextract", "shotelement", "captureframe", "shotcanvas"]);
|
|
@@ -3484,6 +4037,8 @@ var controlactions = /* @__PURE__ */ new Set(["blockrequest", "mockresponse", "r
|
|
|
3484
4037
|
var debugactions = /* @__PURE__ */ new Set(["watchconsole", "watcherrors", "watchtasks"]);
|
|
3485
4038
|
var cdpactions = /* @__PURE__ */ new Set(["attachcdp", "detachcdp", "cdpcmd", "watchcdp", "setbreakpoint", "stepcode", "watchexpr", "overridescript"]);
|
|
3486
4039
|
var profileractions = /* @__PURE__ */ new Set(["measureflow", "heapshot", "trackmemory", "profilecpu", "watchshifts", "traceload", "annotatetrace", "replaytrace", "capturesourcemaps"]);
|
|
4040
|
+
var emulationactions = /* @__PURE__ */ new Set(["emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission", "blackboxscripts"]);
|
|
4041
|
+
var sessionactions = /* @__PURE__ */ new Set(["persiststate", "capturesession", "restoresession", "namedsessions", "diffsessions", "searchsessions", "exportsessions", "importsessions"]);
|
|
3487
4042
|
var credentialheaders = /* @__PURE__ */ new Set(["authorization", "proxy-authorization", "cookie", "cookie2", "set-cookie", "api-key", "x-api-key", "x-auth-token", "x-session-token", "proxy-authorization"]);
|
|
3488
4043
|
var fieldkinds = ["text", "email", "phone", "date", "number", "select", "check", "radio", "file", "password", "card", "code"];
|
|
3489
4044
|
var layoutmutationactions = /* @__PURE__ */ new Set(["grouptabs", "colorgroup", "collapsegroup", "savelayout", "restorelayout"]);
|
|
@@ -3499,6 +4054,9 @@ function hostpattern(origin) {
|
|
|
3499
4054
|
if (parsed.protocol !== "https:") throw new Error("Only HTTPS origins can be granted.");
|
|
3500
4055
|
return `${parsed.origin}/*`;
|
|
3501
4056
|
}
|
|
4057
|
+
function issessionkind(kind) {
|
|
4058
|
+
return sessionactions.has(kind);
|
|
4059
|
+
}
|
|
3502
4060
|
function iswatchkind(kind) {
|
|
3503
4061
|
return watchactions.has(kind);
|
|
3504
4062
|
}
|
|
@@ -3511,6 +4069,9 @@ function iscdpkind(kind) {
|
|
|
3511
4069
|
function isprofilekind(kind) {
|
|
3512
4070
|
return profileractions.has(kind);
|
|
3513
4071
|
}
|
|
4072
|
+
function isemulationkind(kind) {
|
|
4073
|
+
return emulationactions.has(kind);
|
|
4074
|
+
}
|
|
3514
4075
|
function observationmodeof(kind) {
|
|
3515
4076
|
if (watchactions.has(kind) || debugactions.has(kind) || profileractions.has(kind) && kind !== "heapshot" && kind !== "replaytrace" && kind !== "annotatetrace" && kind !== "capturesourcemaps" && kind !== "profilecpu" || cdpactions.has(kind) && kind === "watchcdp" || kind === "waitquiet") return "watching";
|
|
3516
4077
|
if (kind === "diffsnapshots") return "diffing";
|
|
@@ -4795,6 +5356,176 @@ function pauseretentionwindow(settings) {
|
|
|
4795
5356
|
function breakpointceilingof(settings) {
|
|
4796
5357
|
return settings?.breakpointceiling;
|
|
4797
5358
|
}
|
|
5359
|
+
function emugate(input) {
|
|
5360
|
+
const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: "emulate the run tab" });
|
|
5361
|
+
if (!gate.allowed) return gate;
|
|
5362
|
+
if (!input.plan || input.plan.state !== "approved") return { allowed: false, reason: "Emulation layers need an approved plan before they apply." };
|
|
5363
|
+
let options = {};
|
|
5364
|
+
try {
|
|
5365
|
+
options = parseoptions(input.step);
|
|
5366
|
+
} catch {
|
|
5367
|
+
options = {};
|
|
5368
|
+
}
|
|
5369
|
+
if (options.reviewed !== true) return { allowed: false, reason: `The ${input.step.kind} layer needs the explicit reviewed flag before any mask applies.` };
|
|
5370
|
+
if (revertplanof(options.revertplan) === void 0) return { allowed: false, reason: `Every ${input.step.kind} layer needs a reviewed revert plan beside it before any mask applies.` };
|
|
5371
|
+
return { allowed: true };
|
|
5372
|
+
}
|
|
5373
|
+
function emulationstackallowed(plan, kind, active) {
|
|
5374
|
+
if (!plan) return { allowed: false, reason: "Layer stacking needs the reviewed plan first." };
|
|
5375
|
+
const listed = plan.steps.filter((step) => step.kind === kind).length;
|
|
5376
|
+
if (active >= listed) return { allowed: false, reason: `The plan lists ${listed} reviewed ${kind} step${listed === 1 ? "" : "s"} and ${active} layer${active === 1 ? "" : "s"} of that family are already active; stacking beyond the reviewed plan is refused.` };
|
|
5377
|
+
return { allowed: true };
|
|
5378
|
+
}
|
|
5379
|
+
function locationconsentgate(origin, latitude, longitude, consents) {
|
|
5380
|
+
if (consents.some((consent) => consent.origin === origin && consent.revokedat !== void 0)) return { allowed: false, reason: `The location consent on ${origin} was revoked; approve a new prompt before the location override runs again.` };
|
|
5381
|
+
if (locationconsentcovers(origin, latitude, longitude, consents)) return { allowed: true };
|
|
5382
|
+
return { allowed: false, reason: `The location override of ${latitude}, ${longitude} on ${origin} needs the reviewed location consent first; approve the prompt with the coordinates shown in the review panel.` };
|
|
5383
|
+
}
|
|
5384
|
+
function emulationretentionwindow(settings) {
|
|
5385
|
+
return settings?.emulationretention;
|
|
5386
|
+
}
|
|
5387
|
+
function validateemulationgrammar(step, options) {
|
|
5388
|
+
const kind = step.kind;
|
|
5389
|
+
if (revertplanof(options.revertplan) === void 0) return { allowed: false, reason: `Every ${kind} layer needs a reviewed revert plan before any mask applies.` };
|
|
5390
|
+
if (kind === "emulatedevice") {
|
|
5391
|
+
const preset = devicepresetof(options.device);
|
|
5392
|
+
if (!preset) return { allowed: false, reason: "The device layer needs a reviewed preset with a name, positive integer width and height and a positive pixel ratio." };
|
|
5393
|
+
if (options.reload !== void 0 && typeof options.reload !== "boolean") return { allowed: false, reason: "The reviewed reload flag must be a boolean; the page reloads only when the reviewed plan asks." };
|
|
5394
|
+
return { allowed: true };
|
|
5395
|
+
}
|
|
5396
|
+
if (kind === "emulatenetwork") {
|
|
5397
|
+
const preset = networkpresetof(options.network);
|
|
5398
|
+
if (!preset) return { allowed: false, reason: "The network layer needs a reviewed preset with a name and zero or positive latency, download and upload bounds." };
|
|
5399
|
+
if (options.window !== void 0 && (typeof options.window !== "number" || !Number.isFinite(options.window) || options.window < 0)) return { allowed: false, reason: "The reviewed offline window must be zero or a positive number of milliseconds with no code ceiling." };
|
|
5400
|
+
return { allowed: true };
|
|
5401
|
+
}
|
|
5402
|
+
if (kind === "emulatelocate") {
|
|
5403
|
+
const preset = locationpresetof(options.location);
|
|
5404
|
+
if (!preset) return { allowed: false, reason: "The location layer needs a reviewed preset with a name, a latitude inside -90 and 90, a longitude inside -180 and 180 and a zero or positive accuracy radius." };
|
|
5405
|
+
if (!locationrangevalid(preset.latitude, preset.longitude)) return { allowed: false, reason: "The reviewed latitude must stay inside -90 and 90 degrees and the longitude inside -180 and 180 degrees." };
|
|
5406
|
+
return { allowed: true };
|
|
5407
|
+
}
|
|
5408
|
+
if (kind === "setuseragent") {
|
|
5409
|
+
const preset = agentpresetof(options.agent);
|
|
5410
|
+
if (!preset) return { allowed: false, reason: "The agent layer needs a reviewed preset with a user agent string of the reviewed grammar, a platform and a non-empty brand list." };
|
|
5411
|
+
if (!agentgrammarvalid(preset.useragent)) return { allowed: false, reason: "The reviewed user agent string must use the reviewed grammar of tokens, separators and version marks without line breaks." };
|
|
5412
|
+
return { allowed: true };
|
|
5413
|
+
}
|
|
5414
|
+
if (kind === "overridepermission") {
|
|
5415
|
+
const grant = permissiongrantof(options.permission);
|
|
5416
|
+
if (!grant) return { allowed: false, reason: `The permission override needs a reviewed name of the browser permission set (${browserpermissions.join(", ")}) and a state of ${permissionstates.join(", ")}.` };
|
|
5417
|
+
void permissiongrade(grant.name);
|
|
5418
|
+
return { allowed: true };
|
|
5419
|
+
}
|
|
5420
|
+
if (kind === "blackboxscripts") {
|
|
5421
|
+
const rules = Array.isArray(options.rules) ? options.rules.flatMap((rule) => {
|
|
5422
|
+
const parsed = blackboxruleof(rule);
|
|
5423
|
+
return parsed !== void 0 ? [parsed] : [];
|
|
5424
|
+
}) : [];
|
|
5425
|
+
if (rules.length === 0) return { allowed: false, reason: "The blackbox layer needs a reviewed non-empty rule list where every pattern names its origin explicitly and carries a trace scope." };
|
|
5426
|
+
return { allowed: true };
|
|
5427
|
+
}
|
|
5428
|
+
return { allowed: true };
|
|
5429
|
+
}
|
|
5430
|
+
function permissionnamevalid(name) {
|
|
5431
|
+
if (!browserpermissions.includes(name)) return { allowed: false, reason: `The permission ${name} stays outside the reviewed browser permission set: ${browserpermissions.join(", ")}.` };
|
|
5432
|
+
return { allowed: true };
|
|
5433
|
+
}
|
|
5434
|
+
function validatesessiongrammar(step, options) {
|
|
5435
|
+
const kind = step.kind;
|
|
5436
|
+
if (kind === "persiststate") {
|
|
5437
|
+
if (options.resume !== void 0 && typeof options.resume !== "boolean") return { allowed: false, reason: "The reviewed resume flag must be a boolean." };
|
|
5438
|
+
return { allowed: true };
|
|
5439
|
+
}
|
|
5440
|
+
if (kind === "capturesession") {
|
|
5441
|
+
const plan = snapshotplanof(options.snapshot);
|
|
5442
|
+
if (!plan) return { allowed: false, reason: "The session capture needs a reviewed snapshot plan with its scope, a non-empty section list of the reviewed grammar (tabs, scroll, forms, storage, cookies) and the capture link flag." };
|
|
5443
|
+
if (plan.auto !== void 0) {
|
|
5444
|
+
const interval = autointervalof(options.snapshot.auto);
|
|
5445
|
+
if (interval === void 0) return { allowed: false, reason: "The reviewed auto snapshot interval needs a positive period, a positive maximum snapshot count and a zero or positive expiry window with no code ceiling." };
|
|
5446
|
+
}
|
|
5447
|
+
return { allowed: true };
|
|
5448
|
+
}
|
|
5449
|
+
if (kind === "restoresession") {
|
|
5450
|
+
if (typeof options.sessionid !== "string" || !options.sessionid.trim()) return { allowed: false, reason: "The session restore needs the reviewed session id of the saved record." };
|
|
5451
|
+
if (restoreplanof(options.restore) === void 0) return { allowed: false, reason: "The session restore needs a reviewed restore plan with its tab, form and capture policies." };
|
|
5452
|
+
if (options.reviewed !== true) return { allowed: false, reason: "Every session restore needs the explicit restore review with its tabs, form state and captures listed before it reopens anything." };
|
|
5453
|
+
return { allowed: true };
|
|
5454
|
+
}
|
|
5455
|
+
if (kind === "namedsessions") {
|
|
5456
|
+
if (typeof options.sessionid !== "string" || !options.sessionid.trim()) return { allowed: false, reason: "The session filing needs the reviewed session id of the saved record." };
|
|
5457
|
+
if (typeof options.name !== "string" || !options.name.trim()) return { allowed: false, reason: "The session filing needs a reviewed non-empty session name." };
|
|
5458
|
+
if (options.folder !== void 0 && (typeof options.folder !== "string" || !options.folder.trim())) return { allowed: false, reason: "The reviewed folder name must be a non-empty string." };
|
|
5459
|
+
if (options.tags !== void 0 && (!Array.isArray(options.tags) || !options.tags.every((tag) => typeof tag === "string" && tag.trim()))) return { allowed: false, reason: "The reviewed tag list must be a list of non-empty strings." };
|
|
5460
|
+
return { allowed: true };
|
|
5461
|
+
}
|
|
5462
|
+
if (kind === "diffsessions") {
|
|
5463
|
+
if (typeof options.left !== "string" || !options.left.trim() || typeof options.right !== "string" || !options.right.trim()) return { allowed: false, reason: "The session diff needs the reviewed ids of both saved sessions." };
|
|
5464
|
+
return { allowed: true };
|
|
5465
|
+
}
|
|
5466
|
+
if (kind === "searchsessions") {
|
|
5467
|
+
if (searchqueryof(options.query) === void 0) return { allowed: false, reason: "The session search needs a reviewed query with a non-empty term list, fields of the reviewed grammar (urls, titles, names, text) and an optional time window." };
|
|
5468
|
+
return { allowed: true };
|
|
5469
|
+
}
|
|
5470
|
+
if (kind === "exportsessions") {
|
|
5471
|
+
if (options.reviewed !== true) return { allowed: false, reason: "Session exports need the explicit export review before any session file leaves the device." };
|
|
5472
|
+
if (options.ids !== void 0 && (!Array.isArray(options.ids) || options.ids.length === 0 || !options.ids.every((id) => typeof id === "string" && id.trim()))) return { allowed: false, reason: "The reviewed export id list must be a non-empty list of saved session ids." };
|
|
5473
|
+
return { allowed: true };
|
|
5474
|
+
}
|
|
5475
|
+
if (kind === "importsessions") {
|
|
5476
|
+
if (options.reviewed !== true) return { allowed: false, reason: "Session imports need the explicit full record review before any record joins the library." };
|
|
5477
|
+
if (importsessionfile(options.file) === void 0) return { allowed: false, reason: "The session import needs a reviewed file of the known format version with an intact checksum." };
|
|
5478
|
+
return { allowed: true };
|
|
5479
|
+
}
|
|
5480
|
+
return { allowed: true };
|
|
5481
|
+
}
|
|
5482
|
+
function restorereviewgranted(step) {
|
|
5483
|
+
let options = {};
|
|
5484
|
+
try {
|
|
5485
|
+
options = parseoptions(step);
|
|
5486
|
+
} catch {
|
|
5487
|
+
options = {};
|
|
5488
|
+
}
|
|
5489
|
+
if (restoreplanof(options.restore) === void 0) return { allowed: false, reason: "Every session restore needs a reviewed restore plan with its tab, form and capture policies." };
|
|
5490
|
+
if (options.reviewed !== true) return { allowed: false, reason: "The session restore needs the explicit restore review of its tabs, form state and captures before it reopens anything." };
|
|
5491
|
+
return { allowed: true };
|
|
5492
|
+
}
|
|
5493
|
+
function sessionrestoregate(input) {
|
|
5494
|
+
const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: "run the session memory step" });
|
|
5495
|
+
if (!gate.allowed) return gate;
|
|
5496
|
+
if (!input.plan || input.plan.state !== "approved") return { allowed: false, reason: "Session memory steps need an approved plan before they run." };
|
|
5497
|
+
if (input.step.kind === "restoresession") return restorereviewgranted(input.step);
|
|
5498
|
+
return { allowed: true };
|
|
5499
|
+
}
|
|
5500
|
+
function restoreoriginsgranted(urls, grants) {
|
|
5501
|
+
const covered = new Set(grants);
|
|
5502
|
+
const skippedorigins = [];
|
|
5503
|
+
for (const url of urls) {
|
|
5504
|
+
let origin = "";
|
|
5505
|
+
try {
|
|
5506
|
+
origin = new URL(url).origin;
|
|
5507
|
+
} catch {
|
|
5508
|
+
origin = "";
|
|
5509
|
+
}
|
|
5510
|
+
if (!origin || !covered.has(origin)) skippedorigins.push(origin || url);
|
|
5511
|
+
}
|
|
5512
|
+
return { allowed: skippedorigins.length === 0, skippedorigins: [...new Set(skippedorigins)] };
|
|
5513
|
+
}
|
|
5514
|
+
function sessionnameunique(name, records, recordid) {
|
|
5515
|
+
if (records.some((record2) => record2.name === name && record2.id !== recordid)) return { allowed: false, reason: `The session name ${name} already exists in the library; review a unique name.` };
|
|
5516
|
+
return { allowed: true };
|
|
5517
|
+
}
|
|
5518
|
+
function sessionfolderunique(name, folders) {
|
|
5519
|
+
if (folders.some((folder) => folder.name === name)) return { allowed: false, reason: `The folder name ${name} already exists in the library; review a unique folder name.` };
|
|
5520
|
+
return { allowed: true };
|
|
5521
|
+
}
|
|
5522
|
+
function snapshotretentionwindow(settings) {
|
|
5523
|
+
return settings?.sessionretention;
|
|
5524
|
+
}
|
|
5525
|
+
function permissionstatevalid(state) {
|
|
5526
|
+
if (!permissionstates.includes(state)) return { allowed: false, reason: `The reviewed permission state must be one of ${permissionstates.join(", ")}.` };
|
|
5527
|
+
return { allowed: true };
|
|
5528
|
+
}
|
|
4798
5529
|
function validatecdpgrammar(step, options) {
|
|
4799
5530
|
const kind = step.kind;
|
|
4800
5531
|
if (kind === "attachcdp") {
|
|
@@ -5352,6 +6083,14 @@ function validatestep(step, origin) {
|
|
|
5352
6083
|
const profilecheck = validateprofilegrammar(step, options);
|
|
5353
6084
|
if (!profilecheck.allowed) return profilecheck;
|
|
5354
6085
|
}
|
|
6086
|
+
if (isemulationkind(step.kind)) {
|
|
6087
|
+
const emulationcheck = validateemulationgrammar(step, options);
|
|
6088
|
+
if (!emulationcheck.allowed) return emulationcheck;
|
|
6089
|
+
}
|
|
6090
|
+
if (issessionkind(step.kind)) {
|
|
6091
|
+
const sessioncheck = validatesessiongrammar(step, options);
|
|
6092
|
+
if (!sessioncheck.allowed) return sessioncheck;
|
|
6093
|
+
}
|
|
5355
6094
|
if (step.kind === "tabcreate") {
|
|
5356
6095
|
if (options.background !== void 0 && typeof options.background !== "boolean") return { allowed: false, reason: "The reviewed background flag must be a boolean." };
|
|
5357
6096
|
if (options.window !== void 0 && (typeof options.window !== "number" || !Number.isInteger(options.window) || options.window < 0)) return { allowed: false, reason: "The reviewed target window id must be a non-negative integer." };
|
|
@@ -5521,6 +6260,27 @@ function canexecute(input) {
|
|
|
5521
6260
|
}
|
|
5522
6261
|
}
|
|
5523
6262
|
}
|
|
6263
|
+
if (isemulationkind(input.step.kind)) {
|
|
6264
|
+
const emugatecheck = emugate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });
|
|
6265
|
+
if (!emugatecheck.allowed) return emugatecheck;
|
|
6266
|
+
}
|
|
6267
|
+
if (issessionkind(input.step.kind)) {
|
|
6268
|
+
const sessiongatecheck = sessionrestoregate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });
|
|
6269
|
+
if (!sessiongatecheck.allowed) return sessiongatecheck;
|
|
6270
|
+
if (input.step.kind === "restoresession") {
|
|
6271
|
+
let restoreoptions = {};
|
|
6272
|
+
try {
|
|
6273
|
+
restoreoptions = parseoptions(input.step);
|
|
6274
|
+
} catch {
|
|
6275
|
+
restoreoptions = {};
|
|
6276
|
+
}
|
|
6277
|
+
for (const url of Array.isArray(restoreoptions.origins) ? restoreoptions.origins : []) {
|
|
6278
|
+
if (typeof url !== "string" || !url) continue;
|
|
6279
|
+
const origingate = origincheck(input.session, url);
|
|
6280
|
+
if (!origingate.allowed) return { allowed: false, reason: `The session restore reopens ${url} outside the session origin grants; review the restore record or grant the origin.` };
|
|
6281
|
+
}
|
|
6282
|
+
}
|
|
6283
|
+
}
|
|
5524
6284
|
if (iscontrolkind(input.step.kind)) {
|
|
5525
6285
|
const controlgate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: "control the network" });
|
|
5526
6286
|
if (!controlgate.allowed) return controlgate;
|
|
@@ -5604,7 +6364,7 @@ function canexecute(input) {
|
|
|
5604
6364
|
}
|
|
5605
6365
|
|
|
5606
6366
|
// version.ts
|
|
5607
|
-
var packageversion = "1.1.
|
|
6367
|
+
var packageversion = "1.1.49";
|
|
5608
6368
|
|
|
5609
6369
|
// types.ts
|
|
5610
6370
|
var protocolversion = packageversion;
|
|
@@ -5776,6 +6536,50 @@ function parseproposal(value, origin, grants) {
|
|
|
5776
6536
|
}
|
|
5777
6537
|
if (step.kind === "annotatetrace" && (!Array.isArray(profileoptions.annotations) || profileoptions.annotations.length === 0 || !profileoptions.annotations.every((annotation) => annotationof(annotation) !== void 0))) throw new Error("Trace annotation steps without reviewed step annotations are refused.");
|
|
5778
6538
|
}
|
|
6539
|
+
if (isemulationkind(step.kind)) {
|
|
6540
|
+
const granted = covered.some((pattern) => {
|
|
6541
|
+
try {
|
|
6542
|
+
return new URL(origin).origin === new URL(pattern).origin;
|
|
6543
|
+
} catch {
|
|
6544
|
+
return false;
|
|
6545
|
+
}
|
|
6546
|
+
});
|
|
6547
|
+
if (!granted) throw new Error(`The ${step.kind} step of ${origin} targets an origin outside the grants.`);
|
|
6548
|
+
let emulationoptions = {};
|
|
6549
|
+
try {
|
|
6550
|
+
emulationoptions = parseoptions(step);
|
|
6551
|
+
} catch {
|
|
6552
|
+
emulationoptions = {};
|
|
6553
|
+
}
|
|
6554
|
+
if (revertplanof(emulationoptions.revertplan) === void 0) throw new Error("Emulation steps without a reviewed revert plan are refused.");
|
|
6555
|
+
if (step.kind === "emulatelocate") {
|
|
6556
|
+
const preset = locationpresetof(emulationoptions.location);
|
|
6557
|
+
if (preset === void 0) throw new Error("Location emulation needs a reviewed preset with coordinates inside the latitude and longitude ranges.");
|
|
6558
|
+
}
|
|
6559
|
+
if (step.kind === "overridepermission" && permissiongrantof(emulationoptions.permission) === void 0) throw new Error("Permission overrides of unknown permission names are refused.");
|
|
6560
|
+
}
|
|
6561
|
+
if (issessionkind(step.kind)) {
|
|
6562
|
+
let sessionoptions = {};
|
|
6563
|
+
try {
|
|
6564
|
+
sessionoptions = parseoptions(step);
|
|
6565
|
+
} catch {
|
|
6566
|
+
sessionoptions = {};
|
|
6567
|
+
}
|
|
6568
|
+
if (step.kind === "restoresession") {
|
|
6569
|
+
for (const url of Array.isArray(sessionoptions.origins) ? sessionoptions.origins : []) {
|
|
6570
|
+
if (typeof url !== "string" || !url) continue;
|
|
6571
|
+
const granted = covered.some((pattern) => {
|
|
6572
|
+
try {
|
|
6573
|
+
return new URL(url).origin === new URL(pattern).origin;
|
|
6574
|
+
} catch {
|
|
6575
|
+
return false;
|
|
6576
|
+
}
|
|
6577
|
+
});
|
|
6578
|
+
if (!granted) throw new Error(`The session restore reopens ${url} outside the grants.`);
|
|
6579
|
+
}
|
|
6580
|
+
}
|
|
6581
|
+
if (step.kind === "importsessions" && importsessionfile(sessionoptions.file) === void 0) throw new Error("Session import files of unknown format versions are refused.");
|
|
6582
|
+
}
|
|
5779
6583
|
const evaluation = validatestep(step, origin);
|
|
5780
6584
|
if (!evaluation.allowed) throw new Error(evaluation.reason);
|
|
5781
6585
|
const target = outboundtarget(step);
|
|
@@ -5850,7 +6654,7 @@ function requestbody(input) {
|
|
|
5850
6654
|
return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation, capabilities: input.capabilities });
|
|
5851
6655
|
}
|
|
5852
6656
|
function outcomeresponse(input) {
|
|
5853
|
-
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {}, ...input.media ? { media: input.media } : {}, ...input.transport ? { transport: input.transport } : {}, ...input.network ? { network: input.network } : {}, ...input.control ? { control: input.control } : {}, ...input.timeline ? { timeline: input.timeline } : {}, ...input.cdp ? { cdp: input.cdp } : {}, ...input.profile ? { profile: input.profile } : {} });
|
|
6657
|
+
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {}, ...input.media ? { media: input.media } : {}, ...input.transport ? { transport: input.transport } : {}, ...input.network ? { network: input.network } : {}, ...input.control ? { control: input.control } : {}, ...input.timeline ? { timeline: input.timeline } : {}, ...input.cdp ? { cdp: input.cdp } : {}, ...input.profile ? { profile: input.profile } : {}, ...input.emulation ? { emulation: input.emulation } : {}, ...input.session ? { session: input.session } : {} });
|
|
5854
6658
|
}
|
|
5855
6659
|
function mapresponse(input) {
|
|
5856
6660
|
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, map: input.map });
|
|
@@ -5988,7 +6792,21 @@ function profilereport(input) {
|
|
|
5988
6792
|
});
|
|
5989
6793
|
return { version: protocolversion, flows: input.flows, heaps: input.heaps, samples: input.samples, trends: input.trends, profiles: input.profiles, shifts: input.shifts, traces: input.traces, sourcemaps: input.sourcemaps, consents };
|
|
5990
6794
|
}
|
|
6795
|
+
function emulationreport(input) {
|
|
6796
|
+
const consents = input.consents.map((consent) => {
|
|
6797
|
+
const { prompt, ...metadata } = consent;
|
|
6798
|
+
void prompt;
|
|
6799
|
+
return metadata;
|
|
6800
|
+
});
|
|
6801
|
+
return { version: protocolversion, ...input.state !== void 0 ? { state: input.state } : {}, layers: input.state?.layers ?? [], devices: input.devices, networks: input.networks, locations: input.locations, agents: input.agents, blackbox: input.blackbox, permissions: input.permissions, consents };
|
|
6802
|
+
}
|
|
6803
|
+
function sessionreport(input) {
|
|
6804
|
+
return { version: protocolversion, records: input.records, events: input.events, folders: input.folders, diffs: input.diffs, ...input.auto !== void 0 ? { auto: input.auto } : {}, ...input.crashed === true ? { crashed: true } : {} };
|
|
6805
|
+
}
|
|
5991
6806
|
export {
|
|
6807
|
+
activelayers,
|
|
6808
|
+
agentgrammarvalid,
|
|
6809
|
+
agentpresetof,
|
|
5992
6810
|
allowlistcovers,
|
|
5993
6811
|
annotatetrace,
|
|
5994
6812
|
annotationof,
|
|
@@ -5997,6 +6815,7 @@ export {
|
|
|
5997
6815
|
apikeyconsentgranted,
|
|
5998
6816
|
apireplayspecof,
|
|
5999
6817
|
applyheaderules,
|
|
6818
|
+
applylayer,
|
|
6000
6819
|
argkind,
|
|
6001
6820
|
assetentries,
|
|
6002
6821
|
attachcdpsession,
|
|
@@ -6005,6 +6824,10 @@ export {
|
|
|
6005
6824
|
authconsentgranted,
|
|
6006
6825
|
authorizeurl,
|
|
6007
6826
|
authreport,
|
|
6827
|
+
autointervalof,
|
|
6828
|
+
blackboxedurls,
|
|
6829
|
+
blackboxmatches,
|
|
6830
|
+
blackboxruleof,
|
|
6008
6831
|
blendrows,
|
|
6009
6832
|
blockgate,
|
|
6010
6833
|
blockingduration,
|
|
@@ -6014,6 +6837,7 @@ export {
|
|
|
6014
6837
|
breakpointbudgetallowed,
|
|
6015
6838
|
breakpointceilingof,
|
|
6016
6839
|
breakpointinputof,
|
|
6840
|
+
browserpermissions,
|
|
6017
6841
|
buildname,
|
|
6018
6842
|
buildpdf,
|
|
6019
6843
|
buildsheet,
|
|
@@ -6059,6 +6883,7 @@ export {
|
|
|
6059
6883
|
cookierecordof,
|
|
6060
6884
|
correlationid,
|
|
6061
6885
|
cpusnap,
|
|
6886
|
+
crashinterrupted,
|
|
6062
6887
|
croprect,
|
|
6063
6888
|
crossesviewport,
|
|
6064
6889
|
cursorfrom,
|
|
@@ -6069,19 +6894,33 @@ export {
|
|
|
6069
6894
|
dedupeimages,
|
|
6070
6895
|
actionrisk as deriveactionrisk,
|
|
6071
6896
|
detachcdpsession,
|
|
6897
|
+
devicepresetof,
|
|
6072
6898
|
diffresponse,
|
|
6073
6899
|
diffreviewgrade,
|
|
6900
|
+
diffsessionrecords,
|
|
6074
6901
|
downloadreport,
|
|
6902
|
+
emugate,
|
|
6903
|
+
emulationkinds,
|
|
6904
|
+
emulationreport,
|
|
6905
|
+
emulationretentionwindow,
|
|
6906
|
+
emulationstackallowed,
|
|
6907
|
+
emulationstateof,
|
|
6075
6908
|
errorcapture,
|
|
6076
6909
|
errorreportresponse,
|
|
6077
6910
|
eventresponse,
|
|
6078
6911
|
exchangesreport,
|
|
6912
|
+
expirelayers,
|
|
6079
6913
|
expireprofilerecords,
|
|
6914
|
+
expiresessions,
|
|
6915
|
+
exportpresetlibrary,
|
|
6916
|
+
exportsessionfile,
|
|
6080
6917
|
extractionreport,
|
|
6081
6918
|
extractvalues,
|
|
6082
6919
|
failureclass,
|
|
6920
|
+
familyofkind,
|
|
6083
6921
|
fetchoptionsof,
|
|
6084
6922
|
fetchrequestof,
|
|
6923
|
+
filteredsessions,
|
|
6085
6924
|
filterentries,
|
|
6086
6925
|
filterexchanges,
|
|
6087
6926
|
finishrecording,
|
|
@@ -6101,25 +6940,35 @@ export {
|
|
|
6101
6940
|
heapintervalallowed,
|
|
6102
6941
|
heapsnap,
|
|
6103
6942
|
heldkeysreport,
|
|
6943
|
+
hideblackboxedframes,
|
|
6104
6944
|
hostpattern,
|
|
6105
6945
|
htmlqueriesof,
|
|
6106
6946
|
httpkinds,
|
|
6107
6947
|
imagefilterof,
|
|
6108
6948
|
imagematches,
|
|
6109
6949
|
imagenames,
|
|
6950
|
+
importpresetlibrary,
|
|
6951
|
+
importsessionfile,
|
|
6110
6952
|
iscdpkind,
|
|
6111
6953
|
iscontrolkind,
|
|
6112
6954
|
isdebugkind,
|
|
6955
|
+
isemulationkind,
|
|
6113
6956
|
isformkind,
|
|
6114
6957
|
isnetwatchkind,
|
|
6115
6958
|
isprofilekind,
|
|
6959
|
+
issessionkind,
|
|
6116
6960
|
issocketkind,
|
|
6117
6961
|
iswatchkind,
|
|
6118
6962
|
jsonpathrulesof,
|
|
6119
6963
|
lapseframes,
|
|
6120
6964
|
lapseplanof,
|
|
6965
|
+
layernames,
|
|
6121
6966
|
layoutreport,
|
|
6122
6967
|
levelrank,
|
|
6968
|
+
locationconsentcovers,
|
|
6969
|
+
locationconsentgate,
|
|
6970
|
+
locationpresetof,
|
|
6971
|
+
locationrangevalid,
|
|
6123
6972
|
loglevels,
|
|
6124
6973
|
longtaskcapture,
|
|
6125
6974
|
mapresponse,
|
|
@@ -6140,12 +6989,16 @@ export {
|
|
|
6140
6989
|
netfailureentryof,
|
|
6141
6990
|
netlogreport,
|
|
6142
6991
|
netwatchkinds,
|
|
6992
|
+
networkpresetof,
|
|
6143
6993
|
newblockrule,
|
|
6144
6994
|
newchannel,
|
|
6145
6995
|
newexchange,
|
|
6146
6996
|
newheaderule,
|
|
6997
|
+
newlayer,
|
|
6147
6998
|
newmockspec,
|
|
6148
6999
|
newrecording,
|
|
7000
|
+
newsessiondiff,
|
|
7001
|
+
newsessionrecord,
|
|
6149
7002
|
normalizeendpoint,
|
|
6150
7003
|
oauthflowof,
|
|
6151
7004
|
observationmodeof,
|
|
@@ -6170,6 +7023,11 @@ export {
|
|
|
6170
7023
|
pdfpagesize,
|
|
6171
7024
|
pdfsegments,
|
|
6172
7025
|
pdftextlayout,
|
|
7026
|
+
permissiongrade,
|
|
7027
|
+
permissiongrantof,
|
|
7028
|
+
permissionnamevalid,
|
|
7029
|
+
permissionstates,
|
|
7030
|
+
permissionstatevalid,
|
|
6173
7031
|
planallowlist,
|
|
6174
7032
|
pollcursorof,
|
|
6175
7033
|
polldecision,
|
|
@@ -6206,7 +7064,13 @@ export {
|
|
|
6206
7064
|
resolutionverdict,
|
|
6207
7065
|
resolvedrisk,
|
|
6208
7066
|
resourcefacts,
|
|
7067
|
+
restoreoriginsgranted,
|
|
7068
|
+
restoreplanof,
|
|
7069
|
+
restorereviewgranted,
|
|
6209
7070
|
retryafterof,
|
|
7071
|
+
revertalllayers,
|
|
7072
|
+
revertlayer,
|
|
7073
|
+
revertplanof,
|
|
6210
7074
|
revertrule,
|
|
6211
7075
|
revocationruleof,
|
|
6212
7076
|
rewritesourcelocation,
|
|
@@ -6215,21 +7079,36 @@ export {
|
|
|
6215
7079
|
safetyresponse,
|
|
6216
7080
|
scaledrect,
|
|
6217
7081
|
seamweights,
|
|
7082
|
+
searchfields,
|
|
7083
|
+
searchqueryof,
|
|
7084
|
+
searchsessionrecords,
|
|
6218
7085
|
selectorresponse,
|
|
6219
7086
|
sendcdpcommand,
|
|
6220
7087
|
sendfetch,
|
|
6221
7088
|
sequenceintegrity,
|
|
6222
7089
|
serializearg,
|
|
6223
7090
|
serializecdpcommand,
|
|
7091
|
+
sessionfileversion,
|
|
7092
|
+
sessionfolderof,
|
|
7093
|
+
sessionfolderunique,
|
|
7094
|
+
sessionkinds,
|
|
6224
7095
|
sessionmemory,
|
|
7096
|
+
sessionnameunique,
|
|
7097
|
+
sessionreport,
|
|
7098
|
+
sessionrestoregate,
|
|
7099
|
+
sessiontabof,
|
|
6225
7100
|
shiftentryof,
|
|
6226
7101
|
signalsreport,
|
|
7102
|
+
snapshotplanof,
|
|
7103
|
+
snapshotretentionwindow,
|
|
7104
|
+
snapshotsections,
|
|
6227
7105
|
socketgate,
|
|
6228
7106
|
socketkinds,
|
|
6229
7107
|
sourcemapconsentcovers,
|
|
6230
7108
|
spamdetect,
|
|
6231
7109
|
spamruleof,
|
|
6232
7110
|
sserequestheaders,
|
|
7111
|
+
stackedcount,
|
|
6233
7112
|
stackframes,
|
|
6234
7113
|
stackgate,
|
|
6235
7114
|
statusclassof,
|
|
@@ -6241,6 +7120,9 @@ export {
|
|
|
6241
7120
|
subscriptionoptionsof,
|
|
6242
7121
|
tabreportresponse,
|
|
6243
7122
|
targetgate,
|
|
7123
|
+
taskstatechecksum,
|
|
7124
|
+
taskstateof,
|
|
7125
|
+
taskstatevalid,
|
|
6244
7126
|
teardowncdpsession,
|
|
6245
7127
|
teardownplanof,
|
|
6246
7128
|
templateurl,
|