cdp-tunnel 2.7.3 → 2.7.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.
@@ -141,8 +141,11 @@ var SpecialHandler = (function() {
141
141
 
142
142
  function groupTabSilently(tabId, clientId) {
143
143
  return new Promise(function(resolve) {
144
- addTabToAutomationGroup(tabId, clientId);
145
- // 分组操作是异步的,给一点时间让 tab 被收进折叠的 group
144
+ try {
145
+ addTabToAutomationGroup(tabId, clientId);
146
+ } catch (e) {
147
+ Logger.error('[TabGroup] addTabToAutomationGroup threw:', e.message || e);
148
+ }
146
149
  setTimeout(resolve, 100);
147
150
  });
148
151
  }
@@ -165,7 +168,11 @@ var SpecialHandler = (function() {
165
168
  WebSocketManager.send({ type: 'tabgroup-debug', tabId: tabId, clientId: clientId, phase: 'start' });
166
169
 
167
170
  setTimeout(function() {
168
- muteTabIfNeeded(tabId);
171
+ try {
172
+ muteTabIfNeeded(tabId);
173
+ } catch (e) {
174
+ Logger.error('[TabGroup] muteTabIfNeeded threw:', e.message || e);
175
+ }
169
176
  }, 200);
170
177
 
171
178
  var groupClientId = clientId;
@@ -188,6 +195,11 @@ var SpecialHandler = (function() {
188
195
  function doGroup(tabId, clientId, baseName, retries) {
189
196
  retries = retries || 0;
190
197
  Logger.info('[TabGroup] doGroup: tabId=' + tabId + ' clientId=' + (clientId || 'none') + ' baseName=' + baseName + ' retry=' + retries);
198
+ if (!chrome.tabGroups) {
199
+ Logger.warn('[TabGroup] chrome.tabGroups API not available (headless mode?), skipping grouping for tab:', tabId);
200
+ EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'skip', reason: 'tabGroups-unavailable', tabId: tabId });
201
+ return;
202
+ }
191
203
  chrome.tabGroups.query({}, function(allGroups) {
192
204
  if (chrome.runtime.lastError) {
193
205
  Logger.error('[TabGroup] tabGroups.query failed:', chrome.runtime.lastError.message);
@@ -223,21 +235,26 @@ var SpecialHandler = (function() {
223
235
  }
224
236
  Logger.info('[TabGroup] chrome.tabs.group returned groupId:', groupId);
225
237
  EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'groupCreated', tabId: tabId, groupId: groupId });
226
- if (groupId) {
227
- chrome.tabGroups.update(groupId, {
228
- title: baseName,
229
- color: CDPUtils.getGroupColorForClient(clientId),
230
- collapsed: true
231
- }, function() {
232
- if (chrome.runtime.lastError) {
233
- Logger.error('[TabGroup] Failed to update group:', chrome.runtime.lastError.message);
234
- EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'updateGroup', error: chrome.runtime.lastError.message, groupId: groupId });
235
- } else {
236
- State.setGroupIdForClient(clientId, groupId);
237
- updateTabGroupName(clientId);
238
- Logger.info('[TabGroup] Created new group:', groupId, 'with tab:', tabId);
239
- }
240
- });
238
+ if (groupId) {
239
+ if (chrome.tabGroups) {
240
+ chrome.tabGroups.update(groupId, {
241
+ title: baseName,
242
+ color: CDPUtils.getGroupColorForClient(clientId),
243
+ collapsed: true
244
+ }, function() {
245
+ if (chrome.runtime.lastError) {
246
+ Logger.error('[TabGroup] Failed to update group:', chrome.runtime.lastError.message);
247
+ EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'updateGroup', error: chrome.runtime.lastError.message, groupId: groupId });
248
+ } else {
249
+ State.setGroupIdForClient(clientId, groupId);
250
+ updateTabGroupName(clientId);
251
+ Logger.info('[TabGroup] Group updated:', groupId, baseName);
252
+ }
253
+ });
254
+ } else {
255
+ State.setGroupIdForClient(clientId, groupId);
256
+ Logger.info('[TabGroup] Group created but tabGroups.update unavailable (headless):', groupId);
257
+ }
241
258
  } else {
242
259
  Logger.error('[TabGroup] chrome.tabs.group returned null groupId');
243
260
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "CDP Bridge",
4
- "version": "2.7.3",
4
+ "version": "2.7.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:23297/plugin',
2
+ WS_URL: 'ws://localhost:9221/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.7.3",
3
+ "version": "2.7.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",
@@ -788,24 +788,34 @@ function handlePluginConnection(ws, clientInfo, request) {
788
788
  } else if (targetId && (parsed.method === 'Target.targetCreated' || parsed.method === 'Target.attachedToTarget')) {
789
789
  const pendingMap = parsed.method === 'Target.targetCreated' ? ns.pendingTargetCreatedEvents : ns.pendingAttachedEvents;
790
790
 
791
- let routedToDiscoverer = false;
792
- if (ns.discoveringClientIds.size > 0) {
793
- for (const [discClientId, timestamp] of ns.discoveringClientIds) {
794
- if (Date.now() - timestamp < 30000) {
795
- const discWs = clientById.get(discClientId);
796
- if (discWs && discWs.readyState === WebSocket.OPEN) {
797
- discWs.send(cdpData);
798
- routedToDiscoverer = true;
791
+ // Check if there's a pending Target.createTarget from any client.
792
+ // If so, cache this event — createTarget response will deliver it to the right client.
793
+ // If not, broadcast to discovering clients (for emitAutoAttachForExistingTargets etc.)
794
+ const hasPendingCreateTarget = Array.from(globalRequestIdMap.values()).some(m => m.isCreateTarget);
795
+
796
+ if (hasPendingCreateTarget) {
797
+ pendingMap.set(targetId, { parsed: JSON.parse(JSON.stringify(parsed)), cdpData });
798
+ console.log(`[TARGET EVENT PENDING] ${parsed.method} targetId=${targetId?.substring(0,8) || 'none'} (cached, waiting for createTarget response)`);
799
+ } else {
800
+ // Broadcast to discovering clients
801
+ let routedToDiscoverer = false;
802
+ if (ns.discoveringClientIds.size > 0) {
803
+ for (const [discClientId, timestamp] of ns.discoveringClientIds) {
804
+ if (Date.now() - timestamp < 30000) {
805
+ const discWs = clientById.get(discClientId);
806
+ if (discWs && discWs.readyState === WebSocket.OPEN) {
807
+ discWs.send(cdpData);
808
+ routedToDiscoverer = true;
809
+ }
810
+ } else {
811
+ ns.discoveringClientIds.delete(discClientId);
799
812
  }
800
- } else {
801
- ns.discoveringClientIds.delete(discClientId);
802
813
  }
803
814
  }
804
- }
805
-
806
- if (!routedToDiscoverer) {
807
- pendingMap.set(targetId, { parsed: JSON.parse(JSON.stringify(parsed)), cdpData });
808
- console.log(`[TARGET EVENT PENDING] ${parsed.method} targetId=${targetId?.substring(0,8)} (cached, waiting for createTarget response)`);
815
+ if (!routedToDiscoverer) {
816
+ pendingMap.set(targetId, { parsed: JSON.parse(JSON.stringify(parsed)), cdpData });
817
+ console.log(`[TARGET EVENT PENDING] ${parsed.method} targetId=${targetId?.substring(0,8) || 'none'} (cached, no discoverer)`);
818
+ }
809
819
  }
810
820
  } else {
811
821
  console.log(`[TARGET EVENT DROPPED] ${parsed.method} targetId=${targetId?.substring(0,8) || 'none'} (no owner, dropped for isolation)`);
@@ -818,7 +828,7 @@ function handlePluginConnection(ws, clientInfo, request) {
818
828
  const sessionId = parsed.params?.sessionId;
819
829
 
820
830
  if (targetId && sessionId) {
821
- const clientId = ws.pairedClientId;
831
+ const clientId = ns.targetIdToClientId.get(targetId) || ws.pairedClientId;
822
832
  if (clientId) {
823
833
  ns.sessionToClientId.set(sessionId, clientId);
824
834
  console.log(`[SESSION MAPPED] sessionId=${sessionId?.substring(0,8) || 'none'} -> clientId=${clientId?.substring(0,8) || 'none'}`);