cdp-tunnel 1.7.0 → 2.1.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 +18 -41
- package/extension-new/cdp/handler/special.js +15 -36
- package/extension-new/core/state.js +33 -2
- package/extension-new/core/websocket.js +18 -20
- package/extension-new/utils/helpers.js +51 -1
- package/package.json +21 -3
- package/extension-new/popup.html +0 -72
- package/extension-new/popup.js +0 -34
|
@@ -13,17 +13,6 @@ importScripts('cdp/index.js');
|
|
|
13
13
|
importScripts('features/screencast.js');
|
|
14
14
|
importScripts('features/automation-badge.js');
|
|
15
15
|
|
|
16
|
-
// 为字符串添加hashCode方法(用于生成颜色索引)
|
|
17
|
-
String.prototype.hashCode = function() {
|
|
18
|
-
var hash = 0;
|
|
19
|
-
for (var i = 0; i < this.length; i++) {
|
|
20
|
-
var char = this.charCodeAt(i);
|
|
21
|
-
hash = ((hash << 5) - hash) + char;
|
|
22
|
-
hash = hash & hash; // Convert to 32bit integer
|
|
23
|
-
}
|
|
24
|
-
return hash;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
16
|
(function() {
|
|
28
17
|
'use strict';
|
|
29
18
|
|
|
@@ -230,66 +219,54 @@ String.prototype.hashCode = function() {
|
|
|
230
219
|
|
|
231
220
|
// 将标签页添加到CDP组(添加延迟等待)
|
|
232
221
|
setTimeout(function() {
|
|
233
|
-
// 获取openerTabId对应的clientId
|
|
234
222
|
var openerClientId = openerTabId ? State.getClientIdByTabId(openerTabId) : null;
|
|
235
|
-
var
|
|
236
|
-
|
|
237
|
-
// 如果有指定的clientId,使用该clientId作为组名
|
|
238
|
-
if (openerClientId) {
|
|
239
|
-
groupName = 'CDP-' + openerClientId.substring(0, 8);
|
|
240
|
-
Logger.info('[TabGroup] Using opener clientId for group name:', groupName, 'openerTabId:', openerTabId);
|
|
241
|
-
} else {
|
|
242
|
-
// 回退到使用第一个CDP客户端的ID
|
|
223
|
+
var groupClientId = openerClientId;
|
|
224
|
+
if (!groupClientId) {
|
|
243
225
|
var cdpClients = State.getCDPClients() || [];
|
|
244
226
|
if (cdpClients.length > 0 && cdpClients[0] && cdpClients[0].id) {
|
|
245
|
-
|
|
246
|
-
} else {
|
|
247
|
-
// 如果没有CDP客户端,使用时间戳作为组名
|
|
248
|
-
groupName = 'CDP-' + Date.now().toString(36);
|
|
227
|
+
groupClientId = cdpClients[0].id;
|
|
249
228
|
}
|
|
250
|
-
Logger.info('[TabGroup] Using fallback clientId for group name:', groupName);
|
|
251
229
|
}
|
|
252
230
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
231
|
+
if (!groupClientId) return;
|
|
232
|
+
var baseName = CDPUtils.getGroupBaseName(groupClientId);
|
|
233
|
+
Logger.info('[TabGroup] background onCreated, baseName:', baseName);
|
|
234
|
+
|
|
235
|
+
chrome.tabGroups.query({}, function(allGroups) {
|
|
236
|
+
var existing = CDPUtils.findGroupByName(allGroups, baseName);
|
|
237
|
+
if (existing) {
|
|
238
|
+
chrome.tabs.group({ tabIds: tabId, groupId: existing.id }, function(groupId) {
|
|
257
239
|
if (chrome.runtime.lastError) {
|
|
258
240
|
Logger.error('[TabGroup] Failed to add tab to group:', chrome.runtime.lastError.message);
|
|
259
241
|
} else {
|
|
260
|
-
|
|
242
|
+
State.setGroupIdForClient(groupClientId, existing.id);
|
|
243
|
+
Logger.info('[TabGroup] Tab added to group:', groupId);
|
|
261
244
|
}
|
|
262
245
|
});
|
|
263
246
|
} else {
|
|
264
|
-
// 创建新组并添加标签页
|
|
265
247
|
chrome.tabs.group({ tabIds: tabId }, function(groupId) {
|
|
266
248
|
if (chrome.runtime.lastError) {
|
|
267
249
|
Logger.error('[TabGroup] Failed to create group:', chrome.runtime.lastError.message);
|
|
268
250
|
return;
|
|
269
251
|
}
|
|
270
|
-
// 更新组的标题和颜色
|
|
271
252
|
if (groupId) {
|
|
272
|
-
// 为不同的组使用不同的颜色
|
|
273
|
-
var colors = ['blue', 'red', 'yellow', 'green', 'pink', 'purple', 'cyan', 'orange'];
|
|
274
|
-
var colorIndex = Math.abs(groupName.hashCode ? groupName.hashCode() : 0) % colors.length;
|
|
275
|
-
var groupColor = colors[colorIndex];
|
|
276
|
-
|
|
277
253
|
chrome.tabGroups.update(groupId, {
|
|
278
|
-
title:
|
|
279
|
-
color:
|
|
254
|
+
title: baseName,
|
|
255
|
+
color: CDPUtils.getGroupColorForClient(groupClientId),
|
|
280
256
|
collapsed: true
|
|
281
257
|
}, function(group) {
|
|
282
258
|
if (chrome.runtime.lastError) {
|
|
283
259
|
Logger.error('[TabGroup] Failed to update group:', chrome.runtime.lastError.message);
|
|
284
260
|
} else {
|
|
285
|
-
|
|
261
|
+
State.setGroupIdForClient(groupClientId, groupId);
|
|
262
|
+
Logger.info('[TabGroup] Group created:', group);
|
|
286
263
|
}
|
|
287
264
|
});
|
|
288
265
|
}
|
|
289
266
|
});
|
|
290
267
|
}
|
|
291
268
|
});
|
|
292
|
-
}, 2000);
|
|
269
|
+
}, 2000);
|
|
293
270
|
|
|
294
271
|
Logger.info('[Tabs] Sending Target.attachedToTarget event');
|
|
295
272
|
|
|
@@ -132,34 +132,28 @@ var SpecialHandler = (function() {
|
|
|
132
132
|
muteTabIfNeeded(tabId);
|
|
133
133
|
}, 500);
|
|
134
134
|
|
|
135
|
-
var groupName;
|
|
136
135
|
var groupClientId = clientId;
|
|
137
|
-
|
|
138
|
-
if (clientId) {
|
|
139
|
-
groupName = 'CDP-' + clientId.substring(0, 8);
|
|
140
|
-
} else {
|
|
136
|
+
if (!groupClientId) {
|
|
141
137
|
var cdpClients = State.getCDPClients() || [];
|
|
142
138
|
if (cdpClients.length > 0 && cdpClients[0] && cdpClients[0].id) {
|
|
143
|
-
groupName = 'CDP-' + cdpClients[0].id.substring(0, 8);
|
|
144
139
|
groupClientId = cdpClients[0].id;
|
|
145
|
-
} else {
|
|
146
|
-
groupName = 'CDP-Automation';
|
|
147
140
|
}
|
|
148
141
|
}
|
|
142
|
+
|
|
143
|
+
if (!groupClientId) return;
|
|
144
|
+
var baseName = CDPUtils.getGroupBaseName(groupClientId);
|
|
149
145
|
|
|
150
146
|
setTimeout(function() {
|
|
151
|
-
Logger.info('[TabGroup] Executing group operation
|
|
147
|
+
Logger.info('[TabGroup] Executing group operation for:', baseName);
|
|
152
148
|
|
|
153
149
|
chrome.tabGroups.query({}, function(allGroups) {
|
|
154
|
-
var
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (groups.length > 0) {
|
|
158
|
-
chrome.tabs.group({ tabIds: tabId, groupId: groups[0].id }, function(result) {
|
|
150
|
+
var existing = CDPUtils.findGroupByName(allGroups, baseName);
|
|
151
|
+
if (existing) {
|
|
152
|
+
chrome.tabs.group({ tabIds: tabId, groupId: existing.id }, function(result) {
|
|
159
153
|
if (chrome.runtime.lastError) {
|
|
160
154
|
Logger.error('[TabGroup] Failed to add tab to group:', chrome.runtime.lastError.message);
|
|
161
155
|
} else {
|
|
162
|
-
State.setGroupIdForClient(groupClientId,
|
|
156
|
+
State.setGroupIdForClient(groupClientId, existing.id);
|
|
163
157
|
updateTabGroupName(groupClientId);
|
|
164
158
|
}
|
|
165
159
|
});
|
|
@@ -170,12 +164,9 @@ var SpecialHandler = (function() {
|
|
|
170
164
|
return;
|
|
171
165
|
}
|
|
172
166
|
if (groupId) {
|
|
173
|
-
var colors = ['blue', 'red', 'yellow', 'green', 'pink', 'purple', 'cyan', 'orange'];
|
|
174
|
-
var colorIndex = Math.abs(groupName.hashCode ? groupName.hashCode() : 0) % colors.length;
|
|
175
|
-
|
|
176
167
|
chrome.tabGroups.update(groupId, {
|
|
177
|
-
title:
|
|
178
|
-
color:
|
|
168
|
+
title: baseName,
|
|
169
|
+
color: CDPUtils.getGroupColorForClient(groupClientId),
|
|
179
170
|
collapsed: true
|
|
180
171
|
}, function() {
|
|
181
172
|
if (chrome.runtime.lastError) {
|
|
@@ -201,9 +192,8 @@ var SpecialHandler = (function() {
|
|
|
201
192
|
chrome.tabs.query({ groupId: groupId }, function(tabs) {
|
|
202
193
|
if (chrome.runtime.lastError || !tabs) return;
|
|
203
194
|
|
|
204
|
-
var
|
|
205
|
-
var
|
|
206
|
-
var newName = baseName + ' (' + count + ')';
|
|
195
|
+
var baseName = CDPUtils.getGroupBaseName(clientId);
|
|
196
|
+
var newName = baseName + ' (' + tabs.length + ')';
|
|
207
197
|
|
|
208
198
|
chrome.tabGroups.update(groupId, {
|
|
209
199
|
title: newName
|
|
@@ -217,17 +207,6 @@ var SpecialHandler = (function() {
|
|
|
217
207
|
});
|
|
218
208
|
}
|
|
219
209
|
|
|
220
|
-
// 为字符串添加hashCode方法(用于生成颜色索引)
|
|
221
|
-
String.prototype.hashCode = function() {
|
|
222
|
-
var hash = 0;
|
|
223
|
-
for (var i = 0; i < this.length; i++) {
|
|
224
|
-
var char = this.charCodeAt(i);
|
|
225
|
-
hash = ((hash << 5) - hash) + char;
|
|
226
|
-
hash = hash & hash; // Convert to 32bit integer
|
|
227
|
-
}
|
|
228
|
-
return hash;
|
|
229
|
-
};
|
|
230
|
-
|
|
231
210
|
function targetActivateTarget(context) {
|
|
232
211
|
var params = context.params;
|
|
233
212
|
var targetId = params && params.targetId;
|
|
@@ -399,7 +378,7 @@ function checkTabVisibility(tabId) {
|
|
|
399
378
|
if (clientId) {
|
|
400
379
|
State.setTabIdToClientId(target.tabId, clientId);
|
|
401
380
|
}
|
|
402
|
-
|
|
381
|
+
State.addPreExistingTab(target.tabId);
|
|
403
382
|
|
|
404
383
|
if (config.waitForDebuggerOnStart) {
|
|
405
384
|
State.addPendingDebuggerTab(target.tabId);
|
|
@@ -421,7 +400,7 @@ function checkTabVisibility(tabId) {
|
|
|
421
400
|
if (clientId) {
|
|
422
401
|
State.setTabIdToClientId(target.tabId, clientId);
|
|
423
402
|
}
|
|
424
|
-
|
|
403
|
+
State.addPreExistingTab(target.tabId);
|
|
425
404
|
|
|
426
405
|
if (config.waitForDebuggerOnStart) {
|
|
427
406
|
State.addPendingDebuggerTab(target.tabId);
|
|
@@ -24,7 +24,8 @@ var State = (function() {
|
|
|
24
24
|
clientIdToTabId: new Map(),
|
|
25
25
|
clientIdToSessionId: new Map(),
|
|
26
26
|
tabIdToClientId: new Map(),
|
|
27
|
-
clientIdToGroupId: new Map()
|
|
27
|
+
clientIdToGroupId: new Map(),
|
|
28
|
+
preExistingTabIds: new Set()
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
function mapSession(sessionId, tabId, targetId) {
|
|
@@ -264,6 +265,7 @@ var State = (function() {
|
|
|
264
265
|
_state.hasConnectedClient = false;
|
|
265
266
|
_state.tabIdToClientId.clear();
|
|
266
267
|
_state.clientIdToGroupId.clear();
|
|
268
|
+
_state.preExistingTabIds.clear();
|
|
267
269
|
}
|
|
268
270
|
|
|
269
271
|
function cleanupAllTabs() {
|
|
@@ -346,6 +348,30 @@ var State = (function() {
|
|
|
346
348
|
_state.clientIdToGroupId.delete(clientId);
|
|
347
349
|
}
|
|
348
350
|
|
|
351
|
+
function addPreExistingTab(tabId) {
|
|
352
|
+
_state.preExistingTabIds.add(tabId);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function isPreExistingTab(tabId) {
|
|
356
|
+
return _state.preExistingTabIds.has(tabId);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function getPreExistingTabs() {
|
|
360
|
+
return Array.from(_state.preExistingTabIds);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function removePreExistingTab(tabId) {
|
|
364
|
+
_state.preExistingTabIds.delete(tabId);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function clearPreExistingTabsForClient(clientId) {
|
|
368
|
+
_state.preExistingTabIds.forEach(function(tabId) {
|
|
369
|
+
if (State.getClientIdByTabId(tabId) === clientId) {
|
|
370
|
+
_state.preExistingTabIds.delete(tabId);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
|
|
349
375
|
function getTabIdByClientId(clientId) {
|
|
350
376
|
return _state.clientIdToTabId.get(clientId);
|
|
351
377
|
}
|
|
@@ -448,6 +474,11 @@ var State = (function() {
|
|
|
448
474
|
getClientIdByTabId: getClientIdByTabId,
|
|
449
475
|
setGroupIdForClient: setGroupIdForClient,
|
|
450
476
|
getGroupIdForClient: getGroupIdForClient,
|
|
451
|
-
removeGroupForClient: removeGroupForClient
|
|
477
|
+
removeGroupForClient: removeGroupForClient,
|
|
478
|
+
addPreExistingTab: addPreExistingTab,
|
|
479
|
+
isPreExistingTab: isPreExistingTab,
|
|
480
|
+
getPreExistingTabs: getPreExistingTabs,
|
|
481
|
+
removePreExistingTab: removePreExistingTab,
|
|
482
|
+
clearPreExistingTabsForClient: clearPreExistingTabsForClient
|
|
452
483
|
};
|
|
453
484
|
})();
|
|
@@ -199,6 +199,16 @@ var WebSocketManager = (function() {
|
|
|
199
199
|
closeTabsByClientId(discClientId, resolve);
|
|
200
200
|
});
|
|
201
201
|
}).then(function() {
|
|
202
|
+
var preExistingTabs = State.getPreExistingTabs();
|
|
203
|
+
var clientPreExisting = preExistingTabs.filter(function(tabId) {
|
|
204
|
+
return State.getClientIdByTabId(tabId) === discClientId;
|
|
205
|
+
});
|
|
206
|
+
clientPreExisting.forEach(function(tabId) {
|
|
207
|
+
chrome.debugger.detach({ tabId: tabId }).catch(function() {});
|
|
208
|
+
State.removeAttachedTab(tabId);
|
|
209
|
+
});
|
|
210
|
+
State.clearPreExistingTabsForClient(discClientId);
|
|
211
|
+
|
|
202
212
|
State.removeCDPClient(discClientId);
|
|
203
213
|
if (State.getCDPClients().length === 0) {
|
|
204
214
|
State.setHasConnectedClient(false);
|
|
@@ -261,26 +271,14 @@ var WebSocketManager = (function() {
|
|
|
261
271
|
if (groupId) {
|
|
262
272
|
closeGroupById(groupId, clientId, resolve);
|
|
263
273
|
} else {
|
|
264
|
-
var
|
|
265
|
-
chrome.tabGroups.query({
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
var match = allGroups.find(function(g) {
|
|
270
|
-
return g.title && g.title.indexOf(groupName) === 0;
|
|
271
|
-
});
|
|
272
|
-
if (match) {
|
|
273
|
-
closeGroupById(match.id, clientId, resolve);
|
|
274
|
-
} else {
|
|
275
|
-
Logger.info('[WS] No tab group found, closing tabs by clientId:', clientId);
|
|
276
|
-
closeTabsByClientId(clientId, resolve);
|
|
277
|
-
}
|
|
278
|
-
} else {
|
|
279
|
-
resolve();
|
|
280
|
-
}
|
|
281
|
-
});
|
|
274
|
+
var baseName = CDPUtils.getGroupBaseName(clientId);
|
|
275
|
+
chrome.tabGroups.query({}, function(allGroups) {
|
|
276
|
+
var match = CDPUtils.findGroupByName(allGroups, baseName);
|
|
277
|
+
if (match) {
|
|
278
|
+
closeGroupById(match.id, clientId, resolve);
|
|
282
279
|
} else {
|
|
283
|
-
|
|
280
|
+
Logger.info('[WS] No tab group found, closing tabs by clientId:', clientId);
|
|
281
|
+
closeTabsByClientId(clientId, resolve);
|
|
284
282
|
}
|
|
285
283
|
});
|
|
286
284
|
}
|
|
@@ -321,7 +319,7 @@ var WebSocketManager = (function() {
|
|
|
321
319
|
var tabsToClose = [];
|
|
322
320
|
|
|
323
321
|
attachedTabs.forEach(function(tabId) {
|
|
324
|
-
if (State.getClientIdByTabId(tabId) === clientId) {
|
|
322
|
+
if (State.getClientIdByTabId(tabId) === clientId && !State.isPreExistingTab(tabId)) {
|
|
325
323
|
tabsToClose.push(tabId);
|
|
326
324
|
}
|
|
327
325
|
});
|
|
@@ -17,9 +17,59 @@ var CDPUtils = (function() {
|
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
function hashCode(str) {
|
|
21
|
+
var hash = 0;
|
|
22
|
+
for (var i = 0; i < str.length; i++) {
|
|
23
|
+
var char = str.charCodeAt(i);
|
|
24
|
+
hash = ((hash << 5) - hash) + char;
|
|
25
|
+
hash = hash & hash;
|
|
26
|
+
}
|
|
27
|
+
return hash;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var GROUP_COLORS = ['blue', 'cyan', 'green', 'yellow', 'orange', 'red', 'pink', 'purple'];
|
|
31
|
+
|
|
32
|
+
function getGroupColorForClient(clientId) {
|
|
33
|
+
var idx = Math.abs(hashCode(clientId)) % GROUP_COLORS.length;
|
|
34
|
+
return GROUP_COLORS[idx];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getClientIndex(clientId) {
|
|
38
|
+
var clients = (typeof State !== 'undefined') ? (State.getCDPClients() || []) : [];
|
|
39
|
+
for (var i = 0; i < clients.length; i++) {
|
|
40
|
+
if (clients[i].id === clientId) return i + 1;
|
|
41
|
+
}
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function buildGroupName(clientId) {
|
|
46
|
+
if (!clientId) return 'CDP';
|
|
47
|
+
var idx = getClientIndex(clientId);
|
|
48
|
+
return idx > 0 ? ('CDP #' + idx) : ('CDP-' + clientId.substring(0, 6));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getGroupBaseName(clientId) {
|
|
52
|
+
return buildGroupName(clientId);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function findGroupByName(allGroups, baseName) {
|
|
56
|
+
for (var i = 0; i < allGroups.length; i++) {
|
|
57
|
+
var g = allGroups[i];
|
|
58
|
+
if (g.title && g.title.indexOf(baseName) === 0) return g;
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
20
63
|
return {
|
|
21
64
|
generateSessionId: generateSessionId,
|
|
22
65
|
getChromeVersion: getChromeVersion,
|
|
23
|
-
sleep: sleep
|
|
66
|
+
sleep: sleep,
|
|
67
|
+
hashCode: hashCode,
|
|
68
|
+
GROUP_COLORS: GROUP_COLORS,
|
|
69
|
+
getGroupColorForClient: getGroupColorForClient,
|
|
70
|
+
getClientIndex: getClientIndex,
|
|
71
|
+
buildGroupName: buildGroupName,
|
|
72
|
+
getGroupBaseName: getGroupBaseName,
|
|
73
|
+
findGroupByName: findGroupByName
|
|
24
74
|
};
|
|
25
75
|
})();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cdp-tunnel",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Chrome
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Bridge Chrome's debugger API to WebSocket — control your existing browser with Playwright/Puppeteer via CDP",
|
|
5
5
|
"main": "server/proxy-server.js",
|
|
6
6
|
"bin": "./cli/index.js",
|
|
7
7
|
"scripts": {
|
|
@@ -19,12 +19,30 @@
|
|
|
19
19
|
"keywords": [
|
|
20
20
|
"cdp",
|
|
21
21
|
"chrome-devtools-protocol",
|
|
22
|
+
"cdp-proxy",
|
|
22
23
|
"playwright",
|
|
23
24
|
"puppeteer",
|
|
24
|
-
"chrome-extension"
|
|
25
|
+
"chrome-extension",
|
|
26
|
+
"browser-automation",
|
|
27
|
+
"web-scraping",
|
|
28
|
+
"remote-debugging",
|
|
29
|
+
"websocket",
|
|
30
|
+
"testing",
|
|
31
|
+
"browser-control"
|
|
25
32
|
],
|
|
26
33
|
"author": "dyyz1993",
|
|
27
34
|
"license": "Apache-2.0",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/dyyz1993/cdp-tunnel.git"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/dyyz1993/cdp-tunnel#readme",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/dyyz1993/cdp-tunnel/issues"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=16.0.0"
|
|
45
|
+
},
|
|
28
46
|
"files": [
|
|
29
47
|
"server/",
|
|
30
48
|
"cli/",
|
package/extension-new/popup.html
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<style>
|
|
6
|
-
body {
|
|
7
|
-
width: 300px;
|
|
8
|
-
padding: 15px;
|
|
9
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
10
|
-
font-size: 14px;
|
|
11
|
-
}
|
|
12
|
-
.status {
|
|
13
|
-
display: flex;
|
|
14
|
-
align-items: center;
|
|
15
|
-
margin-bottom: 15px;
|
|
16
|
-
}
|
|
17
|
-
.status-dot {
|
|
18
|
-
width: 10px;
|
|
19
|
-
height: 10px;
|
|
20
|
-
border-radius: 50%;
|
|
21
|
-
margin-right: 8px;
|
|
22
|
-
}
|
|
23
|
-
.status-dot.active {
|
|
24
|
-
background-color: #4CAF50;
|
|
25
|
-
}
|
|
26
|
-
.status-dot.inactive {
|
|
27
|
-
background-color: #9E9E9E;
|
|
28
|
-
}
|
|
29
|
-
.config-section {
|
|
30
|
-
margin-top: 15px;
|
|
31
|
-
}
|
|
32
|
-
.config-section label {
|
|
33
|
-
display: block;
|
|
34
|
-
margin-bottom: 5px;
|
|
35
|
-
font-weight: 500;
|
|
36
|
-
}
|
|
37
|
-
.config-section input {
|
|
38
|
-
width: 100%;
|
|
39
|
-
padding: 8px;
|
|
40
|
-
border: 1px solid #ddd;
|
|
41
|
-
border-radius: 4px;
|
|
42
|
-
box-sizing: border-box;
|
|
43
|
-
}
|
|
44
|
-
.config-section button {
|
|
45
|
-
margin-top: 10px;
|
|
46
|
-
padding: 8px 16px;
|
|
47
|
-
background-color: #2196F3;
|
|
48
|
-
color: white;
|
|
49
|
-
border: none;
|
|
50
|
-
border-radius: 4px;
|
|
51
|
-
cursor: pointer;
|
|
52
|
-
}
|
|
53
|
-
.config-section button:hover {
|
|
54
|
-
background-color: #1976D2;
|
|
55
|
-
}
|
|
56
|
-
</style>
|
|
57
|
-
</head>
|
|
58
|
-
<body>
|
|
59
|
-
<div class="status">
|
|
60
|
-
<div class="status-dot active" id="statusDot"></div>
|
|
61
|
-
<span id="statusText">已激活</span>
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
<div class="config-section">
|
|
65
|
-
<label>WebSocket 地址</label>
|
|
66
|
-
<input type="text" id="wsAddress" placeholder="ws://localhost:9221/client">
|
|
67
|
-
<button id="saveBtn">保存</button>
|
|
68
|
-
</div>
|
|
69
|
-
|
|
70
|
-
<script src="popup.js"></script>
|
|
71
|
-
</body>
|
|
72
|
-
</html>
|
package/extension-new/popup.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
2
|
-
var statusDot = document.getElementById('statusDot');
|
|
3
|
-
var statusText = document.getElementById('statusText');
|
|
4
|
-
var wsAddressInput = document.getElementById('wsAddress');
|
|
5
|
-
var saveBtn = document.getElementById('saveBtn');
|
|
6
|
-
|
|
7
|
-
chrome.storage.local.get(['wsAddress'], function(result) {
|
|
8
|
-
if (result.wsAddress) {
|
|
9
|
-
wsAddressInput.value = result.wsAddress;
|
|
10
|
-
} else {
|
|
11
|
-
wsAddressInput.value = 'ws://localhost:9221/plugin';
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
saveBtn.addEventListener('click', function() {
|
|
16
|
-
var newAddress = wsAddressInput.value.trim();
|
|
17
|
-
if (newAddress) {
|
|
18
|
-
chrome.storage.local.set({ wsAddress: newAddress }, function() {
|
|
19
|
-
statusText.textContent = '已保存,正在重连...';
|
|
20
|
-
|
|
21
|
-
chrome.runtime.sendMessage({ type: 'reconnect' }, function(response) {
|
|
22
|
-
if (response && response.success) {
|
|
23
|
-
statusText.textContent = '已激活';
|
|
24
|
-
} else {
|
|
25
|
-
statusText.textContent = '重连失败';
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
statusDot.classList.add('active');
|
|
33
|
-
statusText.textContent = '已激活';
|
|
34
|
-
});
|