@flrande/bak-extension 0.3.8 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.bak-e2e-build-stamp +1 -1
- package/dist/background.global.js +169 -111
- package/dist/content.global.js +29 -0
- package/dist/manifest.json +1 -1
- package/package.json +2 -2
- package/public/manifest.json +1 -1
- package/src/background.ts +1178 -1157
- package/src/content.ts +1778 -1747
- package/src/session-binding-storage.ts +68 -0
- package/src/workspace.ts +912 -917
|
@@ -1 +1 @@
|
|
|
1
|
-
2026-03-
|
|
1
|
+
2026-03-11T07:35:54.292Z
|
|
@@ -30,26 +30,79 @@
|
|
|
30
30
|
return Math.min(maxDelayMs, baseDelayMs * 2 ** safeAttempt);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// src/session-binding-storage.ts
|
|
34
|
+
var STORAGE_KEY_SESSION_BINDINGS = "sessionBindings";
|
|
35
|
+
var LEGACY_STORAGE_KEY_WORKSPACES = "agentWorkspaces";
|
|
36
|
+
var LEGACY_STORAGE_KEY_WORKSPACE = "agentWorkspace";
|
|
37
|
+
function isWorkspaceRecord(value) {
|
|
38
|
+
if (typeof value !== "object" || value === null) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const candidate = value;
|
|
42
|
+
return typeof candidate.id === "string" && Array.isArray(candidate.tabIds) && (typeof candidate.windowId === "number" || candidate.windowId === null) && (typeof candidate.groupId === "number" || candidate.groupId === null) && (typeof candidate.activeTabId === "number" || candidate.activeTabId === null) && (typeof candidate.primaryTabId === "number" || candidate.primaryTabId === null);
|
|
43
|
+
}
|
|
44
|
+
function cloneWorkspaceRecord(state) {
|
|
45
|
+
return {
|
|
46
|
+
...state,
|
|
47
|
+
tabIds: [...state.tabIds]
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function normalizeWorkspaceRecordMap(value) {
|
|
51
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
52
|
+
return {
|
|
53
|
+
found: false,
|
|
54
|
+
map: {}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const normalizedEntries = [];
|
|
58
|
+
for (const [workspaceId, entry] of Object.entries(value)) {
|
|
59
|
+
if (!isWorkspaceRecord(entry)) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
normalizedEntries.push([workspaceId, cloneWorkspaceRecord(entry)]);
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
found: true,
|
|
66
|
+
map: Object.fromEntries(normalizedEntries)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function resolveSessionBindingStateMap(stored) {
|
|
70
|
+
const current = normalizeWorkspaceRecordMap(stored[STORAGE_KEY_SESSION_BINDINGS]);
|
|
71
|
+
if (current.found) {
|
|
72
|
+
return current.map;
|
|
73
|
+
}
|
|
74
|
+
const legacyMap = normalizeWorkspaceRecordMap(stored[LEGACY_STORAGE_KEY_WORKSPACES]);
|
|
75
|
+
if (legacyMap.found) {
|
|
76
|
+
return legacyMap.map;
|
|
77
|
+
}
|
|
78
|
+
const legacySingle = stored[LEGACY_STORAGE_KEY_WORKSPACE];
|
|
79
|
+
if (isWorkspaceRecord(legacySingle)) {
|
|
80
|
+
return {
|
|
81
|
+
[legacySingle.id]: cloneWorkspaceRecord(legacySingle)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {};
|
|
85
|
+
}
|
|
86
|
+
|
|
33
87
|
// src/workspace.ts
|
|
34
|
-
var DEFAULT_WORKSPACE_ID = "default";
|
|
35
88
|
var DEFAULT_WORKSPACE_LABEL = "bak agent";
|
|
36
89
|
var DEFAULT_WORKSPACE_COLOR = "blue";
|
|
37
90
|
var DEFAULT_WORKSPACE_URL = "about:blank";
|
|
38
|
-
var
|
|
91
|
+
var SessionBindingManager = class {
|
|
39
92
|
storage;
|
|
40
93
|
browser;
|
|
41
94
|
constructor(storage, browser) {
|
|
42
95
|
this.storage = storage;
|
|
43
96
|
this.browser = browser;
|
|
44
97
|
}
|
|
45
|
-
async getWorkspaceInfo(workspaceId
|
|
98
|
+
async getWorkspaceInfo(workspaceId) {
|
|
46
99
|
return this.inspectWorkspace(workspaceId);
|
|
47
100
|
}
|
|
48
101
|
async ensureWorkspace(options = {}) {
|
|
49
102
|
const workspaceId = this.normalizeWorkspaceId(options.workspaceId);
|
|
50
103
|
const repairActions = [];
|
|
51
104
|
const initialUrl = options.initialUrl ?? DEFAULT_WORKSPACE_URL;
|
|
52
|
-
const persisted = await this.storage.load();
|
|
105
|
+
const persisted = await this.storage.load(workspaceId);
|
|
53
106
|
const created = !persisted;
|
|
54
107
|
let state = this.normalizeState(persisted, workspaceId);
|
|
55
108
|
const originalWindowId = state.windowId;
|
|
@@ -263,7 +316,7 @@
|
|
|
263
316
|
tab
|
|
264
317
|
};
|
|
265
318
|
}
|
|
266
|
-
async listTabs(workspaceId
|
|
319
|
+
async listTabs(workspaceId) {
|
|
267
320
|
const ensured = await this.inspectWorkspace(workspaceId);
|
|
268
321
|
if (!ensured) {
|
|
269
322
|
throw new Error(`Workspace ${workspaceId} does not exist`);
|
|
@@ -273,7 +326,7 @@
|
|
|
273
326
|
tabs: ensured.tabs
|
|
274
327
|
};
|
|
275
328
|
}
|
|
276
|
-
async getActiveTab(workspaceId
|
|
329
|
+
async getActiveTab(workspaceId) {
|
|
277
330
|
const ensured = await this.inspectWorkspace(workspaceId);
|
|
278
331
|
if (!ensured) {
|
|
279
332
|
const normalizedWorkspaceId = this.normalizeWorkspaceId(workspaceId);
|
|
@@ -290,7 +343,7 @@
|
|
|
290
343
|
tab: ensured.tabs.find((tab) => tab.id === ensured.activeTabId) ?? null
|
|
291
344
|
};
|
|
292
345
|
}
|
|
293
|
-
async setActiveTab(tabId, workspaceId
|
|
346
|
+
async setActiveTab(tabId, workspaceId) {
|
|
294
347
|
const ensured = await this.ensureWorkspace({ workspaceId });
|
|
295
348
|
if (!ensured.workspace.tabIds.includes(tabId)) {
|
|
296
349
|
throw new Error(`Tab ${tabId} does not belong to workspace ${workspaceId}`);
|
|
@@ -319,7 +372,7 @@
|
|
|
319
372
|
tab
|
|
320
373
|
};
|
|
321
374
|
}
|
|
322
|
-
async focus(workspaceId
|
|
375
|
+
async focus(workspaceId) {
|
|
323
376
|
const ensured = await this.ensureWorkspace({ workspaceId, focus: false });
|
|
324
377
|
if (ensured.workspace.activeTabId !== null) {
|
|
325
378
|
await this.browser.updateTab(ensured.workspace.activeTabId, { active: true });
|
|
@@ -331,16 +384,20 @@
|
|
|
331
384
|
return { ok: true, workspace: refreshed.workspace };
|
|
332
385
|
}
|
|
333
386
|
async reset(options = {}) {
|
|
334
|
-
|
|
335
|
-
|
|
387
|
+
const workspaceId = this.normalizeWorkspaceId(options.workspaceId);
|
|
388
|
+
await this.close(workspaceId);
|
|
389
|
+
return this.ensureWorkspace({
|
|
390
|
+
...options,
|
|
391
|
+
workspaceId
|
|
392
|
+
});
|
|
336
393
|
}
|
|
337
|
-
async close(workspaceId
|
|
338
|
-
const state = await this.
|
|
339
|
-
if (!state
|
|
340
|
-
await this.storage.
|
|
394
|
+
async close(workspaceId) {
|
|
395
|
+
const state = await this.loadWorkspaceRecord(workspaceId);
|
|
396
|
+
if (!state) {
|
|
397
|
+
await this.storage.delete(workspaceId);
|
|
341
398
|
return { ok: true };
|
|
342
399
|
}
|
|
343
|
-
await this.storage.
|
|
400
|
+
await this.storage.delete(workspaceId);
|
|
344
401
|
if (state.windowId !== null) {
|
|
345
402
|
const existingWindow = await this.browser.getWindow(state.windowId);
|
|
346
403
|
if (existingWindow) {
|
|
@@ -366,19 +423,11 @@
|
|
|
366
423
|
}
|
|
367
424
|
const explicitWorkspaceId = typeof options.workspaceId === "string" ? this.normalizeWorkspaceId(options.workspaceId) : void 0;
|
|
368
425
|
if (explicitWorkspaceId) {
|
|
369
|
-
const
|
|
426
|
+
const ensured = await this.ensureWorkspace({
|
|
370
427
|
workspaceId: explicitWorkspaceId,
|
|
371
428
|
focus: false
|
|
372
429
|
});
|
|
373
|
-
return this.buildWorkspaceResolution(
|
|
374
|
-
}
|
|
375
|
-
const existingWorkspace = await this.loadWorkspaceRecord(DEFAULT_WORKSPACE_ID);
|
|
376
|
-
if (existingWorkspace) {
|
|
377
|
-
const ensured2 = await this.ensureWorkspace({
|
|
378
|
-
workspaceId: existingWorkspace.id,
|
|
379
|
-
focus: false
|
|
380
|
-
});
|
|
381
|
-
return this.buildWorkspaceResolution(ensured2, "default-workspace");
|
|
430
|
+
return this.buildWorkspaceResolution(ensured, "explicit-workspace");
|
|
382
431
|
}
|
|
383
432
|
if (options.createIfMissing !== true) {
|
|
384
433
|
const activeTab = await this.browser.getActiveTab();
|
|
@@ -394,19 +443,12 @@
|
|
|
394
443
|
repairActions: []
|
|
395
444
|
};
|
|
396
445
|
}
|
|
397
|
-
|
|
398
|
-
workspaceId: DEFAULT_WORKSPACE_ID,
|
|
399
|
-
focus: false
|
|
400
|
-
});
|
|
401
|
-
return this.buildWorkspaceResolution(ensured, "default-workspace");
|
|
446
|
+
throw new Error("workspaceId is required when createIfMissing is true");
|
|
402
447
|
}
|
|
403
448
|
normalizeWorkspaceId(workspaceId) {
|
|
404
449
|
const candidate = workspaceId?.trim();
|
|
405
450
|
if (!candidate) {
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
if (candidate !== DEFAULT_WORKSPACE_ID) {
|
|
409
|
-
throw new Error(`Unsupported workspace id: ${candidate}`);
|
|
451
|
+
throw new Error("workspaceId is required");
|
|
410
452
|
}
|
|
411
453
|
return candidate;
|
|
412
454
|
}
|
|
@@ -422,9 +464,12 @@
|
|
|
422
464
|
primaryTabId: state?.primaryTabId ?? null
|
|
423
465
|
};
|
|
424
466
|
}
|
|
425
|
-
async
|
|
467
|
+
async listWorkspaceRecords() {
|
|
468
|
+
return await this.storage.list();
|
|
469
|
+
}
|
|
470
|
+
async loadWorkspaceRecord(workspaceId) {
|
|
426
471
|
const normalizedWorkspaceId = this.normalizeWorkspaceId(workspaceId);
|
|
427
|
-
const state = await this.storage.load();
|
|
472
|
+
const state = await this.storage.load(normalizedWorkspaceId);
|
|
428
473
|
if (!state || state.id !== normalizedWorkspaceId) {
|
|
429
474
|
return null;
|
|
430
475
|
}
|
|
@@ -659,7 +704,7 @@
|
|
|
659
704
|
}
|
|
660
705
|
throw lastError2 ?? new Error(`No window with id: ${options.windowId}.`);
|
|
661
706
|
}
|
|
662
|
-
async inspectWorkspace(workspaceId
|
|
707
|
+
async inspectWorkspace(workspaceId) {
|
|
663
708
|
const state = await this.loadWorkspaceRecord(workspaceId);
|
|
664
709
|
if (!state) {
|
|
665
710
|
return null;
|
|
@@ -755,7 +800,6 @@
|
|
|
755
800
|
var STORAGE_KEY_TOKEN = "pairToken";
|
|
756
801
|
var STORAGE_KEY_PORT = "cliPort";
|
|
757
802
|
var STORAGE_KEY_DEBUG_RICH_TEXT = "debugRichText";
|
|
758
|
-
var STORAGE_KEY_WORKSPACE = "agentWorkspace";
|
|
759
803
|
var DEFAULT_TAB_LOAD_TIMEOUT_MS = 4e4;
|
|
760
804
|
var ws = null;
|
|
761
805
|
var reconnectTimer = null;
|
|
@@ -817,6 +861,12 @@
|
|
|
817
861
|
if (lower.includes("no tab with id") || lower.includes("no window with id")) {
|
|
818
862
|
return toError("E_NOT_FOUND", message);
|
|
819
863
|
}
|
|
864
|
+
if (lower.includes("workspace") && lower.includes("does not exist")) {
|
|
865
|
+
return toError("E_NOT_FOUND", message);
|
|
866
|
+
}
|
|
867
|
+
if (lower.includes("does not belong to workspace") || lower.includes("is missing from workspace")) {
|
|
868
|
+
return toError("E_NOT_FOUND", message);
|
|
869
|
+
}
|
|
820
870
|
if (lower.includes("invalid url") || lower.includes("url is invalid")) {
|
|
821
871
|
return toError("E_INVALID_PARAMS", message);
|
|
822
872
|
}
|
|
@@ -838,20 +888,36 @@
|
|
|
838
888
|
groupId: typeof tab.groupId === "number" && tab.groupId >= 0 ? tab.groupId : null
|
|
839
889
|
};
|
|
840
890
|
}
|
|
841
|
-
async function
|
|
842
|
-
const stored = await chrome.storage.local.get(
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
return
|
|
891
|
+
async function loadWorkspaceStateMap() {
|
|
892
|
+
const stored = await chrome.storage.local.get([
|
|
893
|
+
STORAGE_KEY_SESSION_BINDINGS,
|
|
894
|
+
LEGACY_STORAGE_KEY_WORKSPACES,
|
|
895
|
+
LEGACY_STORAGE_KEY_WORKSPACE
|
|
896
|
+
]);
|
|
897
|
+
return resolveSessionBindingStateMap(stored);
|
|
898
|
+
}
|
|
899
|
+
async function loadWorkspaceState(workspaceId) {
|
|
900
|
+
const stateMap = await loadWorkspaceStateMap();
|
|
901
|
+
return stateMap[workspaceId] ?? null;
|
|
902
|
+
}
|
|
903
|
+
async function listWorkspaceStates() {
|
|
904
|
+
return Object.values(await loadWorkspaceStateMap());
|
|
848
905
|
}
|
|
849
906
|
async function saveWorkspaceState(state) {
|
|
850
|
-
|
|
851
|
-
|
|
907
|
+
const stateMap = await loadWorkspaceStateMap();
|
|
908
|
+
stateMap[state.id] = state;
|
|
909
|
+
await chrome.storage.local.set({ [STORAGE_KEY_SESSION_BINDINGS]: stateMap });
|
|
910
|
+
await chrome.storage.local.remove([LEGACY_STORAGE_KEY_WORKSPACES, LEGACY_STORAGE_KEY_WORKSPACE]);
|
|
911
|
+
}
|
|
912
|
+
async function deleteWorkspaceState(workspaceId) {
|
|
913
|
+
const stateMap = await loadWorkspaceStateMap();
|
|
914
|
+
delete stateMap[workspaceId];
|
|
915
|
+
if (Object.keys(stateMap).length === 0) {
|
|
916
|
+
await chrome.storage.local.remove([STORAGE_KEY_SESSION_BINDINGS, LEGACY_STORAGE_KEY_WORKSPACES, LEGACY_STORAGE_KEY_WORKSPACE]);
|
|
852
917
|
return;
|
|
853
918
|
}
|
|
854
|
-
await chrome.storage.local.set({ [
|
|
919
|
+
await chrome.storage.local.set({ [STORAGE_KEY_SESSION_BINDINGS]: stateMap });
|
|
920
|
+
await chrome.storage.local.remove([LEGACY_STORAGE_KEY_WORKSPACES, LEGACY_STORAGE_KEY_WORKSPACE]);
|
|
855
921
|
}
|
|
856
922
|
var workspaceBrowser = {
|
|
857
923
|
async getTab(tabId) {
|
|
@@ -983,10 +1049,12 @@
|
|
|
983
1049
|
};
|
|
984
1050
|
}
|
|
985
1051
|
};
|
|
986
|
-
var
|
|
1052
|
+
var bindingManager = new SessionBindingManager(
|
|
987
1053
|
{
|
|
988
1054
|
load: loadWorkspaceState,
|
|
989
|
-
save: saveWorkspaceState
|
|
1055
|
+
save: saveWorkspaceState,
|
|
1056
|
+
delete: deleteWorkspaceState,
|
|
1057
|
+
list: listWorkspaceStates
|
|
990
1058
|
},
|
|
991
1059
|
workspaceBrowser
|
|
992
1060
|
);
|
|
@@ -1094,7 +1162,7 @@
|
|
|
1094
1162
|
} catch {
|
|
1095
1163
|
refreshedTab = await workspaceBrowser.getTab(opened.tab.id) ?? opened.tab;
|
|
1096
1164
|
}
|
|
1097
|
-
const refreshedWorkspace = await
|
|
1165
|
+
const refreshedWorkspace = await bindingManager.getWorkspaceInfo(opened.workspace.id) ?? {
|
|
1098
1166
|
...opened.workspace,
|
|
1099
1167
|
tabs: opened.workspace.tabs.map((tab) => tab.id === refreshedTab.id ? refreshedTab : tab)
|
|
1100
1168
|
};
|
|
@@ -1121,7 +1189,7 @@
|
|
|
1121
1189
|
const tab2 = await chrome.tabs.get(target.tabId);
|
|
1122
1190
|
return validate(tab2);
|
|
1123
1191
|
}
|
|
1124
|
-
const resolved = await
|
|
1192
|
+
const resolved = await bindingManager.resolveTarget({
|
|
1125
1193
|
tabId: target.tabId,
|
|
1126
1194
|
workspaceId: typeof target.workspaceId === "string" ? target.workspaceId : void 0,
|
|
1127
1195
|
createIfMissing: false
|
|
@@ -1254,6 +1322,8 @@
|
|
|
1254
1322
|
"mouse.click",
|
|
1255
1323
|
"mouse.wheel",
|
|
1256
1324
|
"file.upload",
|
|
1325
|
+
"context.get",
|
|
1326
|
+
"context.set",
|
|
1257
1327
|
"context.enterFrame",
|
|
1258
1328
|
"context.exitFrame",
|
|
1259
1329
|
"context.enterShadow",
|
|
@@ -1301,24 +1371,6 @@
|
|
|
1301
1371
|
return { ok: true };
|
|
1302
1372
|
}
|
|
1303
1373
|
case "tabs.new": {
|
|
1304
|
-
if (typeof params.workspaceId === "string" || params.windowId === void 0) {
|
|
1305
|
-
const expectedUrl = params.url ?? "about:blank";
|
|
1306
|
-
const opened = await preserveHumanFocus(true, async () => {
|
|
1307
|
-
return await workspaceManager.openTab({
|
|
1308
|
-
workspaceId: typeof params.workspaceId === "string" ? params.workspaceId : DEFAULT_WORKSPACE_ID,
|
|
1309
|
-
url: expectedUrl,
|
|
1310
|
-
active: params.active === true,
|
|
1311
|
-
focus: false
|
|
1312
|
-
});
|
|
1313
|
-
});
|
|
1314
|
-
const stabilized = await finalizeOpenedWorkspaceTab(opened, expectedUrl);
|
|
1315
|
-
return {
|
|
1316
|
-
tabId: stabilized.tab.id,
|
|
1317
|
-
windowId: stabilized.tab.windowId,
|
|
1318
|
-
groupId: stabilized.workspace.groupId,
|
|
1319
|
-
workspaceId: stabilized.workspace.id
|
|
1320
|
-
};
|
|
1321
|
-
}
|
|
1322
1374
|
const tab = await chrome.tabs.create({
|
|
1323
1375
|
url: params.url ?? "about:blank",
|
|
1324
1376
|
windowId: typeof params.windowId === "number" ? params.windowId : void 0,
|
|
@@ -1344,8 +1396,8 @@
|
|
|
1344
1396
|
}
|
|
1345
1397
|
case "workspace.ensure": {
|
|
1346
1398
|
return preserveHumanFocus(params.focus !== true, async () => {
|
|
1347
|
-
return await
|
|
1348
|
-
workspaceId:
|
|
1399
|
+
return await bindingManager.ensureWorkspace({
|
|
1400
|
+
workspaceId: String(params.workspaceId ?? ""),
|
|
1349
1401
|
focus: params.focus === true,
|
|
1350
1402
|
initialUrl: typeof params.url === "string" ? params.url : void 0
|
|
1351
1403
|
});
|
|
@@ -1353,14 +1405,14 @@
|
|
|
1353
1405
|
}
|
|
1354
1406
|
case "workspace.info": {
|
|
1355
1407
|
return {
|
|
1356
|
-
workspace: await
|
|
1408
|
+
workspace: await bindingManager.getWorkspaceInfo(String(params.workspaceId ?? ""))
|
|
1357
1409
|
};
|
|
1358
1410
|
}
|
|
1359
1411
|
case "workspace.openTab": {
|
|
1360
1412
|
const expectedUrl = typeof params.url === "string" ? params.url : void 0;
|
|
1361
1413
|
const opened = await preserveHumanFocus(params.focus !== true, async () => {
|
|
1362
|
-
return await
|
|
1363
|
-
workspaceId:
|
|
1414
|
+
return await bindingManager.openTab({
|
|
1415
|
+
workspaceId: String(params.workspaceId ?? ""),
|
|
1364
1416
|
url: expectedUrl,
|
|
1365
1417
|
active: params.active === true,
|
|
1366
1418
|
focus: params.focus === true
|
|
@@ -1369,28 +1421,28 @@
|
|
|
1369
1421
|
return await finalizeOpenedWorkspaceTab(opened, expectedUrl);
|
|
1370
1422
|
}
|
|
1371
1423
|
case "workspace.listTabs": {
|
|
1372
|
-
return await
|
|
1424
|
+
return await bindingManager.listTabs(String(params.workspaceId ?? ""));
|
|
1373
1425
|
}
|
|
1374
1426
|
case "workspace.getActiveTab": {
|
|
1375
|
-
return await
|
|
1427
|
+
return await bindingManager.getActiveTab(String(params.workspaceId ?? ""));
|
|
1376
1428
|
}
|
|
1377
1429
|
case "workspace.setActiveTab": {
|
|
1378
|
-
return await
|
|
1430
|
+
return await bindingManager.setActiveTab(Number(params.tabId), String(params.workspaceId ?? ""));
|
|
1379
1431
|
}
|
|
1380
1432
|
case "workspace.focus": {
|
|
1381
|
-
return await
|
|
1433
|
+
return await bindingManager.focus(String(params.workspaceId ?? ""));
|
|
1382
1434
|
}
|
|
1383
1435
|
case "workspace.reset": {
|
|
1384
1436
|
return await preserveHumanFocus(params.focus !== true, async () => {
|
|
1385
|
-
return await
|
|
1386
|
-
workspaceId:
|
|
1437
|
+
return await bindingManager.reset({
|
|
1438
|
+
workspaceId: String(params.workspaceId ?? ""),
|
|
1387
1439
|
focus: params.focus === true,
|
|
1388
1440
|
initialUrl: typeof params.url === "string" ? params.url : void 0
|
|
1389
1441
|
});
|
|
1390
1442
|
});
|
|
1391
1443
|
}
|
|
1392
1444
|
case "workspace.close": {
|
|
1393
|
-
return await
|
|
1445
|
+
return await bindingManager.close(String(params.workspaceId ?? ""));
|
|
1394
1446
|
}
|
|
1395
1447
|
case "page.goto": {
|
|
1396
1448
|
return await preserveHumanFocus(typeof target.tabId !== "number", async () => {
|
|
@@ -1619,7 +1671,7 @@
|
|
|
1619
1671
|
ws?.send(JSON.stringify({
|
|
1620
1672
|
type: "hello",
|
|
1621
1673
|
role: "extension",
|
|
1622
|
-
version: "0.
|
|
1674
|
+
version: "0.5.0",
|
|
1623
1675
|
ts: Date.now()
|
|
1624
1676
|
}));
|
|
1625
1677
|
});
|
|
@@ -1654,43 +1706,49 @@
|
|
|
1654
1706
|
});
|
|
1655
1707
|
}
|
|
1656
1708
|
chrome.tabs.onRemoved.addListener((tabId) => {
|
|
1657
|
-
void
|
|
1658
|
-
|
|
1659
|
-
|
|
1709
|
+
void listWorkspaceStates().then(async (states) => {
|
|
1710
|
+
for (const state of states) {
|
|
1711
|
+
if (!state.tabIds.includes(tabId)) {
|
|
1712
|
+
continue;
|
|
1713
|
+
}
|
|
1714
|
+
const nextTabIds = state.tabIds.filter((id) => id !== tabId);
|
|
1715
|
+
await saveWorkspaceState({
|
|
1716
|
+
...state,
|
|
1717
|
+
tabIds: nextTabIds,
|
|
1718
|
+
activeTabId: state.activeTabId === tabId ? null : state.activeTabId,
|
|
1719
|
+
primaryTabId: state.primaryTabId === tabId ? null : state.primaryTabId
|
|
1720
|
+
});
|
|
1660
1721
|
}
|
|
1661
|
-
const nextTabIds = state.tabIds.filter((id) => id !== tabId);
|
|
1662
|
-
await saveWorkspaceState({
|
|
1663
|
-
...state,
|
|
1664
|
-
tabIds: nextTabIds,
|
|
1665
|
-
activeTabId: state.activeTabId === tabId ? null : state.activeTabId,
|
|
1666
|
-
primaryTabId: state.primaryTabId === tabId ? null : state.primaryTabId
|
|
1667
|
-
});
|
|
1668
1722
|
});
|
|
1669
1723
|
});
|
|
1670
1724
|
chrome.tabs.onActivated.addListener((activeInfo) => {
|
|
1671
|
-
void
|
|
1672
|
-
|
|
1673
|
-
|
|
1725
|
+
void listWorkspaceStates().then(async (states) => {
|
|
1726
|
+
for (const state of states) {
|
|
1727
|
+
if (state.windowId !== activeInfo.windowId || !state.tabIds.includes(activeInfo.tabId)) {
|
|
1728
|
+
continue;
|
|
1729
|
+
}
|
|
1730
|
+
await saveWorkspaceState({
|
|
1731
|
+
...state,
|
|
1732
|
+
activeTabId: activeInfo.tabId
|
|
1733
|
+
});
|
|
1674
1734
|
}
|
|
1675
|
-
await saveWorkspaceState({
|
|
1676
|
-
...state,
|
|
1677
|
-
activeTabId: activeInfo.tabId
|
|
1678
|
-
});
|
|
1679
1735
|
});
|
|
1680
1736
|
});
|
|
1681
1737
|
chrome.windows.onRemoved.addListener((windowId) => {
|
|
1682
|
-
void
|
|
1683
|
-
|
|
1684
|
-
|
|
1738
|
+
void listWorkspaceStates().then(async (states) => {
|
|
1739
|
+
for (const state of states) {
|
|
1740
|
+
if (state.windowId !== windowId) {
|
|
1741
|
+
continue;
|
|
1742
|
+
}
|
|
1743
|
+
await saveWorkspaceState({
|
|
1744
|
+
...state,
|
|
1745
|
+
windowId: null,
|
|
1746
|
+
groupId: null,
|
|
1747
|
+
tabIds: [],
|
|
1748
|
+
activeTabId: null,
|
|
1749
|
+
primaryTabId: null
|
|
1750
|
+
});
|
|
1685
1751
|
}
|
|
1686
|
-
await saveWorkspaceState({
|
|
1687
|
-
...state,
|
|
1688
|
-
windowId: null,
|
|
1689
|
-
groupId: null,
|
|
1690
|
-
tabIds: [],
|
|
1691
|
-
activeTabId: null,
|
|
1692
|
-
primaryTabId: null
|
|
1693
|
-
});
|
|
1694
1752
|
});
|
|
1695
1753
|
});
|
|
1696
1754
|
chrome.runtime.onInstalled.addListener(() => {
|
package/dist/content.global.js
CHANGED
|
@@ -1962,6 +1962,35 @@
|
|
|
1962
1962
|
dispatchInputEvents(target);
|
|
1963
1963
|
return { ok: true, fileCount: transfer.files.length };
|
|
1964
1964
|
}
|
|
1965
|
+
case "context.get":
|
|
1966
|
+
return {
|
|
1967
|
+
ok: true,
|
|
1968
|
+
frameDepth: contextState.framePath.length,
|
|
1969
|
+
shadowDepth: contextState.shadowPath.length,
|
|
1970
|
+
framePath: [...contextState.framePath],
|
|
1971
|
+
shadowPath: [...contextState.shadowPath]
|
|
1972
|
+
};
|
|
1973
|
+
case "context.set": {
|
|
1974
|
+
const framePath = Array.isArray(params.framePath) ? params.framePath.map(String) : [];
|
|
1975
|
+
const shadowPath = Array.isArray(params.shadowPath) ? params.shadowPath.map(String) : [];
|
|
1976
|
+
const frameResult = resolveFrameDocument(framePath);
|
|
1977
|
+
if (!frameResult.ok) {
|
|
1978
|
+
throw frameResult.error;
|
|
1979
|
+
}
|
|
1980
|
+
const shadowResult = resolveShadowRoot(frameResult.document, shadowPath);
|
|
1981
|
+
if (!shadowResult.ok) {
|
|
1982
|
+
throw shadowResult.error;
|
|
1983
|
+
}
|
|
1984
|
+
contextState.framePath = framePath;
|
|
1985
|
+
contextState.shadowPath = shadowPath;
|
|
1986
|
+
return {
|
|
1987
|
+
ok: true,
|
|
1988
|
+
frameDepth: contextState.framePath.length,
|
|
1989
|
+
shadowDepth: contextState.shadowPath.length,
|
|
1990
|
+
framePath: [...contextState.framePath],
|
|
1991
|
+
shadowPath: [...contextState.shadowPath]
|
|
1992
|
+
};
|
|
1993
|
+
}
|
|
1965
1994
|
case "context.enterFrame": {
|
|
1966
1995
|
if (params.reset === true) {
|
|
1967
1996
|
contextState.framePath = [];
|
package/dist/manifest.json
CHANGED
package/package.json
CHANGED