cdp-tunnel 3.2.7 → 3.3.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.
|
@@ -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 端口一个
|
|
@@ -204,57 +205,42 @@ class PortPoolManager {
|
|
|
204
205
|
const SYNTHETIC_INPUT = ['Input.dispatchKeyEvent', 'Input.dispatchMouseEvent'];
|
|
205
206
|
|
|
206
207
|
// 消息处理:client → plugin(带 portIndex 标记)
|
|
207
|
-
|
|
208
|
-
const handleMessage = async (data) => {
|
|
208
|
+
ws.on('message', async (data) => {
|
|
209
209
|
let msg;
|
|
210
210
|
try { msg = JSON.parse(data.toString()); } catch { return; }
|
|
211
211
|
|
|
212
212
|
if (msg.id !== undefined) {
|
|
213
|
-
// createTarget
|
|
214
|
-
if (msg.method === 'Target.createTarget'
|
|
215
|
-
await session.
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
// attachToTarget:已 attach 的 target 返回虚拟 session
|
|
219
|
-
if (msg.method === 'Target.attachToTarget' && msg.params && msg.params.targetId) {
|
|
220
|
-
const targetId = msg.params.targetId;
|
|
221
|
-
if (session.attachedTargets && session.attachedTargets.has(targetId)) {
|
|
222
|
-
const vsid = `vs_${session.portIndex}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
223
|
-
session.virtualSessions.set(vsid, targetId);
|
|
224
|
-
this.sessionToPort.set(vsid, session.portIndex);
|
|
225
|
-
ws.send(JSON.stringify({ id: msg.id, result: { sessionId: vsid } }));
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
if (!session.attachedTargets) session.attachedTargets = new Set();
|
|
229
|
-
session.attachedTargets.add(targetId);
|
|
213
|
+
// createTarget 串行化(避免并发 chrome.tabs.create 回调串)
|
|
214
|
+
if (msg.method === 'Target.createTarget') {
|
|
215
|
+
while (session.createTargetLock) { await session.createTargetLock; }
|
|
216
|
+
session.createTargetLock = new Promise(r => { session._releaseCreateTarget = r; });
|
|
230
217
|
}
|
|
231
218
|
|
|
219
|
+
// 合成输入命令:先 bringToFront + 等待,再发原命令
|
|
232
220
|
if (SYNTHETIC_INPUT.indexOf(msg.method) >= 0 && msg.sessionId) {
|
|
233
221
|
await this._ensureVisible(session, pluginWs, msg.sessionId);
|
|
234
222
|
}
|
|
235
223
|
|
|
236
|
-
//
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const newId = `pool${session.portIndex}_${msg.id}`;
|
|
224
|
+
// 命令:分配全局唯一 id(避免不同 client 的 msg.id 冲突)
|
|
225
|
+
const uniqueId = ++this.idCounter;
|
|
226
|
+
const newId = `pool${session.portIndex}_${uniqueId}`;
|
|
227
|
+
// 记录 originalId(用于响应时恢复)
|
|
228
|
+
if (!ws._origIds) ws._origIds = new Map();
|
|
229
|
+
ws._origIds.set(uniqueId, msg.id);
|
|
244
230
|
session.pendingRequests.set(newId, {
|
|
245
|
-
originalId: msg.id,
|
|
246
|
-
|
|
231
|
+
originalId: msg.id,
|
|
232
|
+
method: msg.method,
|
|
233
|
+
clientWs: ws,
|
|
234
|
+
params: msg.params,
|
|
235
|
+
sessionId: msg.sessionId
|
|
247
236
|
});
|
|
237
|
+
|
|
248
238
|
const forwarded = { ...msg, id: newId, __portIndex: session.portIndex, __clientId: `pool_${session.port}` };
|
|
249
239
|
pluginWs.send(JSON.stringify(forwarded));
|
|
250
240
|
} else {
|
|
241
|
+
// 无 id 的消息(事件),直接转发
|
|
251
242
|
pluginWs.send(JSON.stringify({ ...msg, __portIndex: session.portIndex }));
|
|
252
243
|
}
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
ws.on('message', (data) => {
|
|
256
|
-
if (!session.cmdQueue) session.cmdQueue = Promise.resolve();
|
|
257
|
-
session.cmdQueue = session.cmdQueue.then(() => handleMessage(data)).catch(() => {});
|
|
258
244
|
});
|
|
259
245
|
|
|
260
246
|
ws.on('close', () => {
|
|
@@ -292,18 +278,21 @@ class PortPoolManager {
|
|
|
292
278
|
const pending = session.pendingRequests.get(msg.id);
|
|
293
279
|
session.pendingRequests.delete(msg.id);
|
|
294
280
|
|
|
295
|
-
// 如果是 createTarget
|
|
281
|
+
// 如果是 createTarget 响应
|
|
282
|
+
if (pending && pending.method === 'Target.createTarget') {
|
|
283
|
+
console.log('[PORT POOL] createTarget resp: ' + JSON.stringify(msg.result).slice(0, 80) + ' pending=' + !!pending);
|
|
284
|
+
}
|
|
296
285
|
if (msg.result && msg.result.targetId) {
|
|
297
286
|
const tid = msg.result.targetId;
|
|
298
287
|
session.targetIds.add(tid);
|
|
299
288
|
session.targetUrls.set(tid, pending?.params?.url || 'about:blank');
|
|
300
289
|
this.targetToPort.set(tid, portIndex);
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
290
|
+
// 释放 createTarget 锁
|
|
291
|
+
if (session._releaseCreateTarget) {
|
|
292
|
+
session._releaseCreateTarget();
|
|
293
|
+
session._releaseCreateTarget = null;
|
|
294
|
+
session.createTargetLock = null;
|
|
295
|
+
}
|
|
307
296
|
}
|
|
308
297
|
|
|
309
298
|
// 如果是 Page.navigate 响应,更新 targetId 的 url
|
|
@@ -330,7 +319,7 @@ class PortPoolManager {
|
|
|
330
319
|
}
|
|
331
320
|
|
|
332
321
|
// 恢复原始 id,发给发起请求的 client
|
|
333
|
-
const response = { ...msg, id: this._parseOriginalId(originalId) };
|
|
322
|
+
const response = { ...msg, id: pending ? pending.originalId : this._parseOriginalId(originalId) };
|
|
334
323
|
delete response.__portIndex;
|
|
335
324
|
delete response.__clientId;
|
|
336
325
|
delete response.type;
|