bb-browser 0.1.2 → 0.2.1
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 +113 -160
- package/dist/{chunk-YAVLEXUJ.js → chunk-TUO443YI.js} +2 -1
- package/dist/cli.js +1 -1
- package/dist/daemon.js +14 -3
- package/dist/daemon.js.map +1 -1
- package/extension/background.js +166 -90
- package/extension/background.js.map +1 -1
- package/extension/dist/background.js +27 -5
- package/extension/dist/background.js.map +1 -1
- package/extension/dist/manifest.json +1 -0
- package/extension/dist/options.html +26 -0
- package/extension/dist/options.js +19 -0
- package/extension/dist/options.js.map +1 -0
- package/extension/manifest.json +2 -1
- package/extension/options.html +26 -0
- package/extension/options.js +19 -0
- package/extension/options.js.map +1 -0
- package/package.json +1 -1
- /package/dist/{chunk-YAVLEXUJ.js.map → chunk-TUO443YI.js.map} +0 -0
package/extension/background.js
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
const
|
|
1
|
+
const DEFAULT_DAEMON_PORT = 19824;
|
|
2
|
+
const DEFAULT_DAEMON_HOST = "localhost";
|
|
3
|
+
const DEFAULT_DAEMON_BASE_URL = `http://${DEFAULT_DAEMON_HOST}:${DEFAULT_DAEMON_PORT}`;
|
|
4
4
|
const SSE_RECONNECT_DELAY = 3e3;
|
|
5
5
|
const SSE_MAX_RECONNECT_ATTEMPTS = 5;
|
|
6
|
+
const STORAGE_KEY = "upstreamUrl";
|
|
7
|
+
async function getUpstreamUrl() {
|
|
8
|
+
try {
|
|
9
|
+
const result = await chrome.storage.sync.get(STORAGE_KEY);
|
|
10
|
+
const url = result[STORAGE_KEY];
|
|
11
|
+
if (url && typeof url === "string" && url.trim()) {
|
|
12
|
+
return url.trim().replace(/\/+$/, "");
|
|
13
|
+
}
|
|
14
|
+
} catch {
|
|
15
|
+
}
|
|
16
|
+
return DEFAULT_DAEMON_BASE_URL;
|
|
17
|
+
}
|
|
6
18
|
|
|
7
19
|
class SSEClient {
|
|
8
20
|
constructor() {
|
|
@@ -19,7 +31,8 @@ class SSEClient {
|
|
|
19
31
|
console.warn("[SSEClient] Already connected");
|
|
20
32
|
return;
|
|
21
33
|
}
|
|
22
|
-
const
|
|
34
|
+
const baseUrl = await getUpstreamUrl();
|
|
35
|
+
const sseUrl = `${baseUrl}/sse`;
|
|
23
36
|
console.log("[SSEClient] Connecting to:", sseUrl);
|
|
24
37
|
this.abortController = new AbortController();
|
|
25
38
|
try {
|
|
@@ -81,7 +94,9 @@ class SSEClient {
|
|
|
81
94
|
data = trimmedLine.substring(5).trim();
|
|
82
95
|
} else if (trimmedLine === "") {
|
|
83
96
|
if (event && data) {
|
|
84
|
-
|
|
97
|
+
this.handleMessage(event, data).catch(
|
|
98
|
+
(err) => console.error("[SSEClient] handleMessage error:", err)
|
|
99
|
+
);
|
|
85
100
|
event = "";
|
|
86
101
|
data = "";
|
|
87
102
|
}
|
|
@@ -172,7 +187,8 @@ class SSEClient {
|
|
|
172
187
|
}
|
|
173
188
|
|
|
174
189
|
async function sendResult(result) {
|
|
175
|
-
const
|
|
190
|
+
const baseUrl = await getUpstreamUrl();
|
|
191
|
+
const url = `${baseUrl}/result`;
|
|
176
192
|
console.log("[APIClient] Sending result:", result.id, result.success);
|
|
177
193
|
try {
|
|
178
194
|
const response = await fetch(url, {
|
|
@@ -424,15 +440,15 @@ function initEventListeners() {
|
|
|
424
440
|
});
|
|
425
441
|
chrome.debugger.onDetach.addListener((source) => {
|
|
426
442
|
if (source.tabId) {
|
|
427
|
-
cleanupTab(source.tabId);
|
|
443
|
+
cleanupTab$2(source.tabId);
|
|
428
444
|
console.log("[CDPService] Debugger detached from tab:", source.tabId);
|
|
429
445
|
}
|
|
430
446
|
});
|
|
431
447
|
chrome.tabs.onRemoved.addListener((tabId) => {
|
|
432
|
-
cleanupTab(tabId);
|
|
448
|
+
cleanupTab$2(tabId);
|
|
433
449
|
});
|
|
434
450
|
}
|
|
435
|
-
function cleanupTab(tabId) {
|
|
451
|
+
function cleanupTab$2(tabId) {
|
|
436
452
|
attachedTabs.delete(tabId);
|
|
437
453
|
pendingDialogs.delete(tabId);
|
|
438
454
|
networkRequests.delete(tabId);
|
|
@@ -584,13 +600,19 @@ function handleException(tabId, params) {
|
|
|
584
600
|
jsErrors.set(tabId, errors);
|
|
585
601
|
}
|
|
586
602
|
|
|
603
|
+
const tabSnapshotRefs$1 = /* @__PURE__ */ new Map();
|
|
604
|
+
const tabActiveFrameId$2 = /* @__PURE__ */ new Map();
|
|
605
|
+
function cleanupTab$1(tabId) {
|
|
606
|
+
tabSnapshotRefs$1.delete(tabId);
|
|
607
|
+
tabActiveFrameId$2.delete(tabId);
|
|
608
|
+
}
|
|
587
609
|
async function getSnapshot$1(tabId, options = {}) {
|
|
588
610
|
const { interactive = false } = options;
|
|
589
611
|
console.log("[DOMService] Getting snapshot for tab:", tabId, { interactive });
|
|
590
612
|
await injectBuildDomTreeScript(tabId);
|
|
591
613
|
const domTreeResult = await executeBuildDomTree(tabId);
|
|
592
614
|
const snapshotResult = interactive ? convertToAccessibilityTree(domTreeResult) : convertToFullTree(domTreeResult);
|
|
593
|
-
snapshotResult.refs;
|
|
615
|
+
tabSnapshotRefs$1.set(tabId, snapshotResult.refs);
|
|
594
616
|
console.log("[DOMService] Snapshot complete:", {
|
|
595
617
|
mode: interactive ? "interactive" : "full",
|
|
596
618
|
linesCount: snapshotResult.snapshot.split("\n").length,
|
|
@@ -599,6 +621,10 @@ async function getSnapshot$1(tabId, options = {}) {
|
|
|
599
621
|
return snapshotResult;
|
|
600
622
|
}
|
|
601
623
|
function getFrameTarget(tabId) {
|
|
624
|
+
const frameId = tabActiveFrameId$2.get(tabId) ?? null;
|
|
625
|
+
if (frameId !== null) {
|
|
626
|
+
return { tabId, frameIds: [frameId] };
|
|
627
|
+
}
|
|
602
628
|
return { tabId };
|
|
603
629
|
}
|
|
604
630
|
async function injectBuildDomTreeScript(tabId) {
|
|
@@ -883,22 +909,29 @@ function convertToFullTree(result) {
|
|
|
883
909
|
return { snapshot: lines.join("\n"), refs };
|
|
884
910
|
}
|
|
885
911
|
|
|
886
|
-
|
|
912
|
+
const tabSnapshotRefs = /* @__PURE__ */ new Map();
|
|
913
|
+
const tabActiveFrameId$1 = /* @__PURE__ */ new Map();
|
|
887
914
|
async function loadRefsFromStorage() {
|
|
888
915
|
try {
|
|
889
|
-
const result = await chrome.storage.session.get("
|
|
890
|
-
if (result.
|
|
891
|
-
|
|
892
|
-
|
|
916
|
+
const result = await chrome.storage.session.get("tabSnapshotRefs");
|
|
917
|
+
if (result.tabSnapshotRefs) {
|
|
918
|
+
const stored = result.tabSnapshotRefs;
|
|
919
|
+
for (const [tabIdStr, refs] of Object.entries(stored)) {
|
|
920
|
+
tabSnapshotRefs.set(Number(tabIdStr), refs);
|
|
921
|
+
}
|
|
922
|
+
console.log("[CDPDOMService] Loaded refs from storage:", tabSnapshotRefs.size, "tabs");
|
|
893
923
|
}
|
|
894
924
|
} catch (e) {
|
|
895
925
|
console.warn("[CDPDOMService] Failed to load refs from storage:", e);
|
|
896
926
|
}
|
|
897
927
|
}
|
|
898
|
-
async function saveRefsToStorage(refs) {
|
|
928
|
+
async function saveRefsToStorage(tabId, refs) {
|
|
899
929
|
try {
|
|
900
|
-
await chrome.storage.session.
|
|
901
|
-
|
|
930
|
+
const result = await chrome.storage.session.get("tabSnapshotRefs");
|
|
931
|
+
const stored = result.tabSnapshotRefs || {};
|
|
932
|
+
stored[String(tabId)] = refs;
|
|
933
|
+
await chrome.storage.session.set({ tabSnapshotRefs: stored });
|
|
934
|
+
console.log("[CDPDOMService] Saved refs to storage for tab:", tabId, Object.keys(refs).length);
|
|
902
935
|
} catch (e) {
|
|
903
936
|
console.warn("[CDPDOMService] Failed to save refs to storage:", e);
|
|
904
937
|
}
|
|
@@ -916,8 +949,8 @@ async function getSnapshot(tabId, options = {}) {
|
|
|
916
949
|
tagName: refInfo.tagName
|
|
917
950
|
};
|
|
918
951
|
}
|
|
919
|
-
|
|
920
|
-
await saveRefsToStorage(convertedRefs);
|
|
952
|
+
tabSnapshotRefs.set(tabId, convertedRefs);
|
|
953
|
+
await saveRefsToStorage(tabId, convertedRefs);
|
|
921
954
|
console.log("[CDPDOMService] Snapshot complete:", {
|
|
922
955
|
linesCount: result.snapshot.split("\n").length,
|
|
923
956
|
refsCount: Object.keys(convertedRefs).length
|
|
@@ -927,15 +960,24 @@ async function getSnapshot(tabId, options = {}) {
|
|
|
927
960
|
refs: convertedRefs
|
|
928
961
|
};
|
|
929
962
|
}
|
|
930
|
-
async function getRefInfo(ref) {
|
|
963
|
+
async function getRefInfo(tabId, ref) {
|
|
931
964
|
const refId = ref.startsWith("@") ? ref.slice(1) : ref;
|
|
932
|
-
|
|
933
|
-
|
|
965
|
+
const refs = tabSnapshotRefs.get(tabId);
|
|
966
|
+
if (refs?.[refId]) {
|
|
967
|
+
return refs[refId];
|
|
934
968
|
}
|
|
935
|
-
if (
|
|
969
|
+
if (!tabSnapshotRefs.has(tabId)) {
|
|
936
970
|
await loadRefsFromStorage();
|
|
971
|
+
const loaded = tabSnapshotRefs.get(tabId);
|
|
972
|
+
if (loaded?.[refId]) {
|
|
973
|
+
return loaded[refId];
|
|
974
|
+
}
|
|
937
975
|
}
|
|
938
|
-
return
|
|
976
|
+
return null;
|
|
977
|
+
}
|
|
978
|
+
function cleanupTab(tabId) {
|
|
979
|
+
tabSnapshotRefs.delete(tabId);
|
|
980
|
+
tabActiveFrameId$1.delete(tabId);
|
|
939
981
|
}
|
|
940
982
|
async function getElementCenterByXPath(tabId, xpath) {
|
|
941
983
|
const result = await evaluate(tabId, `
|
|
@@ -966,7 +1008,7 @@ async function getElementCenterByXPath(tabId, xpath) {
|
|
|
966
1008
|
return result;
|
|
967
1009
|
}
|
|
968
1010
|
async function clickElement(tabId, ref) {
|
|
969
|
-
const refInfo = await getRefInfo(ref);
|
|
1011
|
+
const refInfo = await getRefInfo(tabId, ref);
|
|
970
1012
|
if (!refInfo) {
|
|
971
1013
|
throw new Error(`Ref "${ref}" not found. Run snapshot first to get available refs.`);
|
|
972
1014
|
}
|
|
@@ -977,7 +1019,7 @@ async function clickElement(tabId, ref) {
|
|
|
977
1019
|
return { role, name };
|
|
978
1020
|
}
|
|
979
1021
|
async function hoverElement(tabId, ref) {
|
|
980
|
-
const refInfo = await getRefInfo(ref);
|
|
1022
|
+
const refInfo = await getRefInfo(tabId, ref);
|
|
981
1023
|
if (!refInfo) {
|
|
982
1024
|
throw new Error(`Ref "${ref}" not found. Run snapshot first to get available refs.`);
|
|
983
1025
|
}
|
|
@@ -988,7 +1030,7 @@ async function hoverElement(tabId, ref) {
|
|
|
988
1030
|
return { role, name };
|
|
989
1031
|
}
|
|
990
1032
|
async function fillElement(tabId, ref, text) {
|
|
991
|
-
const refInfo = await getRefInfo(ref);
|
|
1033
|
+
const refInfo = await getRefInfo(tabId, ref);
|
|
992
1034
|
if (!refInfo) {
|
|
993
1035
|
throw new Error(`Ref "${ref}" not found. Run snapshot first to get available refs.`);
|
|
994
1036
|
}
|
|
@@ -1021,7 +1063,7 @@ async function fillElement(tabId, ref, text) {
|
|
|
1021
1063
|
return { role, name };
|
|
1022
1064
|
}
|
|
1023
1065
|
async function typeElement(tabId, ref, text) {
|
|
1024
|
-
const refInfo = await getRefInfo(ref);
|
|
1066
|
+
const refInfo = await getRefInfo(tabId, ref);
|
|
1025
1067
|
if (!refInfo) {
|
|
1026
1068
|
throw new Error(`Ref "${ref}" not found. Run snapshot first to get available refs.`);
|
|
1027
1069
|
}
|
|
@@ -1049,7 +1091,7 @@ async function typeElement(tabId, ref, text) {
|
|
|
1049
1091
|
return { role, name };
|
|
1050
1092
|
}
|
|
1051
1093
|
async function getElementText(tabId, ref) {
|
|
1052
|
-
const refInfo = await getRefInfo(ref);
|
|
1094
|
+
const refInfo = await getRefInfo(tabId, ref);
|
|
1053
1095
|
if (!refInfo) {
|
|
1054
1096
|
throw new Error(`Ref "${ref}" not found. Run snapshot first to get available refs.`);
|
|
1055
1097
|
}
|
|
@@ -1072,7 +1114,7 @@ async function getElementText(tabId, ref) {
|
|
|
1072
1114
|
return text;
|
|
1073
1115
|
}
|
|
1074
1116
|
async function checkElement(tabId, ref) {
|
|
1075
|
-
const refInfo = await getRefInfo(ref);
|
|
1117
|
+
const refInfo = await getRefInfo(tabId, ref);
|
|
1076
1118
|
if (!refInfo) {
|
|
1077
1119
|
throw new Error(`Ref "${ref}" not found. Run snapshot first to get available refs.`);
|
|
1078
1120
|
}
|
|
@@ -1103,7 +1145,7 @@ async function checkElement(tabId, ref) {
|
|
|
1103
1145
|
return { role, name, wasAlreadyChecked: result };
|
|
1104
1146
|
}
|
|
1105
1147
|
async function uncheckElement(tabId, ref) {
|
|
1106
|
-
const refInfo = await getRefInfo(ref);
|
|
1148
|
+
const refInfo = await getRefInfo(tabId, ref);
|
|
1107
1149
|
if (!refInfo) {
|
|
1108
1150
|
throw new Error(`Ref "${ref}" not found. Run snapshot first to get available refs.`);
|
|
1109
1151
|
}
|
|
@@ -1134,7 +1176,7 @@ async function uncheckElement(tabId, ref) {
|
|
|
1134
1176
|
return { role, name, wasAlreadyUnchecked: result };
|
|
1135
1177
|
}
|
|
1136
1178
|
async function selectOption(tabId, ref, value) {
|
|
1137
|
-
const refInfo = await getRefInfo(ref);
|
|
1179
|
+
const refInfo = await getRefInfo(tabId, ref);
|
|
1138
1180
|
if (!refInfo) {
|
|
1139
1181
|
throw new Error(`Ref "${ref}" not found. Run snapshot first to get available refs.`);
|
|
1140
1182
|
}
|
|
@@ -1191,7 +1233,7 @@ async function selectOption(tabId, ref, value) {
|
|
|
1191
1233
|
return { role, name, selectedValue, selectedLabel };
|
|
1192
1234
|
}
|
|
1193
1235
|
async function waitForElement(tabId, ref, maxWait = 1e4, interval = 200) {
|
|
1194
|
-
const refInfo = await getRefInfo(ref);
|
|
1236
|
+
const refInfo = await getRefInfo(tabId, ref);
|
|
1195
1237
|
if (!refInfo) {
|
|
1196
1238
|
throw new Error(`Ref "${ref}" not found. Run snapshot first to get available refs.`);
|
|
1197
1239
|
}
|
|
@@ -1219,8 +1261,9 @@ async function waitForElement(tabId, ref, maxWait = 1e4, interval = 200) {
|
|
|
1219
1261
|
}
|
|
1220
1262
|
throw new Error(`Timeout waiting for element @${ref} after ${maxWait}ms`);
|
|
1221
1263
|
}
|
|
1222
|
-
function setActiveFrameId(frameId) {
|
|
1223
|
-
|
|
1264
|
+
function setActiveFrameId(tabId, frameId) {
|
|
1265
|
+
tabActiveFrameId$1.set(tabId, frameId);
|
|
1266
|
+
console.log("[CDPDOMService] Active frame changed:", { tabId, frameId: frameId ?? "main" });
|
|
1224
1267
|
}
|
|
1225
1268
|
async function pressKey(tabId, key, modifiers = []) {
|
|
1226
1269
|
let modifierFlags = 0;
|
|
@@ -1365,7 +1408,17 @@ chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, _tab) => {
|
|
|
1365
1408
|
console.log("[TraceService] Initialized");
|
|
1366
1409
|
|
|
1367
1410
|
initEventListeners();
|
|
1368
|
-
|
|
1411
|
+
const tabActiveFrameId = /* @__PURE__ */ new Map();
|
|
1412
|
+
async function resolveTab(command) {
|
|
1413
|
+
if (command.tabId !== void 0 && typeof command.tabId === "number") {
|
|
1414
|
+
return chrome.tabs.get(command.tabId);
|
|
1415
|
+
}
|
|
1416
|
+
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
|
1417
|
+
if (!tab?.id) {
|
|
1418
|
+
throw new Error("No active tab found");
|
|
1419
|
+
}
|
|
1420
|
+
return tab;
|
|
1421
|
+
}
|
|
1369
1422
|
async function handleCommand(command) {
|
|
1370
1423
|
console.log("[CommandHandler] Processing command:", command.id, command.action);
|
|
1371
1424
|
let result;
|
|
@@ -1530,8 +1583,8 @@ async function handleOpen(command) {
|
|
|
1530
1583
|
};
|
|
1531
1584
|
}
|
|
1532
1585
|
async function handleSnapshot(command) {
|
|
1533
|
-
const
|
|
1534
|
-
if (!activeTab
|
|
1586
|
+
const activeTab = await resolveTab(command);
|
|
1587
|
+
if (!activeTab.id) {
|
|
1535
1588
|
return {
|
|
1536
1589
|
id: command.id,
|
|
1537
1590
|
success: false,
|
|
@@ -1577,8 +1630,8 @@ async function handleClick(command) {
|
|
|
1577
1630
|
error: "Missing ref parameter"
|
|
1578
1631
|
};
|
|
1579
1632
|
}
|
|
1580
|
-
const
|
|
1581
|
-
if (!activeTab
|
|
1633
|
+
const activeTab = await resolveTab(command);
|
|
1634
|
+
if (!activeTab.id) {
|
|
1582
1635
|
return {
|
|
1583
1636
|
id: command.id,
|
|
1584
1637
|
success: false,
|
|
@@ -1614,8 +1667,8 @@ async function handleHover(command) {
|
|
|
1614
1667
|
error: "Missing ref parameter"
|
|
1615
1668
|
};
|
|
1616
1669
|
}
|
|
1617
|
-
const
|
|
1618
|
-
if (!activeTab
|
|
1670
|
+
const activeTab = await resolveTab(command);
|
|
1671
|
+
if (!activeTab.id) {
|
|
1619
1672
|
return {
|
|
1620
1673
|
id: command.id,
|
|
1621
1674
|
success: false,
|
|
@@ -1659,8 +1712,8 @@ async function handleFill(command) {
|
|
|
1659
1712
|
error: "Missing text parameter"
|
|
1660
1713
|
};
|
|
1661
1714
|
}
|
|
1662
|
-
const
|
|
1663
|
-
if (!activeTab
|
|
1715
|
+
const activeTab = await resolveTab(command);
|
|
1716
|
+
if (!activeTab.id) {
|
|
1664
1717
|
return {
|
|
1665
1718
|
id: command.id,
|
|
1666
1719
|
success: false,
|
|
@@ -1705,8 +1758,8 @@ async function handleType(command) {
|
|
|
1705
1758
|
error: "Missing text parameter"
|
|
1706
1759
|
};
|
|
1707
1760
|
}
|
|
1708
|
-
const
|
|
1709
|
-
if (!activeTab
|
|
1761
|
+
const activeTab = await resolveTab(command);
|
|
1762
|
+
if (!activeTab.id) {
|
|
1710
1763
|
return {
|
|
1711
1764
|
id: command.id,
|
|
1712
1765
|
success: false,
|
|
@@ -1743,8 +1796,8 @@ async function handleCheck(command) {
|
|
|
1743
1796
|
error: "Missing ref parameter"
|
|
1744
1797
|
};
|
|
1745
1798
|
}
|
|
1746
|
-
const
|
|
1747
|
-
if (!activeTab
|
|
1799
|
+
const activeTab = await resolveTab(command);
|
|
1800
|
+
if (!activeTab.id) {
|
|
1748
1801
|
return {
|
|
1749
1802
|
id: command.id,
|
|
1750
1803
|
success: false,
|
|
@@ -1781,8 +1834,8 @@ async function handleUncheck(command) {
|
|
|
1781
1834
|
error: "Missing ref parameter"
|
|
1782
1835
|
};
|
|
1783
1836
|
}
|
|
1784
|
-
const
|
|
1785
|
-
if (!activeTab
|
|
1837
|
+
const activeTab = await resolveTab(command);
|
|
1838
|
+
if (!activeTab.id) {
|
|
1786
1839
|
return {
|
|
1787
1840
|
id: command.id,
|
|
1788
1841
|
success: false,
|
|
@@ -1827,8 +1880,8 @@ async function handleSelect(command) {
|
|
|
1827
1880
|
error: "Missing value parameter"
|
|
1828
1881
|
};
|
|
1829
1882
|
}
|
|
1830
|
-
const
|
|
1831
|
-
if (!activeTab
|
|
1883
|
+
const activeTab = await resolveTab(command);
|
|
1884
|
+
if (!activeTab.id) {
|
|
1832
1885
|
return {
|
|
1833
1886
|
id: command.id,
|
|
1834
1887
|
success: false,
|
|
@@ -1858,8 +1911,8 @@ async function handleSelect(command) {
|
|
|
1858
1911
|
}
|
|
1859
1912
|
}
|
|
1860
1913
|
async function handleClose(command) {
|
|
1861
|
-
const
|
|
1862
|
-
if (!activeTab
|
|
1914
|
+
const activeTab = await resolveTab(command);
|
|
1915
|
+
if (!activeTab.id) {
|
|
1863
1916
|
return {
|
|
1864
1917
|
id: command.id,
|
|
1865
1918
|
success: false,
|
|
@@ -1872,6 +1925,9 @@ async function handleClose(command) {
|
|
|
1872
1925
|
console.log("[CommandHandler] Closing tab:", tabId, url);
|
|
1873
1926
|
try {
|
|
1874
1927
|
await chrome.tabs.remove(tabId);
|
|
1928
|
+
cleanupTab$1(tabId);
|
|
1929
|
+
cleanupTab(tabId);
|
|
1930
|
+
tabActiveFrameId.delete(tabId);
|
|
1875
1931
|
return {
|
|
1876
1932
|
id: command.id,
|
|
1877
1933
|
success: true,
|
|
@@ -1899,8 +1955,8 @@ async function handleGet(command) {
|
|
|
1899
1955
|
error: "Missing attribute parameter"
|
|
1900
1956
|
};
|
|
1901
1957
|
}
|
|
1902
|
-
const
|
|
1903
|
-
if (!activeTab
|
|
1958
|
+
const activeTab = await resolveTab(command);
|
|
1959
|
+
if (!activeTab.id) {
|
|
1904
1960
|
return {
|
|
1905
1961
|
id: command.id,
|
|
1906
1962
|
success: false,
|
|
@@ -1953,8 +2009,8 @@ async function handleGet(command) {
|
|
|
1953
2009
|
}
|
|
1954
2010
|
}
|
|
1955
2011
|
async function handleScreenshot(command) {
|
|
1956
|
-
const
|
|
1957
|
-
if (!activeTab
|
|
2012
|
+
const activeTab = await resolveTab(command);
|
|
2013
|
+
if (!activeTab.id || !activeTab.windowId) {
|
|
1958
2014
|
return {
|
|
1959
2015
|
id: command.id,
|
|
1960
2016
|
success: false,
|
|
@@ -2009,8 +2065,8 @@ async function handleWait(command) {
|
|
|
2009
2065
|
error: "Missing ref parameter"
|
|
2010
2066
|
};
|
|
2011
2067
|
}
|
|
2012
|
-
const
|
|
2013
|
-
if (!activeTab
|
|
2068
|
+
const activeTab = await resolveTab(command);
|
|
2069
|
+
if (!activeTab.id) {
|
|
2014
2070
|
return {
|
|
2015
2071
|
id: command.id,
|
|
2016
2072
|
success: false,
|
|
@@ -2051,8 +2107,8 @@ async function handlePress(command) {
|
|
|
2051
2107
|
error: "Missing key parameter"
|
|
2052
2108
|
};
|
|
2053
2109
|
}
|
|
2054
|
-
const
|
|
2055
|
-
if (!activeTab
|
|
2110
|
+
const activeTab = await resolveTab(command);
|
|
2111
|
+
if (!activeTab.id) {
|
|
2056
2112
|
return {
|
|
2057
2113
|
id: command.id,
|
|
2058
2114
|
success: false,
|
|
@@ -2104,8 +2160,8 @@ async function handleScroll(command) {
|
|
|
2104
2160
|
error: `Invalid direction: ${direction}`
|
|
2105
2161
|
};
|
|
2106
2162
|
}
|
|
2107
|
-
const
|
|
2108
|
-
if (!activeTab
|
|
2163
|
+
const activeTab = await resolveTab(command);
|
|
2164
|
+
if (!activeTab.id) {
|
|
2109
2165
|
return {
|
|
2110
2166
|
id: command.id,
|
|
2111
2167
|
success: false,
|
|
@@ -2133,8 +2189,8 @@ async function handleScroll(command) {
|
|
|
2133
2189
|
}
|
|
2134
2190
|
}
|
|
2135
2191
|
async function handleBack(command) {
|
|
2136
|
-
const
|
|
2137
|
-
if (!activeTab
|
|
2192
|
+
const activeTab = await resolveTab(command);
|
|
2193
|
+
if (!activeTab.id) {
|
|
2138
2194
|
return {
|
|
2139
2195
|
id: command.id,
|
|
2140
2196
|
success: false,
|
|
@@ -2173,8 +2229,8 @@ async function handleBack(command) {
|
|
|
2173
2229
|
}
|
|
2174
2230
|
}
|
|
2175
2231
|
async function handleForward(command) {
|
|
2176
|
-
const
|
|
2177
|
-
if (!activeTab
|
|
2232
|
+
const activeTab = await resolveTab(command);
|
|
2233
|
+
if (!activeTab.id) {
|
|
2178
2234
|
return {
|
|
2179
2235
|
id: command.id,
|
|
2180
2236
|
success: false,
|
|
@@ -2205,8 +2261,8 @@ async function handleForward(command) {
|
|
|
2205
2261
|
}
|
|
2206
2262
|
}
|
|
2207
2263
|
async function handleRefresh(command) {
|
|
2208
|
-
const
|
|
2209
|
-
if (!activeTab
|
|
2264
|
+
const activeTab = await resolveTab(command);
|
|
2265
|
+
if (!activeTab.id) {
|
|
2210
2266
|
return {
|
|
2211
2267
|
id: command.id,
|
|
2212
2268
|
success: false,
|
|
@@ -2244,8 +2300,8 @@ async function handleEval(command) {
|
|
|
2244
2300
|
error: "Missing script parameter"
|
|
2245
2301
|
};
|
|
2246
2302
|
}
|
|
2247
|
-
const
|
|
2248
|
-
if (!activeTab
|
|
2303
|
+
const activeTab = await resolveTab(command);
|
|
2304
|
+
if (!activeTab.id) {
|
|
2249
2305
|
return {
|
|
2250
2306
|
id: command.id,
|
|
2251
2307
|
success: false,
|
|
@@ -2422,6 +2478,9 @@ async function handleTabClose(command) {
|
|
|
2422
2478
|
const title = targetTab.title || "";
|
|
2423
2479
|
const url = targetTab.url || "";
|
|
2424
2480
|
await chrome.tabs.remove(tabId);
|
|
2481
|
+
cleanupTab$1(tabId);
|
|
2482
|
+
cleanupTab(tabId);
|
|
2483
|
+
tabActiveFrameId.delete(tabId);
|
|
2425
2484
|
return {
|
|
2426
2485
|
id: command.id,
|
|
2427
2486
|
success: true,
|
|
@@ -2449,8 +2508,8 @@ async function handleFrame(command) {
|
|
|
2449
2508
|
error: "Missing selector parameter"
|
|
2450
2509
|
};
|
|
2451
2510
|
}
|
|
2452
|
-
const
|
|
2453
|
-
if (!activeTab
|
|
2511
|
+
const activeTab = await resolveTab(command);
|
|
2512
|
+
if (!activeTab.id) {
|
|
2454
2513
|
return {
|
|
2455
2514
|
id: command.id,
|
|
2456
2515
|
success: false,
|
|
@@ -2461,7 +2520,7 @@ async function handleFrame(command) {
|
|
|
2461
2520
|
console.log("[CommandHandler] Switching to frame:", selector);
|
|
2462
2521
|
try {
|
|
2463
2522
|
const iframeInfoResults = await chrome.scripting.executeScript({
|
|
2464
|
-
target: { tabId, frameIds:
|
|
2523
|
+
target: { tabId, frameIds: tabActiveFrameId.get(tabId) !== null && tabActiveFrameId.get(tabId) !== void 0 ? [tabActiveFrameId.get(tabId)] : [0] },
|
|
2465
2524
|
func: (sel) => {
|
|
2466
2525
|
const iframe = document.querySelector(sel);
|
|
2467
2526
|
if (!iframe) {
|
|
@@ -2540,8 +2599,8 @@ async function handleFrame(command) {
|
|
|
2540
2599
|
error: `无法访问 frame (frameId: ${targetFrameId}),可能是跨域 iframe`
|
|
2541
2600
|
};
|
|
2542
2601
|
}
|
|
2543
|
-
|
|
2544
|
-
setActiveFrameId(String(targetFrameId));
|
|
2602
|
+
tabActiveFrameId.set(tabId, targetFrameId);
|
|
2603
|
+
setActiveFrameId(tabId, String(targetFrameId));
|
|
2545
2604
|
const matchedFrameInfo = frames.find((f) => f.frameId === targetFrameId);
|
|
2546
2605
|
return {
|
|
2547
2606
|
id: command.id,
|
|
@@ -2566,8 +2625,17 @@ async function handleFrame(command) {
|
|
|
2566
2625
|
}
|
|
2567
2626
|
async function handleFrameMain(command) {
|
|
2568
2627
|
console.log("[CommandHandler] Switching to main frame");
|
|
2569
|
-
|
|
2570
|
-
|
|
2628
|
+
const activeTab = await resolveTab(command);
|
|
2629
|
+
if (!activeTab.id) {
|
|
2630
|
+
return {
|
|
2631
|
+
id: command.id,
|
|
2632
|
+
success: false,
|
|
2633
|
+
error: "No active tab found"
|
|
2634
|
+
};
|
|
2635
|
+
}
|
|
2636
|
+
const tabId = activeTab.id;
|
|
2637
|
+
tabActiveFrameId.set(tabId, null);
|
|
2638
|
+
setActiveFrameId(tabId, null);
|
|
2571
2639
|
return {
|
|
2572
2640
|
id: command.id,
|
|
2573
2641
|
success: true,
|
|
@@ -2588,8 +2656,8 @@ async function handleDialog(command) {
|
|
|
2588
2656
|
error: "Missing or invalid dialogResponse parameter (accept/dismiss)"
|
|
2589
2657
|
};
|
|
2590
2658
|
}
|
|
2591
|
-
const
|
|
2592
|
-
if (!activeTab
|
|
2659
|
+
const activeTab = await resolveTab(command);
|
|
2660
|
+
if (!activeTab.id) {
|
|
2593
2661
|
return {
|
|
2594
2662
|
id: command.id,
|
|
2595
2663
|
success: false,
|
|
@@ -2650,8 +2718,8 @@ function waitForTabLoad(tabId, timeout = 3e4) {
|
|
|
2650
2718
|
});
|
|
2651
2719
|
}
|
|
2652
2720
|
async function handleNetwork(command) {
|
|
2653
|
-
const
|
|
2654
|
-
if (!activeTab
|
|
2721
|
+
const activeTab = await resolveTab(command);
|
|
2722
|
+
if (!activeTab.id) {
|
|
2655
2723
|
return {
|
|
2656
2724
|
id: command.id,
|
|
2657
2725
|
success: false,
|
|
@@ -2742,8 +2810,8 @@ async function handleNetwork(command) {
|
|
|
2742
2810
|
}
|
|
2743
2811
|
}
|
|
2744
2812
|
async function handleConsole(command) {
|
|
2745
|
-
const
|
|
2746
|
-
if (!activeTab
|
|
2813
|
+
const activeTab = await resolveTab(command);
|
|
2814
|
+
if (!activeTab.id) {
|
|
2747
2815
|
return {
|
|
2748
2816
|
id: command.id,
|
|
2749
2817
|
success: false,
|
|
@@ -2791,8 +2859,8 @@ async function handleConsole(command) {
|
|
|
2791
2859
|
}
|
|
2792
2860
|
}
|
|
2793
2861
|
async function handleErrors(command) {
|
|
2794
|
-
const
|
|
2795
|
-
if (!activeTab
|
|
2862
|
+
const activeTab = await resolveTab(command);
|
|
2863
|
+
if (!activeTab.id) {
|
|
2796
2864
|
return {
|
|
2797
2865
|
id: command.id,
|
|
2798
2866
|
success: false,
|
|
@@ -2845,8 +2913,8 @@ async function handleTrace(command) {
|
|
|
2845
2913
|
try {
|
|
2846
2914
|
switch (subCommand) {
|
|
2847
2915
|
case "start": {
|
|
2848
|
-
const
|
|
2849
|
-
if (!activeTab
|
|
2916
|
+
const activeTab = await resolveTab(command);
|
|
2917
|
+
if (!activeTab.id) {
|
|
2850
2918
|
return {
|
|
2851
2919
|
id: command.id,
|
|
2852
2920
|
success: false,
|
|
@@ -2915,6 +2983,14 @@ async function handleTrace(command) {
|
|
|
2915
2983
|
const KEEPALIVE_ALARM = "bb-browser-keepalive";
|
|
2916
2984
|
const sseClient = new SSEClient();
|
|
2917
2985
|
sseClient.onCommand(handleCommand);
|
|
2986
|
+
chrome.storage.onChanged.addListener((changes, area) => {
|
|
2987
|
+
if (area === "sync" && changes.upstreamUrl) {
|
|
2988
|
+
const newUrl = changes.upstreamUrl.newValue || "default";
|
|
2989
|
+
console.log("[bb-browser] Upstream URL changed to:", newUrl, "— reconnecting...");
|
|
2990
|
+
sseClient.disconnect();
|
|
2991
|
+
sseClient.connect();
|
|
2992
|
+
}
|
|
2993
|
+
});
|
|
2918
2994
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
2919
2995
|
console.log("[bb-browser] Message from content script:", message, "sender:", sender.tab?.id);
|
|
2920
2996
|
sendResponse({ received: true });
|