cdp-tunnel 2.5.2 → 2.5.4
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/extension-new/cdp/handler/local.js +15 -1
- package/extension-new/cdp/handler/special.js +59 -38
- package/extension-new/cdp/index.js +1 -0
- package/extension-new/core/websocket.js +50 -0
- package/extension-new/manifest.json +1 -1
- package/extension-new/utils/config.js +1 -1
- package/extension-new/utils/helpers.js +2 -1
- package/package.json +1 -1
- package/server/proxy-server.js +34 -7
|
@@ -135,6 +135,19 @@ var LocalHandler = (function() {
|
|
|
135
135
|
return {};
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
function tabGetGroupInfo(context) {
|
|
139
|
+
var clientId = context.clientId;
|
|
140
|
+
var groupId = null;
|
|
141
|
+
var baseName = null;
|
|
142
|
+
try {
|
|
143
|
+
groupId = State.getGroupIdForClient(clientId);
|
|
144
|
+
baseName = CDPUtils.getGroupBaseName(clientId);
|
|
145
|
+
} catch (e) {
|
|
146
|
+
Logger.error('[TabGetGroupInfo] Error: ' + (e.message || e));
|
|
147
|
+
}
|
|
148
|
+
return Promise.resolve({ groupId: groupId, baseName: baseName, clientId: clientId });
|
|
149
|
+
}
|
|
150
|
+
|
|
138
151
|
function tabGetMuteStatus(params) {
|
|
139
152
|
var cdpOnly = params && params.cdpOnly;
|
|
140
153
|
var attachedTabIds = State.getAttachedTabIds();
|
|
@@ -308,6 +321,7 @@ var LocalHandler = (function() {
|
|
|
308
321
|
getTargetInfos: getTargetInfos,
|
|
309
322
|
getTargetInfoById: getTargetInfoById,
|
|
310
323
|
mapToTargetInfo: mapToTargetInfo,
|
|
311
|
-
tabGetMuteStatus: tabGetMuteStatus
|
|
324
|
+
tabGetMuteStatus: tabGetMuteStatus,
|
|
325
|
+
tabGetGroupInfo: tabGetGroupInfo
|
|
312
326
|
};
|
|
313
327
|
})();
|
|
@@ -142,47 +142,68 @@ var SpecialHandler = (function() {
|
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
var baseName = CDPUtils.getGroupBaseName(groupClientId);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
chrome.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
145
|
+
|
|
146
|
+
var retries = 0;
|
|
147
|
+
var maxRetries = 20;
|
|
148
|
+
function tryGroup() {
|
|
149
|
+
chrome.tabs.get(tabId, function(tab) {
|
|
150
|
+
if (chrome.runtime.lastError || !tab) {
|
|
151
|
+
Logger.error('[TabGroup] Tab not found:', tabId, 'retries:', retries);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (tab.status === 'complete') {
|
|
155
|
+
Logger.info('[TabGroup] Tab ready, executing group operation for:', baseName);
|
|
156
|
+
doGroup(tabId, groupClientId, baseName);
|
|
157
|
+
} else if (retries < maxRetries) {
|
|
158
|
+
retries++;
|
|
159
|
+
Logger.info('[TabGroup] Tab not ready (', tab.status, '), retry', retries, '/', maxRetries);
|
|
160
|
+
setTimeout(tryGroup, 200);
|
|
161
161
|
} else {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
Logger.error('[TabGroup] Failed to create group:', chrome.runtime.lastError.message);
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
if (groupId) {
|
|
168
|
-
chrome.tabGroups.update(groupId, {
|
|
169
|
-
title: baseName,
|
|
170
|
-
color: CDPUtils.getGroupColorForClient(groupClientId),
|
|
171
|
-
collapsed: true
|
|
172
|
-
}, function() {
|
|
173
|
-
if (chrome.runtime.lastError) {
|
|
174
|
-
Logger.error('[TabGroup] Failed to update group:', chrome.runtime.lastError.message);
|
|
175
|
-
} else {
|
|
176
|
-
State.setGroupIdForClient(groupClientId, groupId);
|
|
177
|
-
updateTabGroupName(groupClientId);
|
|
178
|
-
Logger.info('[TabGroup] Created new group:', groupId, 'with tab:', tabId);
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
});
|
|
162
|
+
Logger.warn('[TabGroup] Tab never reached complete status, grouping anyway. tabId:', tabId);
|
|
163
|
+
doGroup(tabId, groupClientId, baseName);
|
|
183
164
|
}
|
|
184
165
|
});
|
|
185
|
-
}
|
|
166
|
+
}
|
|
167
|
+
tryGroup();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function doGroup(tabId, clientId, baseName) {
|
|
171
|
+
chrome.tabGroups.query({}, function(allGroups) {
|
|
172
|
+
var existing = CDPUtils.findGroupByName(allGroups, baseName);
|
|
173
|
+
if (existing) {
|
|
174
|
+
chrome.tabs.group({ tabIds: tabId, groupId: existing.id }, function(result) {
|
|
175
|
+
if (chrome.runtime.lastError) {
|
|
176
|
+
Logger.error('[TabGroup] Failed to add tab to group:', chrome.runtime.lastError.message);
|
|
177
|
+
} else {
|
|
178
|
+
State.setGroupIdForClient(clientId, existing.id);
|
|
179
|
+
updateTabGroupName(clientId);
|
|
180
|
+
Logger.info('[TabGroup] Tab', tabId, 'added to existing group:', existing.id);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
} else {
|
|
184
|
+
chrome.tabs.group({ tabIds: tabId }, function(groupId) {
|
|
185
|
+
if (chrome.runtime.lastError) {
|
|
186
|
+
Logger.error('[TabGroup] Failed to create group:', chrome.runtime.lastError.message);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (groupId) {
|
|
190
|
+
chrome.tabGroups.update(groupId, {
|
|
191
|
+
title: baseName,
|
|
192
|
+
color: CDPUtils.getGroupColorForClient(clientId),
|
|
193
|
+
collapsed: true
|
|
194
|
+
}, function() {
|
|
195
|
+
if (chrome.runtime.lastError) {
|
|
196
|
+
Logger.error('[TabGroup] Failed to update group:', chrome.runtime.lastError.message);
|
|
197
|
+
} else {
|
|
198
|
+
State.setGroupIdForClient(clientId, groupId);
|
|
199
|
+
updateTabGroupName(clientId);
|
|
200
|
+
Logger.info('[TabGroup] Created new group:', groupId, 'with tab:', tabId);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
});
|
|
186
207
|
}
|
|
187
208
|
|
|
188
209
|
function updateTabGroupName(clientId) {
|
|
@@ -23,6 +23,7 @@ var CDP_HANDLERS = {
|
|
|
23
23
|
'Target.attachToBrowserTarget': { type: 'LOCAL', handler: LocalHandler.targetAttachToBrowserTarget },
|
|
24
24
|
|
|
25
25
|
'Tab.getMuteStatus': { type: 'LOCAL', handler: LocalHandler.tabGetMuteStatus },
|
|
26
|
+
'Tab.getGroupInfo': { type: 'LOCAL', handler: LocalHandler.tabGetGroupInfo },
|
|
26
27
|
|
|
27
28
|
'SystemInfo.getInfo': { type: 'LOCAL', handler: LocalHandler.systemInfoGetInfo },
|
|
28
29
|
'SystemInfo.getProcessInfo': { type: 'LOCAL', handler: LocalHandler.systemInfoGetProcessInfo },
|
|
@@ -191,6 +191,7 @@ var WebSocketManager = (function() {
|
|
|
191
191
|
Logger.info('[WS] Client connected, resuming event forwarding');
|
|
192
192
|
State.setHasConnectedClient(true);
|
|
193
193
|
State.addCDPClient(message.clientId, message.clientId);
|
|
194
|
+
startGroupMonitor();
|
|
194
195
|
broadcastStateUpdate();
|
|
195
196
|
break;
|
|
196
197
|
|
|
@@ -214,6 +215,7 @@ var WebSocketManager = (function() {
|
|
|
214
215
|
State.removeCDPClient(discClientId);
|
|
215
216
|
if (State.getCDPClients().length === 0) {
|
|
216
217
|
State.setHasConnectedClient(false);
|
|
218
|
+
stopGroupMonitor();
|
|
217
219
|
}
|
|
218
220
|
broadcastStateUpdate();
|
|
219
221
|
});
|
|
@@ -223,6 +225,11 @@ var WebSocketManager = (function() {
|
|
|
223
225
|
Logger.info('[WS] Received client list:', message.clients);
|
|
224
226
|
State.setCDPClients(message.clients || []);
|
|
225
227
|
State.setHasConnectedClient((message.clients || []).length > 0);
|
|
228
|
+
if ((message.clients || []).length > 0) {
|
|
229
|
+
startGroupMonitor();
|
|
230
|
+
} else {
|
|
231
|
+
stopGroupMonitor();
|
|
232
|
+
}
|
|
226
233
|
broadcastStateUpdate();
|
|
227
234
|
break;
|
|
228
235
|
|
|
@@ -378,6 +385,49 @@ var WebSocketManager = (function() {
|
|
|
378
385
|
});
|
|
379
386
|
}
|
|
380
387
|
|
|
388
|
+
var _groupMonitorTimer = null;
|
|
389
|
+
|
|
390
|
+
function startGroupMonitor() {
|
|
391
|
+
Logger.info('[Monitor] Starting group monitor...');
|
|
392
|
+
if (_groupMonitorTimer) clearInterval(_groupMonitorTimer);
|
|
393
|
+
_groupMonitorTimer = setInterval(function() {
|
|
394
|
+
var attached = State.getAttachedTabIds();
|
|
395
|
+
attached.forEach(function(tabId) {
|
|
396
|
+
var clientId = State.getClientIdByTabId(tabId);
|
|
397
|
+
if (!clientId) return;
|
|
398
|
+
if (State.isPreExistingTab(tabId)) return;
|
|
399
|
+
chrome.tabs.get(tabId, function(tab) {
|
|
400
|
+
if (chrome.runtime.lastError || !tab) return;
|
|
401
|
+
if (tab.groupId) return;
|
|
402
|
+
Logger.info('[Monitor] Tab', tabId, 'has no group, regrouping for client:', clientId);
|
|
403
|
+
var baseName = CDPUtils.getGroupBaseName(clientId);
|
|
404
|
+
var groupId = State.getGroupIdForClient(clientId);
|
|
405
|
+
if (groupId) {
|
|
406
|
+
chrome.tabs.group({ tabIds: tabId, groupId: groupId }, function() {});
|
|
407
|
+
} else {
|
|
408
|
+
chrome.tabs.group({ tabIds: tabId }, function(newGroupId) {
|
|
409
|
+
if (chrome.runtime.lastError || !newGroupId) return;
|
|
410
|
+
chrome.tabGroups.update(newGroupId, {
|
|
411
|
+
title: baseName,
|
|
412
|
+
color: CDPUtils.getGroupColorForClient(clientId),
|
|
413
|
+
collapsed: true
|
|
414
|
+
}, function() {
|
|
415
|
+
State.setGroupIdForClient(clientId, newGroupId);
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
}, 10000);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function stopGroupMonitor() {
|
|
425
|
+
if (_groupMonitorTimer) {
|
|
426
|
+
clearInterval(_groupMonitorTimer);
|
|
427
|
+
_groupMonitorTimer = null;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
381
431
|
function handleServerRestart() {
|
|
382
432
|
Logger.info('[WS] Server restarted, cleaning up all state...');
|
|
383
433
|
|
|
@@ -44,7 +44,8 @@ var CDPUtils = (function() {
|
|
|
44
44
|
|
|
45
45
|
function buildGroupName(clientId) {
|
|
46
46
|
if (!clientId) return 'CDP';
|
|
47
|
-
|
|
47
|
+
var suffix = clientId.length > 8 ? clientId.substring(clientId.length - 8) : clientId;
|
|
48
|
+
return 'CDP-' + suffix;
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
function getGroupBaseName(clientId) {
|
package/package.json
CHANGED
package/server/proxy-server.js
CHANGED
|
@@ -890,10 +890,12 @@ function handleClientConnection(ws, clientInfo, customClientId = null) {
|
|
|
890
890
|
|
|
891
891
|
// 为每个请求分配全局唯一 ID,避免多客户端 ID 冲突
|
|
892
892
|
let modifiedData = data;
|
|
893
|
+
let originalId = null;
|
|
894
|
+
let globalId = null;
|
|
893
895
|
if (parsed && parsed.id !== undefined) {
|
|
894
|
-
|
|
896
|
+
originalId = parsed.id;
|
|
895
897
|
globalRequestIdCounter++;
|
|
896
|
-
|
|
898
|
+
globalId = globalRequestIdCounter;
|
|
897
899
|
|
|
898
900
|
// 保存映射:全局ID -> {clientId, originalId, sessionId}
|
|
899
901
|
// 如果请求有 sessionId,也保存它,用于响应路由
|
|
@@ -922,11 +924,36 @@ function handleClientConnection(ws, clientInfo, customClientId = null) {
|
|
|
922
924
|
}
|
|
923
925
|
console.log(`[PENDING CREATE TARGET] Request id=${parsed.id} from client=${id}`);
|
|
924
926
|
}
|
|
925
|
-
if (parsed && parsed.
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
927
|
+
if (parsed && parsed.id !== undefined) {
|
|
928
|
+
if (parsed.method === 'Target.closeTarget') {
|
|
929
|
+
const targetId = parsed.params?.targetId;
|
|
930
|
+
const ownerClient = targetId ? targetIdToClientId.get(targetId) : null;
|
|
931
|
+
if (ownerClient && ownerClient !== id) {
|
|
932
|
+
console.log(`[BLOCKED] ${parsed.method} targetId=${targetId?.substring(0,8)} owner=${ownerClient?.substring(0,8)} requester=${id?.substring(0,8)} — not owner`);
|
|
933
|
+
const errMsg = JSON.stringify({
|
|
934
|
+
id: originalId,
|
|
935
|
+
error: { code: -32000, message: 'Target is owned by another client' }
|
|
936
|
+
});
|
|
937
|
+
safeSend(ws, errMsg, 'client');
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
const currentMapping = globalRequestIdMap.get(parsed.id);
|
|
941
|
+
if (currentMapping) {
|
|
942
|
+
currentMapping.method = 'Target.closeTarget';
|
|
943
|
+
currentMapping.closeTargetId = targetId;
|
|
944
|
+
}
|
|
945
|
+
} else if (parsed.method === 'Target.attachToTarget') {
|
|
946
|
+
const targetId = parsed.params?.targetId;
|
|
947
|
+
const ownerClient = targetId ? targetIdToClientId.get(targetId) : null;
|
|
948
|
+
if (ownerClient && ownerClient !== id) {
|
|
949
|
+
console.log(`[BLOCKED] ${parsed.method} targetId=${targetId?.substring(0,8)} owner=${ownerClient?.substring(0,8)} requester=${id?.substring(0,8)} — not owner`);
|
|
950
|
+
const errMsg = JSON.stringify({
|
|
951
|
+
id: originalId,
|
|
952
|
+
error: { code: -32000, message: 'Target is owned by another client' }
|
|
953
|
+
});
|
|
954
|
+
safeSend(ws, errMsg, 'client');
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
930
957
|
}
|
|
931
958
|
}
|
|
932
959
|
|