cdp-tunnel 2.7.9 → 2.8.0
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/background.js +234 -130
- package/extension-new/cdp/handler/forward.js +9 -7
- package/extension-new/cdp/handler/local.js +60 -39
- package/extension-new/cdp/handler/special.js +145 -119
- package/extension-new/cdp/index.js +16 -7
- package/extension-new/cdp/response.js +12 -4
- package/extension-new/config-page-preview.html +174 -57
- package/extension-new/config-page.js +169 -70
- package/extension-new/core/connection-manager.js +120 -0
- package/extension-new/core/connection-state.js +355 -0
- package/extension-new/core/debugger.js +65 -52
- package/extension-new/core/state.js +87 -438
- package/extension-new/core/websocket.js +345 -279
- package/extension-new/features/screencast.js +42 -20
- package/extension-new/manifest.json +3 -2
- package/extension-new/utils/config.js +83 -2
- package/extension-new/utils/helpers.js +5 -4
- package/package.json +1 -1
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
var SpecialHandler = (function() {
|
|
2
2
|
var _groupQueue = new Map();
|
|
3
3
|
|
|
4
|
+
function _getState(ctx) {
|
|
5
|
+
return ctx._state;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function _getWSManager(ctx) {
|
|
9
|
+
return ctx._wsManager;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function _getConnectionTag(ctx) {
|
|
13
|
+
var wm = ctx._wsManager;
|
|
14
|
+
return (wm && wm.config && wm.config.tag) || null;
|
|
15
|
+
}
|
|
16
|
+
|
|
4
17
|
function muteTabIfNeeded(tabId) {
|
|
5
18
|
Config.getAutoMute(function(enabled) {
|
|
6
19
|
if (!enabled) return;
|
|
@@ -15,8 +28,9 @@ var SpecialHandler = (function() {
|
|
|
15
28
|
}
|
|
16
29
|
|
|
17
30
|
function targetSetAutoAttach(context) {
|
|
31
|
+
var state = _getState(context);
|
|
18
32
|
var params = context.params;
|
|
19
|
-
|
|
33
|
+
state.setAutoAttachConfig({
|
|
20
34
|
autoAttach: !!(params && params.autoAttach),
|
|
21
35
|
waitForDebuggerOnStart: !!(params && params.waitForDebuggerOnStart),
|
|
22
36
|
flatten: !(params && params.flatten === false)
|
|
@@ -31,6 +45,7 @@ var SpecialHandler = (function() {
|
|
|
31
45
|
}
|
|
32
46
|
|
|
33
47
|
function targetAttachToTarget(context) {
|
|
48
|
+
var state = _getState(context);
|
|
34
49
|
var params = context.params;
|
|
35
50
|
var targetId = params && params.targetId;
|
|
36
51
|
var clientId = context.clientId;
|
|
@@ -43,31 +58,32 @@ var SpecialHandler = (function() {
|
|
|
43
58
|
throw new Error('Target not found');
|
|
44
59
|
}
|
|
45
60
|
|
|
46
|
-
var isAlreadyAttached =
|
|
61
|
+
var isAlreadyAttached = state.isTabAttached(tabId);
|
|
47
62
|
|
|
48
63
|
if (isAlreadyAttached) {
|
|
49
64
|
var newSessionId = CDPUtils.generateSessionId();
|
|
50
|
-
|
|
65
|
+
state.mapSession(newSessionId, tabId, targetId);
|
|
51
66
|
muteTabIfNeeded(tabId);
|
|
52
67
|
Logger.info('[CDP] Created additional session:', newSessionId, 'for tab:', tabId);
|
|
53
68
|
return { sessionId: newSessionId };
|
|
54
69
|
}
|
|
55
70
|
|
|
56
|
-
return DebuggerManager.attach(tabId).then(function(attached) {
|
|
71
|
+
return DebuggerManager.attach(tabId, state).then(function(attached) {
|
|
57
72
|
if (!attached) {
|
|
58
73
|
throw new Error('Failed to attach');
|
|
59
74
|
}
|
|
60
75
|
|
|
61
76
|
var sessionId = CDPUtils.generateSessionId();
|
|
62
|
-
|
|
77
|
+
state.mapSession(sessionId, tabId, targetId);
|
|
63
78
|
|
|
64
79
|
if (clientId) {
|
|
65
|
-
|
|
80
|
+
state.setTabIdToClientId(tabId, clientId);
|
|
66
81
|
}
|
|
67
82
|
|
|
68
|
-
if (
|
|
69
|
-
addTabToAutomationGroup(tabId, clientId);
|
|
70
|
-
} else {
|
|
83
|
+
if (state.isCDPCreatedTab(tabId)) {
|
|
84
|
+
addTabToAutomationGroup(tabId, clientId, null, context);
|
|
85
|
+
} else {
|
|
86
|
+
state.addPreExistingTab(tabId);
|
|
71
87
|
Logger.info('[CDP] Target.attachToTarget: user tab not CDP-created, treating as pre-existing. tabId:', tabId);
|
|
72
88
|
}
|
|
73
89
|
|
|
@@ -77,17 +93,18 @@ var SpecialHandler = (function() {
|
|
|
77
93
|
}
|
|
78
94
|
|
|
79
95
|
function targetDetachFromTarget(context) {
|
|
96
|
+
var state = _getState(context);
|
|
80
97
|
var params = context.params;
|
|
81
98
|
var sessionId = params && params.sessionId;
|
|
82
99
|
if (!sessionId) {
|
|
83
100
|
return Promise.resolve({});
|
|
84
101
|
}
|
|
85
102
|
|
|
86
|
-
var tabId =
|
|
87
|
-
|
|
103
|
+
var tabId = state.getTabIdBySession(sessionId);
|
|
104
|
+
state.unmapSession(sessionId);
|
|
88
105
|
|
|
89
|
-
if (tabId && !
|
|
90
|
-
return DebuggerManager.detach(tabId).then(function() {
|
|
106
|
+
if (tabId && !state.hasOtherSessionForTab(tabId)) {
|
|
107
|
+
return DebuggerManager.detach(tabId, state).then(function() {
|
|
91
108
|
return {};
|
|
92
109
|
}).catch(function() {
|
|
93
110
|
return {};
|
|
@@ -97,6 +114,8 @@ var SpecialHandler = (function() {
|
|
|
97
114
|
}
|
|
98
115
|
|
|
99
116
|
function targetCreateTarget(context) {
|
|
117
|
+
var state = _getState(context);
|
|
118
|
+
var wsManager = _getWSManager(context);
|
|
100
119
|
var params = context.params;
|
|
101
120
|
var url = (params && params.url) || 'about:blank';
|
|
102
121
|
var browserContextId = (params && params.browserContextId) || 'default';
|
|
@@ -104,7 +123,6 @@ var SpecialHandler = (function() {
|
|
|
104
123
|
var needsNavigate = url !== 'about:blank' && url !== '';
|
|
105
124
|
|
|
106
125
|
return new Promise(function(resolve, reject) {
|
|
107
|
-
// Step 1: 先创建 about:blank (不加载任何资源,tab bar 闪烁最小)
|
|
108
126
|
chrome.tabs.create({ url: 'about:blank', active: false }, function(tab) {
|
|
109
127
|
if (!tab || !tab.id) {
|
|
110
128
|
reject(new Error('Failed to create tab'));
|
|
@@ -112,19 +130,16 @@ var SpecialHandler = (function() {
|
|
|
112
130
|
}
|
|
113
131
|
|
|
114
132
|
if (clientId) {
|
|
115
|
-
|
|
133
|
+
state.setTabIdToClientId(tab.id, clientId);
|
|
116
134
|
}
|
|
117
135
|
|
|
118
|
-
|
|
136
|
+
state.addCDPCreatedTab(tab.id);
|
|
119
137
|
|
|
120
|
-
|
|
121
|
-
groupTabSilently(tab.id, clientId).then(function() {
|
|
122
|
-
// Step 3: 获取 targetId 并 attach debugger
|
|
138
|
+
groupTabSilently(tab.id, clientId, context).then(function() {
|
|
123
139
|
return getTargetIdByTabId(tab.id).then(function(targetId) {
|
|
124
|
-
return emitAutoAttachEvents(tab.id, targetId, browserContextId).then(function() {
|
|
125
|
-
// Step 4: 折叠+attach 完成后,再导航到真实 URL
|
|
140
|
+
return emitAutoAttachEvents(tab.id, targetId, browserContextId, context).then(function() {
|
|
126
141
|
if (needsNavigate) {
|
|
127
|
-
|
|
142
|
+
state.addPendingCreatedTabUrl(url);
|
|
128
143
|
return navigateTabQuietly(tab.id, url).then(function() {
|
|
129
144
|
resolve({ targetId: targetId });
|
|
130
145
|
});
|
|
@@ -140,11 +155,11 @@ var SpecialHandler = (function() {
|
|
|
140
155
|
});
|
|
141
156
|
}
|
|
142
157
|
|
|
143
|
-
function groupTabSilently(tabId, clientId) {
|
|
158
|
+
function groupTabSilently(tabId, clientId, context) {
|
|
144
159
|
return new Promise(function(resolve) {
|
|
145
160
|
addTabToAutomationGroup(tabId, clientId, function(success) {
|
|
146
161
|
setTimeout(resolve, 50);
|
|
147
|
-
});
|
|
162
|
+
}, context);
|
|
148
163
|
});
|
|
149
164
|
}
|
|
150
165
|
|
|
@@ -154,13 +169,12 @@ var SpecialHandler = (function() {
|
|
|
154
169
|
if (chrome.runtime.lastError) {
|
|
155
170
|
Logger.warn('[NavigateQuietly] Failed:', chrome.runtime.lastError.message);
|
|
156
171
|
}
|
|
157
|
-
// 不管成功失败都 resolve,让调用者继续
|
|
158
172
|
resolve();
|
|
159
173
|
});
|
|
160
174
|
});
|
|
161
175
|
}
|
|
162
176
|
|
|
163
|
-
function addTabToAutomationGroup(tabId, clientId, callback) {
|
|
177
|
+
function addTabToAutomationGroup(tabId, clientId, callback, context) {
|
|
164
178
|
var key = clientId || '__no_client__';
|
|
165
179
|
var prev = _groupQueue.get(key) || Promise.resolve();
|
|
166
180
|
|
|
@@ -173,7 +187,7 @@ var SpecialHandler = (function() {
|
|
|
173
187
|
_addTabToAutomationGroupInner(tabId, clientId, function(success) {
|
|
174
188
|
clearTimeout(timeoutId);
|
|
175
189
|
resolve(success);
|
|
176
|
-
});
|
|
190
|
+
}, context);
|
|
177
191
|
});
|
|
178
192
|
}).catch(function(err) {
|
|
179
193
|
Logger.error('[addTabToAutomationGroup] queue error:', err.message || err);
|
|
@@ -192,10 +206,15 @@ var SpecialHandler = (function() {
|
|
|
192
206
|
}
|
|
193
207
|
}
|
|
194
208
|
|
|
195
|
-
function _addTabToAutomationGroupInner(tabId, clientId, callback) {
|
|
209
|
+
function _addTabToAutomationGroupInner(tabId, clientId, callback, context) {
|
|
210
|
+
var state = context ? _getState(context) : null;
|
|
211
|
+
var wsManager = context ? _getWSManager(context) : null;
|
|
212
|
+
|
|
196
213
|
Logger.info('[TabGroup] Starting addTabToAutomationGroup for tabId:', tabId, 'clientId:', clientId);
|
|
197
214
|
|
|
198
|
-
|
|
215
|
+
if (wsManager) {
|
|
216
|
+
wsManager.send({ type: 'tabgroup-debug', tabId: tabId, clientId: clientId, phase: 'start' });
|
|
217
|
+
}
|
|
199
218
|
|
|
200
219
|
setTimeout(function() {
|
|
201
220
|
try {
|
|
@@ -207,7 +226,7 @@ var SpecialHandler = (function() {
|
|
|
207
226
|
|
|
208
227
|
var groupClientId = clientId;
|
|
209
228
|
if (!groupClientId) {
|
|
210
|
-
var cdpClients =
|
|
229
|
+
var cdpClients = state ? state.getCDPClients() : [];
|
|
211
230
|
if (cdpClients.length > 0 && cdpClients[0] && cdpClients[0].id) {
|
|
212
231
|
groupClientId = cdpClients[0].id;
|
|
213
232
|
Logger.warn('[TabGroup] No clientId for tab:', tabId, 'fallback to first client:', groupClientId);
|
|
@@ -217,49 +236,53 @@ var SpecialHandler = (function() {
|
|
|
217
236
|
return;
|
|
218
237
|
}
|
|
219
238
|
}
|
|
220
|
-
var baseName = CDPUtils.getGroupBaseName(groupClientId);
|
|
239
|
+
var baseName = CDPUtils.getGroupBaseName(groupClientId, _getConnectionTag(context));
|
|
221
240
|
|
|
222
241
|
Logger.info('[TabGroup] Grouping tab immediately for:', baseName);
|
|
223
|
-
doGroup(tabId, groupClientId, baseName, 0, callback);
|
|
242
|
+
doGroup(tabId, groupClientId, baseName, 0, callback, context);
|
|
224
243
|
}
|
|
225
244
|
|
|
226
|
-
function doGroup(tabId, clientId, baseName, retries, callback) {
|
|
245
|
+
function doGroup(tabId, clientId, baseName, retries, callback, context) {
|
|
246
|
+
var state = context ? _getState(context) : null;
|
|
247
|
+
var wsManager = context ? _getWSManager(context) : null;
|
|
227
248
|
retries = retries || 0;
|
|
228
249
|
Logger.info('[TabGroup] doGroup: tabId=' + tabId + ' clientId=' + (clientId || 'none') + ' baseName=' + baseName + ' retry=' + retries);
|
|
229
250
|
if (!chrome.tabGroups) {
|
|
230
251
|
Logger.warn('[TabGroup] chrome.tabGroups API not available (headless mode?), skipping grouping for tab:', tabId);
|
|
231
|
-
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'skip', reason: 'tabGroups-unavailable', tabId: tabId });
|
|
252
|
+
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'skip', reason: 'tabGroups-unavailable', tabId: tabId }, null, wsManager);
|
|
232
253
|
if (callback) callback(false);
|
|
233
254
|
return;
|
|
234
255
|
}
|
|
235
|
-
var cachedGroupId =
|
|
256
|
+
var cachedGroupId = state ? state.getGroupIdForClient(clientId) : null;
|
|
236
257
|
if (cachedGroupId) {
|
|
237
258
|
Logger.info('[TabGroup] Using cached groupId:', cachedGroupId, 'for client:', clientId);
|
|
238
259
|
chrome.tabs.group({ tabIds: tabId, groupId: cachedGroupId }, function(result) {
|
|
239
260
|
if (!chrome.runtime.lastError) {
|
|
240
|
-
updateTabGroupName(clientId);
|
|
261
|
+
updateTabGroupName(clientId, state, wsManager);
|
|
241
262
|
Logger.info('[TabGroup] Tab', tabId, 'added to cached group:', cachedGroupId);
|
|
242
263
|
if (callback) callback(true);
|
|
243
264
|
return;
|
|
244
265
|
}
|
|
245
266
|
Logger.warn('[TabGroup] Cached groupId', cachedGroupId, 'failed:', chrome.runtime.lastError.message, '— falling back to query');
|
|
246
|
-
doGroupQuery(tabId, clientId, baseName, retries, callback);
|
|
267
|
+
doGroupQuery(tabId, clientId, baseName, retries, callback, context);
|
|
247
268
|
});
|
|
248
269
|
return;
|
|
249
270
|
}
|
|
250
|
-
doGroupQuery(tabId, clientId, baseName, retries, callback);
|
|
271
|
+
doGroupQuery(tabId, clientId, baseName, retries, callback, context);
|
|
251
272
|
}
|
|
252
273
|
|
|
253
|
-
function doGroupQuery(tabId, clientId, baseName, retries, callback) {
|
|
274
|
+
function doGroupQuery(tabId, clientId, baseName, retries, callback, context) {
|
|
275
|
+
var state = context ? _getState(context) : null;
|
|
276
|
+
var wsManager = context ? _getWSManager(context) : null;
|
|
254
277
|
chrome.tabGroups.query({}, function(allGroups) {
|
|
255
278
|
if (chrome.runtime.lastError) {
|
|
256
279
|
Logger.error('[TabGroup] tabGroups.query failed:', chrome.runtime.lastError.message);
|
|
257
|
-
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'query', error: chrome.runtime.lastError.message });
|
|
280
|
+
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'query', error: chrome.runtime.lastError.message }, null, wsManager);
|
|
258
281
|
}
|
|
259
282
|
if (!allGroups) {
|
|
260
283
|
Logger.error('[TabGroup] tabGroups.query returned null');
|
|
261
284
|
if (retries < 3) {
|
|
262
|
-
setTimeout(function() { doGroup(tabId, clientId, baseName, retries + 1, callback); }, 500);
|
|
285
|
+
setTimeout(function() { doGroup(tabId, clientId, baseName, retries + 1, callback, context); }, 500);
|
|
263
286
|
} else {
|
|
264
287
|
if (callback) callback(false);
|
|
265
288
|
}
|
|
@@ -272,15 +295,15 @@ var SpecialHandler = (function() {
|
|
|
272
295
|
chrome.tabs.group({ tabIds: tabId, groupId: existing.id }, function(result) {
|
|
273
296
|
if (chrome.runtime.lastError) {
|
|
274
297
|
Logger.error('[TabGroup] Failed to add tab to group:', chrome.runtime.lastError.message, 'retries:', retries);
|
|
275
|
-
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'addToExisting', error: chrome.runtime.lastError.message, tabId: tabId, groupId: existing.id });
|
|
298
|
+
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'addToExisting', error: chrome.runtime.lastError.message, tabId: tabId, groupId: existing.id }, null, wsManager);
|
|
276
299
|
if (retries < 3) {
|
|
277
|
-
setTimeout(function() { doGroup(tabId, clientId, baseName, retries + 1, callback); }, 500);
|
|
300
|
+
setTimeout(function() { doGroup(tabId, clientId, baseName, retries + 1, callback, context); }, 500);
|
|
278
301
|
} else {
|
|
279
302
|
if (callback) callback(false);
|
|
280
303
|
}
|
|
281
304
|
} else {
|
|
282
|
-
|
|
283
|
-
updateTabGroupName(clientId);
|
|
305
|
+
if (state) state.setGroupIdForClient(clientId, existing.id);
|
|
306
|
+
updateTabGroupName(clientId, state, wsManager);
|
|
284
307
|
Logger.info('[TabGroup] Tab', tabId, 'added to existing group:', existing.id);
|
|
285
308
|
if (callback) callback(true);
|
|
286
309
|
}
|
|
@@ -290,16 +313,16 @@ var SpecialHandler = (function() {
|
|
|
290
313
|
chrome.tabs.group({ tabIds: tabId }, function(groupId) {
|
|
291
314
|
if (chrome.runtime.lastError) {
|
|
292
315
|
Logger.error('[TabGroup] Failed to create group:', chrome.runtime.lastError.message, 'retries:', retries);
|
|
293
|
-
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'createGroup', error: chrome.runtime.lastError.message, tabId: tabId });
|
|
316
|
+
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'createGroup', error: chrome.runtime.lastError.message, tabId: tabId }, null, wsManager);
|
|
294
317
|
if (retries < 3) {
|
|
295
|
-
setTimeout(function() { doGroup(tabId, clientId, baseName, retries + 1, callback); }, 500);
|
|
318
|
+
setTimeout(function() { doGroup(tabId, clientId, baseName, retries + 1, callback, context); }, 500);
|
|
296
319
|
} else {
|
|
297
320
|
if (callback) callback(false);
|
|
298
321
|
}
|
|
299
322
|
return;
|
|
300
323
|
}
|
|
301
324
|
Logger.info('[TabGroup] chrome.tabs.group returned groupId:', groupId);
|
|
302
|
-
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'groupCreated', tabId: tabId, groupId: groupId });
|
|
325
|
+
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'groupCreated', tabId: tabId, groupId: groupId }, null, wsManager);
|
|
303
326
|
if (groupId) {
|
|
304
327
|
if (chrome.tabGroups) {
|
|
305
328
|
chrome.tabGroups.update(groupId, {
|
|
@@ -309,16 +332,16 @@ var SpecialHandler = (function() {
|
|
|
309
332
|
}, function() {
|
|
310
333
|
if (chrome.runtime.lastError) {
|
|
311
334
|
Logger.error('[TabGroup] Failed to update group:', chrome.runtime.lastError.message);
|
|
312
|
-
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'updateGroup', error: chrome.runtime.lastError.message, groupId: groupId });
|
|
335
|
+
EventBuilder.send('CDPTunnel.debug', { source: 'doGroup', phase: 'updateGroup', error: chrome.runtime.lastError.message, groupId: groupId }, null, wsManager);
|
|
313
336
|
} else {
|
|
314
|
-
|
|
315
|
-
updateTabGroupName(clientId);
|
|
337
|
+
if (state) state.setGroupIdForClient(clientId, groupId);
|
|
338
|
+
updateTabGroupName(clientId, state, wsManager);
|
|
316
339
|
Logger.info('[TabGroup] Group updated:', groupId, baseName);
|
|
317
340
|
}
|
|
318
341
|
if (callback) callback(true);
|
|
319
342
|
});
|
|
320
343
|
} else {
|
|
321
|
-
|
|
344
|
+
if (state) state.setGroupIdForClient(clientId, groupId);
|
|
322
345
|
Logger.info('[TabGroup] Group created but tabGroups.update unavailable (headless):', groupId);
|
|
323
346
|
if (callback) callback(true);
|
|
324
347
|
}
|
|
@@ -331,18 +354,20 @@ var SpecialHandler = (function() {
|
|
|
331
354
|
});
|
|
332
355
|
}
|
|
333
356
|
|
|
334
|
-
function updateTabGroupName(clientId) {
|
|
357
|
+
function updateTabGroupName(clientId, state, wsManager) {
|
|
335
358
|
if (!clientId) return;
|
|
336
|
-
|
|
337
|
-
var groupId =
|
|
359
|
+
|
|
360
|
+
var groupId = state ? state.getGroupIdForClient(clientId) : null;
|
|
338
361
|
if (!groupId) return;
|
|
339
|
-
|
|
362
|
+
|
|
363
|
+
var connectionTag = (wsManager && wsManager.config && wsManager.config.tag) || null;
|
|
364
|
+
|
|
340
365
|
chrome.tabs.query({ groupId: groupId }, function(tabs) {
|
|
341
366
|
if (chrome.runtime.lastError || !tabs) return;
|
|
342
|
-
|
|
343
|
-
var baseName = CDPUtils.getGroupBaseName(clientId);
|
|
367
|
+
|
|
368
|
+
var baseName = CDPUtils.getGroupBaseName(clientId, connectionTag);
|
|
344
369
|
var newName = baseName + ' (' + tabs.length + ')';
|
|
345
|
-
|
|
370
|
+
|
|
346
371
|
chrome.tabGroups.update(groupId, {
|
|
347
372
|
title: newName
|
|
348
373
|
}, function() {
|
|
@@ -354,7 +379,7 @@ var SpecialHandler = (function() {
|
|
|
354
379
|
});
|
|
355
380
|
});
|
|
356
381
|
}
|
|
357
|
-
|
|
382
|
+
|
|
358
383
|
function targetActivateTarget(context) {
|
|
359
384
|
var params = context.params;
|
|
360
385
|
var targetId = params && params.targetId;
|
|
@@ -371,22 +396,23 @@ var SpecialHandler = (function() {
|
|
|
371
396
|
}
|
|
372
397
|
|
|
373
398
|
function targetCloseTarget(context) {
|
|
399
|
+
var state = _getState(context);
|
|
374
400
|
var params = context.params;
|
|
375
401
|
var targetId = params && params.targetId;
|
|
376
402
|
if (targetId) {
|
|
377
|
-
var tabId =
|
|
403
|
+
var tabId = state.getTabIdByTargetId(targetId);
|
|
378
404
|
if (tabId) {
|
|
379
|
-
var closeClientId =
|
|
405
|
+
var closeClientId = state.getClientIdByTabId(tabId);
|
|
380
406
|
return new Promise(function(resolve) {
|
|
381
407
|
chrome.tabs.remove(tabId, function() {
|
|
382
|
-
|
|
408
|
+
state.removeAttachedTab(tabId);
|
|
383
409
|
if (closeClientId) {
|
|
384
|
-
updateTabGroupName(closeClientId);
|
|
410
|
+
updateTabGroupName(closeClientId, state, _getWSManager(context));
|
|
385
411
|
}
|
|
386
412
|
resolve({ success: true });
|
|
387
413
|
});
|
|
388
414
|
}).catch(function() {
|
|
389
|
-
|
|
415
|
+
state.removeAttachedTab(tabId);
|
|
390
416
|
return { success: true };
|
|
391
417
|
});
|
|
392
418
|
}
|
|
@@ -395,52 +421,55 @@ var SpecialHandler = (function() {
|
|
|
395
421
|
}
|
|
396
422
|
|
|
397
423
|
function pageStartScreencast(context) {
|
|
424
|
+
var state = _getState(context);
|
|
398
425
|
var params = context.params;
|
|
399
426
|
var sessionId = context.sessionId;
|
|
400
|
-
var tabId = sessionId ?
|
|
427
|
+
var tabId = sessionId ? state.getTabIdBySession(sessionId) : state.getCurrentTabId();
|
|
401
428
|
|
|
402
429
|
return checkTabVisibility(tabId).then(function(isVisible) {
|
|
403
430
|
if (!isVisible) {
|
|
404
|
-
return Screencast.startPolling(tabId, params, sessionId).then(function() {
|
|
431
|
+
return Screencast.startPolling(tabId, params, sessionId, state).then(function() {
|
|
405
432
|
return {};
|
|
406
433
|
});
|
|
407
434
|
}
|
|
408
|
-
return ForwardHandler.execute(
|
|
435
|
+
return ForwardHandler.execute(context);
|
|
409
436
|
});
|
|
410
437
|
}
|
|
411
438
|
|
|
412
439
|
function pageStopScreencast(context) {
|
|
440
|
+
var state = _getState(context);
|
|
413
441
|
var sessionId = context.sessionId;
|
|
414
|
-
var tabId = sessionId ?
|
|
415
|
-
var session = tabId ?
|
|
416
|
-
|
|
442
|
+
var tabId = sessionId ? state.getTabIdBySession(sessionId) : state.getCurrentTabId();
|
|
443
|
+
var session = tabId ? state.getScreencastSession(tabId) : null;
|
|
444
|
+
|
|
417
445
|
if (session) {
|
|
418
|
-
Screencast.stopPolling(tabId);
|
|
446
|
+
Screencast.stopPolling(tabId, state);
|
|
419
447
|
}
|
|
420
|
-
|
|
448
|
+
|
|
421
449
|
return {};
|
|
422
450
|
}
|
|
423
451
|
|
|
424
452
|
function pageScreencastFrameAck(context) {
|
|
425
|
-
var
|
|
453
|
+
var state = _getState(context);
|
|
426
454
|
var sessionId = context.sessionId;
|
|
427
|
-
var tabId = sessionId ?
|
|
428
|
-
var session = tabId ?
|
|
429
|
-
|
|
455
|
+
var tabId = sessionId ? state.getTabIdBySession(sessionId) : state.getCurrentTabId();
|
|
456
|
+
var session = tabId ? state.getScreencastSession(tabId) : null;
|
|
457
|
+
|
|
430
458
|
if (session) {
|
|
431
|
-
Screencast.ackFrame(tabId, params && params.sessionId);
|
|
459
|
+
Screencast.ackFrame(tabId, (context.params && context.params.sessionId), state);
|
|
432
460
|
return {};
|
|
433
461
|
}
|
|
434
|
-
|
|
462
|
+
|
|
435
463
|
return {};
|
|
436
464
|
}
|
|
437
465
|
|
|
438
466
|
function runtimeRunIfWaitingForDebugger(context) {
|
|
467
|
+
var state = _getState(context);
|
|
439
468
|
var sessionId = context.sessionId;
|
|
440
|
-
var tabId = sessionId ?
|
|
469
|
+
var tabId = sessionId ? state.getTabIdBySession(sessionId) : state.getCurrentTabId();
|
|
441
470
|
|
|
442
|
-
if (tabId &&
|
|
443
|
-
|
|
471
|
+
if (tabId && state.isPendingDebuggerTab(tabId)) {
|
|
472
|
+
state.removePendingDebuggerTab(tabId);
|
|
444
473
|
}
|
|
445
474
|
return {};
|
|
446
475
|
}
|
|
@@ -484,8 +513,10 @@ function checkTabVisibility(tabId) {
|
|
|
484
513
|
}
|
|
485
514
|
|
|
486
515
|
function emitAutoAttachForExistingTargets(context) {
|
|
516
|
+
var state = _getState(context);
|
|
517
|
+
var wsManager = _getWSManager(context);
|
|
487
518
|
var clientId = context ? context.clientId : null;
|
|
488
|
-
var config =
|
|
519
|
+
var config = state.getAutoAttachConfig();
|
|
489
520
|
|
|
490
521
|
return chrome.debugger.getTargets().then(function(targets) {
|
|
491
522
|
var promises = [];
|
|
@@ -498,15 +529,15 @@ function checkTabVisibility(tabId) {
|
|
|
498
529
|
|
|
499
530
|
var targetId = target.id;
|
|
500
531
|
var tabId = target.tabId;
|
|
501
|
-
var hasEmitted =
|
|
532
|
+
var hasEmitted = state.hasEmittedTarget(targetId);
|
|
502
533
|
|
|
503
534
|
if (hasEmitted) {
|
|
504
535
|
Logger.info('[CDP] Target already emitted, skipping:', targetId);
|
|
505
536
|
return;
|
|
506
537
|
}
|
|
507
538
|
|
|
508
|
-
var isCDPCreated =
|
|
509
|
-
var isOwnedByClient = isCDPCreated &&
|
|
539
|
+
var isCDPCreated = state.isCDPCreatedTab(tabId);
|
|
540
|
+
var isOwnedByClient = isCDPCreated && state.getClientIdByTabId(tabId) === clientId;
|
|
510
541
|
var otherClientOwns = isCDPCreated && !isOwnedByClient;
|
|
511
542
|
|
|
512
543
|
if (!isCDPCreated) {
|
|
@@ -516,35 +547,35 @@ function checkTabVisibility(tabId) {
|
|
|
516
547
|
|
|
517
548
|
if (otherClientOwns) {
|
|
518
549
|
Logger.info('[CDP] Skipping other-client tab:', targetId, 'tabId:', tabId);
|
|
519
|
-
|
|
550
|
+
state.addEmittedTarget(targetId);
|
|
520
551
|
return;
|
|
521
552
|
}
|
|
522
553
|
|
|
523
|
-
|
|
554
|
+
state.addEmittedTarget(targetId);
|
|
524
555
|
var targetInfo = LocalHandler.mapToTargetInfo(target);
|
|
525
|
-
|
|
556
|
+
|
|
526
557
|
Logger.info('[CDP] Emitting CDP-owned target:', targetId, 'tabId:', tabId);
|
|
527
558
|
|
|
528
559
|
var attachLogic = function(attached) {
|
|
529
560
|
var sessionId = CDPUtils.generateSessionId();
|
|
530
|
-
|
|
561
|
+
state.mapSession(sessionId, tabId, targetId);
|
|
531
562
|
|
|
532
563
|
if (config.waitForDebuggerOnStart) {
|
|
533
|
-
|
|
564
|
+
state.addPendingDebuggerTab(tabId);
|
|
534
565
|
}
|
|
535
566
|
|
|
536
567
|
EventBuilder.send('Target.attachedToTarget', {
|
|
537
568
|
sessionId: sessionId,
|
|
538
569
|
targetInfo: Object.assign({}, targetInfo, { attached: true }),
|
|
539
570
|
waitingForDebugger: config.waitForDebuggerOnStart || false
|
|
540
|
-
});
|
|
571
|
+
}, null, wsManager);
|
|
541
572
|
};
|
|
542
573
|
|
|
543
574
|
if (target.attached) {
|
|
544
575
|
promises.push(Promise.resolve().then(function() { attachLogic(true); }));
|
|
545
576
|
} else {
|
|
546
577
|
promises.push(
|
|
547
|
-
DebuggerManager.attach(tabId).then(function(attached) {
|
|
578
|
+
DebuggerManager.attach(tabId, state).then(function(attached) {
|
|
548
579
|
if (!attached) return;
|
|
549
580
|
attachLogic(attached);
|
|
550
581
|
})
|
|
@@ -556,54 +587,48 @@ function checkTabVisibility(tabId) {
|
|
|
556
587
|
});
|
|
557
588
|
}
|
|
558
589
|
|
|
559
|
-
function emitAutoAttachEvents(tabId, targetId, browserContextId) {
|
|
560
|
-
|
|
590
|
+
function emitAutoAttachEvents(tabId, targetId, browserContextId, context) {
|
|
591
|
+
var state = _getState(context);
|
|
592
|
+
var wsManager = _getWSManager(context);
|
|
593
|
+
if (state.hasEmittedTarget(targetId)) {
|
|
561
594
|
Logger.info('[CDP] Target already emitted, skipping emitAutoAttachEvents:', targetId);
|
|
562
595
|
return Promise.resolve();
|
|
563
596
|
}
|
|
564
|
-
|
|
565
|
-
|
|
597
|
+
|
|
598
|
+
state.addEmittedTarget(targetId);
|
|
566
599
|
|
|
567
600
|
return LocalHandler.getTargetInfoById(targetId).then(function(targetInfo) {
|
|
568
601
|
if (browserContextId && browserContextId !== 'default') {
|
|
569
602
|
targetInfo.browserContextId = browserContextId;
|
|
570
603
|
}
|
|
571
|
-
EventBuilder.send('Target.targetCreated', { targetInfo: targetInfo });
|
|
604
|
+
EventBuilder.send('Target.targetCreated', { targetInfo: targetInfo }, null, wsManager);
|
|
572
605
|
|
|
573
|
-
return DebuggerManager.attach(tabId).then(function(attached) {
|
|
606
|
+
return DebuggerManager.attach(tabId, state).then(function(attached) {
|
|
574
607
|
if (!attached) return;
|
|
575
608
|
|
|
576
609
|
var sessionId = CDPUtils.generateSessionId();
|
|
577
|
-
|
|
610
|
+
state.mapSession(sessionId, tabId, targetId);
|
|
578
611
|
|
|
579
|
-
var config =
|
|
612
|
+
var config = state.getAutoAttachConfig();
|
|
580
613
|
if (config.waitForDebuggerOnStart) {
|
|
581
|
-
|
|
614
|
+
state.addPendingDebuggerTab(tabId);
|
|
582
615
|
}
|
|
583
616
|
|
|
584
617
|
EventBuilder.send('Target.attachedToTarget', {
|
|
585
618
|
sessionId: sessionId,
|
|
586
619
|
targetInfo: targetInfo,
|
|
587
620
|
waitingForDebugger: config.waitForDebuggerOnStart
|
|
588
|
-
});
|
|
621
|
+
}, null, wsManager);
|
|
589
622
|
});
|
|
590
623
|
});
|
|
591
624
|
}
|
|
592
625
|
|
|
593
626
|
function pageCreateIsolatedWorld(context) {
|
|
594
|
-
|
|
595
|
-
var sessionId = context.sessionId;
|
|
596
|
-
var tabId = sessionId ? State.getTabIdBySession(sessionId) : State.getCurrentTabId();
|
|
597
|
-
|
|
598
|
-
return ForwardHandler.execute({ id: context.id, method: 'Page.createIsolatedWorld', params: params, sessionId: sessionId });
|
|
627
|
+
return ForwardHandler.execute(context);
|
|
599
628
|
}
|
|
600
629
|
|
|
601
630
|
function pageAddScriptToEvaluateOnNewDocument(context) {
|
|
602
|
-
|
|
603
|
-
var sessionId = context.sessionId;
|
|
604
|
-
var tabId = sessionId ? State.getTabIdBySession(sessionId) : State.getCurrentTabId();
|
|
605
|
-
|
|
606
|
-
return ForwardHandler.execute({ id: context.id, method: 'Page.addScriptToEvaluateOnNewDocument', params: params, sessionId: sessionId });
|
|
631
|
+
return ForwardHandler.execute(context);
|
|
607
632
|
}
|
|
608
633
|
|
|
609
634
|
function domSetFileInputFiles(context) {
|
|
@@ -612,7 +637,7 @@ function checkTabVisibility(tabId) {
|
|
|
612
637
|
var files = params && params.files;
|
|
613
638
|
|
|
614
639
|
if (!files || !Array.isArray(files) || files.length === 0) {
|
|
615
|
-
return ForwardHandler.execute(
|
|
640
|
+
return ForwardHandler.execute(context);
|
|
616
641
|
}
|
|
617
642
|
|
|
618
643
|
var hasUrl = files.some(function(f) {
|
|
@@ -620,16 +645,17 @@ function checkTabVisibility(tabId) {
|
|
|
620
645
|
});
|
|
621
646
|
|
|
622
647
|
if (!hasUrl) {
|
|
623
|
-
return ForwardHandler.execute(
|
|
648
|
+
return ForwardHandler.execute(context);
|
|
624
649
|
}
|
|
625
650
|
|
|
626
651
|
Logger.info('[CDP] DOM.setFileInputFiles: 检测到远程 URL, 开始下载...');
|
|
627
652
|
|
|
628
653
|
return downloadRemoteFiles(files).then(function(localFiles) {
|
|
629
654
|
Logger.info('[CDP] DOM.setFileInputFiles: 下载完成, 本地路径:', localFiles);
|
|
630
|
-
|
|
655
|
+
|
|
631
656
|
var newParams = Object.assign({}, params, { files: localFiles });
|
|
632
|
-
|
|
657
|
+
var newContext = Object.assign({}, context, { params: newParams });
|
|
658
|
+
return ForwardHandler.execute(newContext);
|
|
633
659
|
});
|
|
634
660
|
}
|
|
635
661
|
|
|
@@ -647,7 +673,7 @@ function checkTabVisibility(tabId) {
|
|
|
647
673
|
function downloadRemoteFile(url) {
|
|
648
674
|
return new Promise(function(resolve, reject) {
|
|
649
675
|
var filename = 'cdp_upload_' + Date.now() + '_' + url.split('/').pop().split('?')[0];
|
|
650
|
-
|
|
676
|
+
|
|
651
677
|
chrome.downloads.download({
|
|
652
678
|
url: url,
|
|
653
679
|
filename: filename,
|
|
@@ -668,7 +694,7 @@ function checkTabVisibility(tabId) {
|
|
|
668
694
|
reject(new Error('Download item not found'));
|
|
669
695
|
return;
|
|
670
696
|
}
|
|
671
|
-
|
|
697
|
+
|
|
672
698
|
var filePath = results[0].filename;
|
|
673
699
|
Logger.info('[CDP] 下载完成, 本地路径:', filePath);
|
|
674
700
|
resolve(filePath);
|