cdp-tunnel 2.9.0 → 2.9.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.
- package/extension-new/background.js +13 -3
- package/extension-new/config-page-preview.html +35 -0
- package/extension-new/config-page.js +30 -4
- package/extension-new/core/connection-manager.js +1 -1
- package/extension-new/core/connection-state.js +2 -1
- package/extension-new/manifest.json +1 -1
- package/extension-new/popup.html +6 -0
- package/extension-new/popup.js +45 -2
- package/extension-new/utils/config.js +2 -0
- package/package.json +1 -1
|
@@ -338,6 +338,15 @@ importScripts('features/automation-badge.js');
|
|
|
338
338
|
});
|
|
339
339
|
});
|
|
340
340
|
|
|
341
|
+
function getCdpAddress(wsUrl, mode) {
|
|
342
|
+
var match = (wsUrl || '').match(/:\/\/([^\/]+):(\d+)/);
|
|
343
|
+
if (!match) return '';
|
|
344
|
+
var host = match[1];
|
|
345
|
+
var port = parseInt(match[2], 10);
|
|
346
|
+
if (mode === 'takeover') port += 1;
|
|
347
|
+
return 'http://' + host + ':' + port;
|
|
348
|
+
}
|
|
349
|
+
|
|
341
350
|
chrome.runtime.onInstalled.addListener(function(details) {
|
|
342
351
|
Logger.info('[Runtime] Extension installed/updated:', details.reason);
|
|
343
352
|
State.persist(null, false);
|
|
@@ -466,14 +475,15 @@ importScripts('features/automation-badge.js');
|
|
|
466
475
|
status = 'error';
|
|
467
476
|
}
|
|
468
477
|
}
|
|
469
|
-
|
|
478
|
+
var cdpAddress = getCdpAddress(conn.url, conn.mode || 'create');
|
|
479
|
+
return { id: conn.id, tag: conn.tag, url: conn.url, mode: conn.mode || 'create', status: status, attachedCount: attachedCount, cdpAddress: cdpAddress };
|
|
470
480
|
});
|
|
471
481
|
sendResponse({ connections: list });
|
|
472
482
|
});
|
|
473
483
|
return true;
|
|
474
484
|
} else if (message.type === 'add-connection') {
|
|
475
|
-
Logger.info('[Runtime] Adding connection:', message.tag, message.url);
|
|
476
|
-
Config.addConnection({ tag: message.tag, url: message.url }, function(conn) {
|
|
485
|
+
Logger.info('[Runtime] Adding connection:', message.tag, message.url, 'mode:', message.mode);
|
|
486
|
+
Config.addConnection({ tag: message.tag, url: message.url, mode: message.mode || 'create' }, function(conn) {
|
|
477
487
|
if (conn && conn.enabled) {
|
|
478
488
|
ConnectionManager.addConnection(conn);
|
|
479
489
|
var entry = ConnectionManager.getConnection(conn.id);
|
|
@@ -283,6 +283,37 @@
|
|
|
283
283
|
font-family: 'Monaco', 'Menlo', monospace;
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
.conn-config-cdp {
|
|
287
|
+
font-size: 11px;
|
|
288
|
+
color: #374151;
|
|
289
|
+
font-family: 'Monaco', 'Menlo', monospace;
|
|
290
|
+
margin-top: 2px;
|
|
291
|
+
display: flex;
|
|
292
|
+
align-items: center;
|
|
293
|
+
gap: 4px;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.conn-config-cdp .cdp-addr {
|
|
297
|
+
color: #2563eb;
|
|
298
|
+
font-weight: 600;
|
|
299
|
+
cursor: pointer;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.conn-config-cdp .btn-copy-cdp {
|
|
303
|
+
border: none;
|
|
304
|
+
background: transparent;
|
|
305
|
+
cursor: pointer;
|
|
306
|
+
font-size: 12px;
|
|
307
|
+
padding: 0 4px;
|
|
308
|
+
opacity: 0.5;
|
|
309
|
+
transition: opacity 0.2s;
|
|
310
|
+
line-height: 1;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.conn-config-cdp .btn-copy-cdp:hover {
|
|
314
|
+
opacity: 1;
|
|
315
|
+
}
|
|
316
|
+
|
|
286
317
|
.conn-config-item .btn-delete {
|
|
287
318
|
padding: 4px 10px;
|
|
288
319
|
border: none;
|
|
@@ -814,6 +845,10 @@
|
|
|
814
845
|
<div class="add-conn-form">
|
|
815
846
|
<input type="text" class="input-tag" id="newConnTag" placeholder="名称" value="local">
|
|
816
847
|
<input type="text" class="input-url" id="newConnUrl" placeholder="ws://localhost:9221/plugin" value="ws://localhost:9221/plugin">
|
|
848
|
+
<select id="inputMode" style="padding:8px 10px;border:1px solid #d1d5db;border-radius:6px;font-size:13px;outline:none;transition:border-color 0.2s;flex-shrink:0;">
|
|
849
|
+
<option value="create">创建模式</option>
|
|
850
|
+
<option value="takeover">接管模式</option>
|
|
851
|
+
</select>
|
|
817
852
|
<button class="btn btn-primary btn-sm" id="addConnBtn">添加连接</button>
|
|
818
853
|
</div>
|
|
819
854
|
</div>
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
newConnTag: document.getElementById('newConnTag'),
|
|
28
28
|
newConnUrl: document.getElementById('newConnUrl'),
|
|
29
29
|
addConnBtn: document.getElementById('addConnBtn'),
|
|
30
|
+
inputMode: document.getElementById('inputMode'),
|
|
30
31
|
autoMuteToggle: document.getElementById('autoMuteToggle'),
|
|
31
32
|
pluginIdDisplay: document.getElementById('pluginIdDisplay')
|
|
32
33
|
};
|
|
@@ -94,13 +95,15 @@
|
|
|
94
95
|
connections.forEach(function(conn) {
|
|
95
96
|
var statusClass = getStatusClass(conn.id, conn.enabled);
|
|
96
97
|
var isActive = conn.enabled && statusClass === 'connected';
|
|
98
|
+
var cdpAddr = getCdpAddress(conn.url, conn.mode);
|
|
97
99
|
html +=
|
|
98
100
|
'<div class="conn-config-item' + (isActive ? ' active' : '') + '" data-id="' + conn.id + '">' +
|
|
99
101
|
'<input type="checkbox" class="conn-toggle" data-id="' + conn.id + '"' + (conn.enabled ? ' checked' : '') + ' title="启用/禁用">' +
|
|
100
102
|
'<span class="status-dot ' + statusClass + '" title="' + statusClass + '"></span>' +
|
|
101
103
|
'<div class="conn-config-info">' +
|
|
102
|
-
'<div class="conn-config-tag">' + escapeHtml(conn.tag) + '</div>' +
|
|
103
|
-
'<div class="conn-config-url" title="' + escapeAttr(conn.url) + '">' + escapeHtml(conn.url) + '</div>' +
|
|
104
|
+
'<div class="conn-config-tag">' + (conn.mode === 'takeover' ? '🔗 ' : '🆕 ') + escapeHtml(conn.tag) + '</div>' +
|
|
105
|
+
'<div class="conn-config-url" title="' + escapeAttr(conn.url) + '">WS: ' + escapeHtml(conn.url) + '</div>' +
|
|
106
|
+
(cdpAddr ? '<div class="conn-config-cdp">CDP: <span class="cdp-addr" data-cdp="' + escapeAttr(cdpAddr) + '">' + escapeHtml(cdpAddr) + '</span> <button class="btn-copy-cdp" data-cdp="' + escapeAttr(cdpAddr) + '" title="复制 CDP 地址">📋</button></div>' : '') +
|
|
104
107
|
'</div>' +
|
|
105
108
|
'<button class="btn-delete" data-id="' + conn.id + '" title="删除">删除</button>' +
|
|
106
109
|
'</div>';
|
|
@@ -296,6 +299,15 @@
|
|
|
296
299
|
return (s || '').replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
|
|
297
300
|
}
|
|
298
301
|
|
|
302
|
+
function getCdpAddress(wsUrl, mode) {
|
|
303
|
+
var match = (wsUrl || '').match(/:\/\/([^\/]+):(\d+)/);
|
|
304
|
+
if (!match) return '';
|
|
305
|
+
var host = match[1];
|
|
306
|
+
var port = parseInt(match[2], 10);
|
|
307
|
+
if (mode === 'takeover') port += 1;
|
|
308
|
+
return 'http://' + host + ':' + port;
|
|
309
|
+
}
|
|
310
|
+
|
|
299
311
|
function init() {
|
|
300
312
|
if (typeof chrome !== 'undefined' && chrome.storage) {
|
|
301
313
|
chrome.storage.local.get(['autoMute'], function(result) {
|
|
@@ -333,6 +345,7 @@
|
|
|
333
345
|
elements.addConnBtn.addEventListener('click', function() {
|
|
334
346
|
var tag = elements.newConnTag.value.trim();
|
|
335
347
|
var url = elements.newConnUrl.value.trim();
|
|
348
|
+
var mode = elements.inputMode.value || 'create';
|
|
336
349
|
|
|
337
350
|
if (!tag) {
|
|
338
351
|
showToast('请输入连接名称', 'error');
|
|
@@ -344,16 +357,18 @@
|
|
|
344
357
|
}
|
|
345
358
|
|
|
346
359
|
if (typeof chrome !== 'undefined' && chrome.runtime) {
|
|
347
|
-
chrome.runtime.sendMessage({ type: 'add-connection', tag: tag, url: url }, function() {
|
|
360
|
+
chrome.runtime.sendMessage({ type: 'add-connection', tag: tag, url: url, mode: mode }, function() {
|
|
348
361
|
elements.newConnTag.value = '';
|
|
349
362
|
elements.newConnUrl.value = '';
|
|
363
|
+
elements.inputMode.value = 'create';
|
|
350
364
|
loadAndRenderConnections();
|
|
351
365
|
showToast('连接已添加');
|
|
352
366
|
});
|
|
353
367
|
} else if (typeof Config !== 'undefined') {
|
|
354
|
-
Config.addConnection({ tag: tag, url: url }, function() {
|
|
368
|
+
Config.addConnection({ tag: tag, url: url, mode: mode }, function() {
|
|
355
369
|
elements.newConnTag.value = '';
|
|
356
370
|
elements.newConnUrl.value = '';
|
|
371
|
+
elements.inputMode.value = 'create';
|
|
357
372
|
loadAndRenderConnections();
|
|
358
373
|
showToast('连接已添加');
|
|
359
374
|
});
|
|
@@ -361,6 +376,17 @@
|
|
|
361
376
|
});
|
|
362
377
|
|
|
363
378
|
elements.connConfigList.addEventListener('click', function(e) {
|
|
379
|
+
var copyBtn = e.target.closest('.btn-copy-cdp');
|
|
380
|
+
if (copyBtn) {
|
|
381
|
+
var addr = copyBtn.dataset.cdp;
|
|
382
|
+
if (addr) {
|
|
383
|
+
navigator.clipboard.writeText(addr).then(function() {
|
|
384
|
+
showToast('已复制: ' + addr);
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
|
|
364
390
|
var toggleEl = e.target.closest('.conn-toggle');
|
|
365
391
|
if (toggleEl) {
|
|
366
392
|
var connId = toggleEl.dataset.id;
|
|
@@ -23,7 +23,7 @@ var ConnectionManager = (function() {
|
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
var state = new ConnectionState(config.id);
|
|
26
|
+
var state = new ConnectionState(config.id, config.mode);
|
|
27
27
|
var wsManager = new WebSocketConnection(config.id, state, config);
|
|
28
28
|
|
|
29
29
|
_connections.set(config.id, {
|
package/extension-new/popup.html
CHANGED
|
@@ -23,6 +23,12 @@ body { width: 320px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
|
|
23
23
|
.conn-tag { font-weight: 600; font-size: 13px; color: #e0e0e0; }
|
|
24
24
|
.conn-url { color: #888; font-size: 11px; font-family: 'SF Mono', Menlo, monospace; word-break: break-all; margin-top: 3px; line-height: 1.4; }
|
|
25
25
|
|
|
26
|
+
.conn-cdp { color: #4a9eff; font-size: 11px; font-family: 'SF Mono', Menlo, monospace; margin-top: 2px; display: flex; align-items: center; gap: 2px; }
|
|
27
|
+
.conn-cdp-label { color: #888; }
|
|
28
|
+
.conn-cdp-value { font-weight: 600; }
|
|
29
|
+
.conn-cdp-copy { background: none; border: none; cursor: pointer; font-size: 11px; padding: 0 2px; opacity: 0.5; transition: opacity 0.15s; }
|
|
30
|
+
.conn-cdp-copy:hover { opacity: 1; }
|
|
31
|
+
|
|
26
32
|
.empty-hint { text-align: center; padding: 16px 10px; color: #777; font-size: 12px; }
|
|
27
33
|
|
|
28
34
|
.stats-row { display: flex; gap: 16px; padding: 8px 0; font-size: 12px; color: #aaa; }
|
package/extension-new/popup.js
CHANGED
|
@@ -14,6 +14,15 @@
|
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
function getCdpAddress(wsUrl, mode) {
|
|
18
|
+
var match = (wsUrl || '').match(/:\/\/([^\/]+):(\d+)/);
|
|
19
|
+
if (!match) return '';
|
|
20
|
+
var host = match[1];
|
|
21
|
+
var port = parseInt(match[2], 10);
|
|
22
|
+
if (mode === 'takeover') port += 1;
|
|
23
|
+
return 'http://' + host + ':' + port;
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
function renderConnectionList(connections) {
|
|
18
27
|
connectionList.innerHTML = '';
|
|
19
28
|
|
|
@@ -32,19 +41,53 @@
|
|
|
32
41
|
var dot = document.createElement('span');
|
|
33
42
|
dot.className = 'conn-dot ' + conn.status;
|
|
34
43
|
|
|
44
|
+
var modeIcon = conn.mode === 'takeover' ? '🔗 ' : '🆕 ';
|
|
45
|
+
|
|
35
46
|
var tag = document.createElement('span');
|
|
36
47
|
tag.className = 'conn-tag';
|
|
37
|
-
tag.textContent = conn.tag;
|
|
48
|
+
tag.textContent = modeIcon + conn.tag;
|
|
38
49
|
|
|
39
50
|
header.appendChild(dot);
|
|
40
51
|
header.appendChild(tag);
|
|
41
52
|
|
|
42
53
|
var url = document.createElement('div');
|
|
43
54
|
url.className = 'conn-url';
|
|
44
|
-
url.textContent = conn.url;
|
|
55
|
+
url.textContent = 'WS: ' + conn.url;
|
|
45
56
|
|
|
46
57
|
item.appendChild(header);
|
|
47
58
|
item.appendChild(url);
|
|
59
|
+
|
|
60
|
+
var cdpAddr = conn.cdpAddress || getCdpAddress(conn.url, conn.mode);
|
|
61
|
+
if (cdpAddr) {
|
|
62
|
+
var cdpRow = document.createElement('div');
|
|
63
|
+
cdpRow.className = 'conn-cdp';
|
|
64
|
+
|
|
65
|
+
var cdpLabel = document.createElement('span');
|
|
66
|
+
cdpLabel.className = 'conn-cdp-label';
|
|
67
|
+
cdpLabel.textContent = 'CDP: ';
|
|
68
|
+
|
|
69
|
+
var cdpValue = document.createElement('span');
|
|
70
|
+
cdpValue.className = 'conn-cdp-value';
|
|
71
|
+
cdpValue.textContent = cdpAddr;
|
|
72
|
+
|
|
73
|
+
var copyBtn = document.createElement('button');
|
|
74
|
+
copyBtn.className = 'conn-cdp-copy';
|
|
75
|
+
copyBtn.textContent = '📋';
|
|
76
|
+
copyBtn.title = '复制';
|
|
77
|
+
copyBtn.addEventListener('click', function(ev) {
|
|
78
|
+
ev.stopPropagation();
|
|
79
|
+
navigator.clipboard.writeText(cdpAddr).then(function() {
|
|
80
|
+
copyBtn.textContent = '✓';
|
|
81
|
+
setTimeout(function() { copyBtn.textContent = '📋'; }, 1200);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
cdpRow.appendChild(cdpLabel);
|
|
86
|
+
cdpRow.appendChild(cdpValue);
|
|
87
|
+
cdpRow.appendChild(copyBtn);
|
|
88
|
+
item.appendChild(cdpRow);
|
|
89
|
+
}
|
|
90
|
+
|
|
48
91
|
connectionList.appendChild(item);
|
|
49
92
|
});
|
|
50
93
|
}
|
|
@@ -58,6 +58,7 @@ var Config = {
|
|
|
58
58
|
id: 'conn_' + Date.now() + '_' + Math.random().toString(36).substr(2, 6),
|
|
59
59
|
tag: opts.tag || 'unnamed',
|
|
60
60
|
url: opts.url || '',
|
|
61
|
+
mode: opts.mode || 'create',
|
|
61
62
|
enabled: opts.enabled !== undefined ? opts.enabled : true
|
|
62
63
|
};
|
|
63
64
|
connections.push(conn);
|
|
@@ -91,6 +92,7 @@ var Config = {
|
|
|
91
92
|
if (c.id === id) {
|
|
92
93
|
if (updates.tag !== undefined) c.tag = updates.tag;
|
|
93
94
|
if (updates.url !== undefined) c.url = updates.url;
|
|
95
|
+
if (updates.mode !== undefined) c.mode = updates.mode;
|
|
94
96
|
}
|
|
95
97
|
});
|
|
96
98
|
Config.setConnections(connections, callback);
|
package/package.json
CHANGED