cdp-tunnel 3.3.0 → 3.3.2
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.
|
@@ -161,11 +161,24 @@ var SpecialHandler = (function() {
|
|
|
161
161
|
var needsNavigate = url !== 'about:blank' && url !== '';
|
|
162
162
|
|
|
163
163
|
return new Promise(function(resolve, reject) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
164
|
+
var retryCount = 0;
|
|
165
|
+
var maxRetries = 3;
|
|
166
|
+
|
|
167
|
+
function doCreate() {
|
|
168
|
+
chrome.tabs.create({ url: 'about:blank', active: false }, function(tab) {
|
|
169
|
+
if (!tab || !tab.id) {
|
|
170
|
+
retryCount++;
|
|
171
|
+
if (retryCount <= maxRetries) {
|
|
172
|
+
Logger.warn('[CreateTarget] Empty tab (tab=' + (!!tab) + '), retry ' + retryCount);
|
|
173
|
+
setTimeout(doCreate, 100 * retryCount);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
Logger.error('[CreateTarget] Failed after ' + maxRetries + ' retries');
|
|
177
|
+
reject(new Error('Failed to create tab after ' + maxRetries + ' retries'));
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
Logger.info('[CreateTarget] tab created: ' + tab.id);
|
|
169
182
|
|
|
170
183
|
if (clientId) {
|
|
171
184
|
state.setTabIdToClientId(tab.id, clientId);
|
|
@@ -189,7 +202,10 @@ var SpecialHandler = (function() {
|
|
|
189
202
|
Logger.error('[CreateTarget] Error:', err.message || err);
|
|
190
203
|
reject(err);
|
|
191
204
|
});
|
|
192
|
-
|
|
205
|
+
}); // chrome.tabs.create callback end
|
|
206
|
+
} // doCreate end
|
|
207
|
+
|
|
208
|
+
doCreate();
|
|
193
209
|
});
|
|
194
210
|
}
|
|
195
211
|
|
package/package.json
CHANGED
|
@@ -20,7 +20,8 @@ const { CONFIG } = require('./config');
|
|
|
20
20
|
|
|
21
21
|
class PortPoolManager {
|
|
22
22
|
constructor(mainProxy) {
|
|
23
|
-
this.mainProxy = mainProxy;
|
|
23
|
+
this.mainProxy = mainProxy;
|
|
24
|
+
this.idCounter = 0; // 全局唯一 id 计数器 // 现有 proxy 的引用(拿 plugin 连接)
|
|
24
25
|
this.createServers = []; // [http.Server] 每个 create 端口一个
|
|
25
26
|
this.createWss = []; // [WebSocket.Server] 每个 create 端口一个
|
|
26
27
|
this.portSessions = []; // [PortSession] 每个 create 端口一个
|
|
@@ -209,10 +210,11 @@ class PortPoolManager {
|
|
|
209
210
|
try { msg = JSON.parse(data.toString()); } catch { return; }
|
|
210
211
|
|
|
211
212
|
if (msg.id !== undefined) {
|
|
212
|
-
// createTarget
|
|
213
|
+
// createTarget 串行化 + 标记 pending
|
|
213
214
|
if (msg.method === 'Target.createTarget') {
|
|
214
215
|
while (session.createTargetLock) { await session.createTargetLock; }
|
|
215
216
|
session.createTargetLock = new Promise(r => { session._releaseCreateTarget = r; });
|
|
217
|
+
session.pendingCreate = true; // 标记:下一个 targetCreated 事件归属这个端口
|
|
216
218
|
}
|
|
217
219
|
|
|
218
220
|
// 合成输入命令:先 bringToFront + 等待,再发原命令
|
|
@@ -220,8 +222,12 @@ class PortPoolManager {
|
|
|
220
222
|
await this._ensureVisible(session, pluginWs, msg.sessionId);
|
|
221
223
|
}
|
|
222
224
|
|
|
223
|
-
//
|
|
224
|
-
const
|
|
225
|
+
// 命令:分配全局唯一 id(避免不同 client 的 msg.id 冲突)
|
|
226
|
+
const uniqueId = ++this.idCounter;
|
|
227
|
+
const newId = `pool${session.portIndex}_${uniqueId}`;
|
|
228
|
+
// 记录 originalId(用于响应时恢复)
|
|
229
|
+
if (!ws._origIds) ws._origIds = new Map();
|
|
230
|
+
ws._origIds.set(uniqueId, msg.id);
|
|
225
231
|
session.pendingRequests.set(newId, {
|
|
226
232
|
originalId: msg.id,
|
|
227
233
|
method: msg.method,
|
|
@@ -273,7 +279,10 @@ class PortPoolManager {
|
|
|
273
279
|
const pending = session.pendingRequests.get(msg.id);
|
|
274
280
|
session.pendingRequests.delete(msg.id);
|
|
275
281
|
|
|
276
|
-
// 如果是 createTarget
|
|
282
|
+
// 如果是 createTarget 响应
|
|
283
|
+
if (pending && pending.method === 'Target.createTarget') {
|
|
284
|
+
console.log('[PORT POOL] createTarget resp: ' + JSON.stringify(msg.result).slice(0, 80) + ' pending=' + !!pending);
|
|
285
|
+
}
|
|
277
286
|
if (msg.result && msg.result.targetId) {
|
|
278
287
|
const tid = msg.result.targetId;
|
|
279
288
|
session.targetIds.add(tid);
|
|
@@ -311,7 +320,7 @@ class PortPoolManager {
|
|
|
311
320
|
}
|
|
312
321
|
|
|
313
322
|
// 恢复原始 id,发给发起请求的 client
|
|
314
|
-
const response = { ...msg, id: this._parseOriginalId(originalId) };
|
|
323
|
+
const response = { ...msg, id: pending ? pending.originalId : this._parseOriginalId(originalId) };
|
|
315
324
|
delete response.__portIndex;
|
|
316
325
|
delete response.__clientId;
|
|
317
326
|
delete response.type;
|
|
@@ -340,6 +349,19 @@ class PortPoolManager {
|
|
|
340
349
|
return true;
|
|
341
350
|
}
|
|
342
351
|
}
|
|
352
|
+
// 竞态处理:targetCreated 在 createTarget 响应之前到达
|
|
353
|
+
// 如果有 pendingCreate,把事件归属到对应端口
|
|
354
|
+
for (let pi = 0; pi < this.portSessions.length; pi++) {
|
|
355
|
+
const sess = this.portSessions[pi];
|
|
356
|
+
if (sess && sess.pendingCreate) {
|
|
357
|
+
sess.targetIds.add(targetId);
|
|
358
|
+
sess.targetUrls.set(targetId, 'about:blank');
|
|
359
|
+
this.targetToPort.set(targetId, pi);
|
|
360
|
+
sess.pendingCreate = false; // 消费掉
|
|
361
|
+
this._broadcastToPort(pi, msg);
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
343
365
|
}
|
|
344
366
|
|
|
345
367
|
// sessionId 路由(Network/Screencast/Input 等 session 事件)
|