cdp-tunnel 2.8.2 → 2.8.3
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 +9 -8
- package/extension-new/manifest.json +1 -1
- package/extension-new/popup.html +26 -51
- package/extension-new/popup.js +51 -99
- package/package.json +1 -1
|
@@ -453,21 +453,22 @@ importScripts('features/automation-badge.js');
|
|
|
453
453
|
sendResponse({ success: true });
|
|
454
454
|
} else if (message.type === 'get-connection-statuses') {
|
|
455
455
|
Config.getConnections(function(connections) {
|
|
456
|
-
var
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
} else {
|
|
456
|
+
var list = (connections || []).map(function(conn) {
|
|
457
|
+
var status = 'disabled';
|
|
458
|
+
var attachedCount = 0;
|
|
459
|
+
if (conn.enabled) {
|
|
461
460
|
var entry = ConnectionManager.getConnection(conn.id);
|
|
462
461
|
if (entry) {
|
|
463
462
|
var ws = entry.state.getWs();
|
|
464
|
-
|
|
463
|
+
status = (ws && ws.readyState === WebSocket.OPEN) ? 'connected' : 'error';
|
|
464
|
+
attachedCount = entry.state.getAttachedTabIds().length;
|
|
465
465
|
} else {
|
|
466
|
-
|
|
466
|
+
status = 'error';
|
|
467
467
|
}
|
|
468
468
|
}
|
|
469
|
+
return { id: conn.id, tag: conn.tag, url: conn.url, status: status, attachedCount: attachedCount };
|
|
469
470
|
});
|
|
470
|
-
sendResponse({
|
|
471
|
+
sendResponse({ connections: list });
|
|
471
472
|
});
|
|
472
473
|
return true;
|
|
473
474
|
} else if (message.type === 'add-connection') {
|
package/extension-new/popup.html
CHANGED
|
@@ -4,76 +4,51 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<style>
|
|
6
6
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
7
|
-
body { width:
|
|
7
|
+
body { width: 320px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #1a1a2e; color: #e0e0e0; font-size: 13px; }
|
|
8
8
|
|
|
9
|
-
.header { display: flex; align-items: center; justify-content: space-between; padding:
|
|
9
|
+
.header { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-bottom: 1px solid #2a2a4a; }
|
|
10
10
|
.header h1 { font-size: 15px; font-weight: 600; color: #fff; }
|
|
11
|
-
.status-badge { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 500; padding: 3px 10px; border-radius: 12px; }
|
|
12
|
-
.status-badge.on { background: rgba(76,175,80,0.15); color: #4CAF50; }
|
|
13
|
-
.status-badge.off { background: rgba(158,158,158,0.15); color: #9E9E9E; }
|
|
14
|
-
.status-badge.err { background: rgba(244,67,54,0.15); color: #F44336; }
|
|
15
|
-
.status-dot { width: 8px; height: 8px; border-radius: 50%; }
|
|
16
|
-
.status-badge.on .status-dot { background: #4CAF50; box-shadow: 0 0 6px #4CAF50; }
|
|
17
|
-
.status-badge.off .status-dot { background: #9E9E9E; }
|
|
18
|
-
.status-badge.err .status-dot { background: #F44336; }
|
|
19
11
|
|
|
20
|
-
.
|
|
21
|
-
.section-title { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: #888; margin-bottom: 8px; }
|
|
12
|
+
.body { padding: 10px 14px; }
|
|
22
13
|
|
|
23
|
-
|
|
24
|
-
.ws-address input { flex: 1; background: #16213e; border: 1px solid #2a2a4a; border-radius: 6px; padding: 7px 10px; color: #e0e0e0; font-size: 12px; font-family: monospace; outline: none; }
|
|
25
|
-
.ws-address input:focus { border-color: #4a9eff; }
|
|
26
|
-
.btn-sm { background: #2a2a4a; border: 1px solid #3a3a5a; border-radius: 6px; padding: 6px 12px; color: #e0e0e0; font-size: 12px; cursor: pointer; white-space: nowrap; }
|
|
27
|
-
.btn-sm:hover { background: #3a3a5a; }
|
|
14
|
+
#connectionList { background: #16213e; border-radius: 6px; overflow: hidden; }
|
|
28
15
|
|
|
29
|
-
.
|
|
30
|
-
.
|
|
31
|
-
.
|
|
32
|
-
.
|
|
33
|
-
.
|
|
34
|
-
.
|
|
35
|
-
.
|
|
36
|
-
.
|
|
16
|
+
.conn-item { padding: 8px 10px; border-bottom: 1px solid rgba(255,255,255,0.08); }
|
|
17
|
+
.conn-item:last-child { border-bottom: none; }
|
|
18
|
+
.conn-header { display: flex; align-items: center; gap: 6px; }
|
|
19
|
+
.conn-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
|
|
20
|
+
.conn-dot.connected { background: #4caf50; box-shadow: 0 0 4px #4caf50; }
|
|
21
|
+
.conn-dot.error { background: #f44336; box-shadow: 0 0 4px #f44336; }
|
|
22
|
+
.conn-dot.disabled { background: #9e9e9e; }
|
|
23
|
+
.conn-tag { font-weight: 600; font-size: 13px; color: #e0e0e0; }
|
|
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; }
|
|
37
25
|
|
|
38
|
-
.
|
|
39
|
-
.clients-info span { color: #4a9eff; }
|
|
26
|
+
.empty-hint { text-align: center; padding: 16px 10px; color: #777; font-size: 12px; }
|
|
40
27
|
|
|
41
|
-
.
|
|
28
|
+
.stats-row { display: flex; gap: 16px; padding: 8px 0; font-size: 12px; color: #aaa; }
|
|
29
|
+
.stats-row span b { color: #4a9eff; font-weight: 600; }
|
|
30
|
+
|
|
31
|
+
.btn-full { width: 100%; background: linear-gradient(135deg, #4a9eff, #357abd); border: none; border-radius: 6px; padding: 10px; color: #fff; font-size: 13px; font-weight: 600; cursor: pointer; transition: opacity 0.15s; margin-top: 6px; }
|
|
42
32
|
.btn-full:hover { opacity: 0.85; }
|
|
43
33
|
|
|
44
|
-
.footer { padding:
|
|
45
|
-
.footer a { color: #
|
|
34
|
+
.footer { padding: 6px 14px; text-align: right; }
|
|
35
|
+
.footer a { color: #555; font-size: 11px; text-decoration: none; }
|
|
46
36
|
.footer a:hover { color: #4a9eff; }
|
|
47
37
|
</style>
|
|
48
38
|
</head>
|
|
49
39
|
<body>
|
|
50
40
|
<div class="header">
|
|
51
41
|
<h1>CDP Bridge</h1>
|
|
52
|
-
<div class="status-badge off" id="statusBadge">
|
|
53
|
-
<div class="status-dot"></div>
|
|
54
|
-
<span id="statusText">未连接</span>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
|
|
58
|
-
<div class="section">
|
|
59
|
-
<div class="section-title">WebSocket 地址</div>
|
|
60
|
-
<div class="ws-address">
|
|
61
|
-
<input type="text" id="wsInput" placeholder="ws://localhost:9221/plugin" spellcheck="false">
|
|
62
|
-
<button class="btn-sm" id="saveBtn">保存</button>
|
|
63
|
-
</div>
|
|
64
42
|
</div>
|
|
65
43
|
|
|
66
|
-
<div class="
|
|
67
|
-
<div
|
|
68
|
-
<div id="cdpAddresses"></div>
|
|
69
|
-
</div>
|
|
44
|
+
<div class="body">
|
|
45
|
+
<div id="connectionList"></div>
|
|
70
46
|
|
|
71
|
-
<div class="
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
</div>
|
|
47
|
+
<div class="stats-row" id="statsRow" style="display:none;">
|
|
48
|
+
<span>活跃连接: <b id="statClients">0</b></span>
|
|
49
|
+
<span>页面: <b id="statPages">0</b></span>
|
|
50
|
+
</div>
|
|
75
51
|
|
|
76
|
-
<div class="section">
|
|
77
52
|
<button class="btn-full" id="openConfigBtn">打开完整配置</button>
|
|
78
53
|
</div>
|
|
79
54
|
|
package/extension-new/popup.js
CHANGED
|
@@ -1,127 +1,79 @@
|
|
|
1
1
|
(function() {
|
|
2
2
|
var $ = function(id) { return document.getElementById(id); };
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var cdpSection = $('cdpSection');
|
|
9
|
-
var cdpAddresses = $('cdpAddresses');
|
|
10
|
-
var clientsSection = $('clientsSection');
|
|
11
|
-
var clientsInfo = $('clientsInfo');
|
|
4
|
+
var connectionList = $('connectionList');
|
|
5
|
+
var statsRow = $('statsRow');
|
|
6
|
+
var statClients = $('statClients');
|
|
7
|
+
var statPages = $('statPages');
|
|
12
8
|
|
|
13
9
|
function loadState() {
|
|
14
|
-
chrome.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (!state) return;
|
|
19
|
-
updateStatus(state);
|
|
20
|
-
updateCDP(state);
|
|
21
|
-
updateClients(state);
|
|
10
|
+
chrome.runtime.sendMessage({ type: 'get-connection-statuses' }, function(resp) {
|
|
11
|
+
if (!resp || !resp.connections) return;
|
|
12
|
+
renderConnectionList(resp.connections);
|
|
13
|
+
updateStats(resp.connections);
|
|
22
14
|
});
|
|
23
15
|
}
|
|
24
16
|
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
var text = state.connected ? '已连接' : '未连接';
|
|
28
|
-
if (!state.connected && state.lastError) {
|
|
29
|
-
cls = 'err';
|
|
30
|
-
text = '错误';
|
|
31
|
-
}
|
|
32
|
-
statusBadge.className = 'status-badge ' + cls;
|
|
33
|
-
statusText.textContent = text;
|
|
34
|
-
}
|
|
17
|
+
function renderConnectionList(connections) {
|
|
18
|
+
connectionList.innerHTML = '';
|
|
35
19
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
cdpSection.style.display = 'none';
|
|
20
|
+
if (!connections || connections.length === 0) {
|
|
21
|
+
connectionList.innerHTML = '<div class="empty-hint">尚未配置连接</div>';
|
|
39
22
|
return;
|
|
40
23
|
}
|
|
41
|
-
cdpSection.style.display = '';
|
|
42
24
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
var cdpPath = '/devtools/browser/' + pluginId;
|
|
25
|
+
connections.forEach(function(conn) {
|
|
26
|
+
var item = document.createElement('div');
|
|
27
|
+
item.className = 'conn-item';
|
|
47
28
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (parsed) {
|
|
51
|
-
urls.push({ label: 'CDP 地址', url: parsed.protocol + '://' + parsed.host + cdpPath });
|
|
52
|
-
}
|
|
29
|
+
var header = document.createElement('div');
|
|
30
|
+
header.className = 'conn-header';
|
|
53
31
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
html += '<div class="cdp-row">';
|
|
57
|
-
html += '<div class="cdp-label">' + item.label + '</div>';
|
|
58
|
-
html += '<div class="cdp-url">';
|
|
59
|
-
html += '<code>' + escapeHtml(item.url) + '</code>';
|
|
60
|
-
html += '<button class="copy-btn" data-url="' + escapeAttr(item.url) + '">复制</button>';
|
|
61
|
-
html += '</div></div>';
|
|
62
|
-
});
|
|
63
|
-
cdpAddresses.innerHTML = html;
|
|
64
|
-
}
|
|
32
|
+
var dot = document.createElement('span');
|
|
33
|
+
dot.className = 'conn-dot ' + conn.status;
|
|
65
34
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
clientsSection.style.display = '';
|
|
72
|
-
var clients = state.cdpClients || [];
|
|
73
|
-
var attached = state.attachedPages || [];
|
|
74
|
-
clientsInfo.innerHTML = '活跃连接: <span>' + clients.length + '</span> | 已附加页面: <span>' + attached.length + '</span>';
|
|
75
|
-
}
|
|
35
|
+
var tag = document.createElement('span');
|
|
36
|
+
tag.className = 'conn-tag';
|
|
37
|
+
tag.textContent = conn.tag;
|
|
76
38
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (!m) return null;
|
|
80
|
-
return { protocol: m[1], host: m[2] };
|
|
81
|
-
}
|
|
39
|
+
header.appendChild(dot);
|
|
40
|
+
header.appendChild(tag);
|
|
82
41
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
function escapeAttr(s) {
|
|
87
|
-
return s.replace(/&/g,'&').replace(/"/g,'"').replace(/</g,'<').replace(/>/g,'>');
|
|
88
|
-
}
|
|
42
|
+
var url = document.createElement('div');
|
|
43
|
+
url.className = 'conn-url';
|
|
44
|
+
url.textContent = conn.url;
|
|
89
45
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
saveBtn.textContent = '已保存';
|
|
94
|
-
setTimeout(function() { saveBtn.textContent = '保存'; }, 1500);
|
|
95
|
-
chrome.runtime.sendMessage({ type: 'ws-reconnect' });
|
|
46
|
+
item.appendChild(header);
|
|
47
|
+
item.appendChild(url);
|
|
48
|
+
connectionList.appendChild(item);
|
|
96
49
|
});
|
|
97
|
-
}
|
|
50
|
+
}
|
|
98
51
|
|
|
99
|
-
|
|
100
|
-
var
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
btn.classList.add('copied');
|
|
106
|
-
setTimeout(function() {
|
|
107
|
-
btn.textContent = '复制';
|
|
108
|
-
btn.classList.remove('copied');
|
|
109
|
-
}, 2000);
|
|
52
|
+
function updateStats(connections) {
|
|
53
|
+
var active = 0;
|
|
54
|
+
var pages = 0;
|
|
55
|
+
connections.forEach(function(conn) {
|
|
56
|
+
if (conn.status === 'connected') active++;
|
|
57
|
+
pages += conn.attachedCount || 0;
|
|
110
58
|
});
|
|
111
|
-
});
|
|
112
59
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
60
|
+
if (active > 0 || pages > 0) {
|
|
61
|
+
statsRow.style.display = '';
|
|
62
|
+
} else {
|
|
63
|
+
statsRow.style.display = 'none';
|
|
64
|
+
}
|
|
65
|
+
statClients.textContent = active;
|
|
66
|
+
statPages.textContent = pages;
|
|
118
67
|
}
|
|
119
68
|
|
|
69
|
+
var openConfigBtn = $('openConfigBtn');
|
|
70
|
+
openConfigBtn.addEventListener('click', function() {
|
|
71
|
+
chrome.tabs.create({ url: chrome.runtime.getURL('config-page-preview.html') });
|
|
72
|
+
});
|
|
73
|
+
|
|
120
74
|
var versionLink = $('versionLink');
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
versionLink.textContent = 'v' + manifest.version;
|
|
124
|
-
}
|
|
75
|
+
var manifest = chrome.runtime.getManifest();
|
|
76
|
+
versionLink.textContent = 'v' + manifest.version;
|
|
125
77
|
|
|
126
78
|
loadState();
|
|
127
79
|
})();
|
package/package.json
CHANGED