cdp-tunnel 2.5.3 → 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.
@@ -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
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "CDP Bridge",
4
- "version": "2.5.3",
4
+ "version": "2.5.4",
5
5
  "description": "Chrome DevTools Protocol Bridge for Playwright/Puppeteer automation",
6
6
  "permissions": [
7
7
  "debugger",
@@ -1,5 +1,5 @@
1
1
  var Config = {
2
- WS_URL: 'ws://localhost:25429/plugin',
2
+ WS_URL: 'ws://localhost:37171/plugin',
3
3
  RECONNECT_DELAY: 3000,
4
4
  DEBUGGER_VERSION: '1.3',
5
5
  HEARTBEAT_INTERVAL: 25000,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdp-tunnel",
3
- "version": "2.5.3",
3
+ "version": "2.5.4",
4
4
  "description": "Bridge Chrome's debugger API to WebSocket — control your existing browser with Playwright/Puppeteer via CDP",
5
5
  "main": "server/proxy-server.js",
6
6
  "bin": "./cli/index.js",
@@ -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
- const originalId = parsed.id;
896
+ originalId = parsed.id;
895
897
  globalRequestIdCounter++;
896
- const globalId = globalRequestIdCounter;
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.method === 'Target.closeTarget' && parsed.id !== undefined) {
926
- const currentMapping = globalRequestIdMap.get(parsed.id);
927
- if (currentMapping) {
928
- currentMapping.method = 'Target.closeTarget';
929
- currentMapping.closeTargetId = parsed.params?.targetId;
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