cdp-tunnel 1.0.13 → 1.0.14

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.
Files changed (68) hide show
  1. package/extension-new/background.js +6 -1
  2. package/extension-new/cdp/handler/special.js +47 -27
  3. package/extension-new/core/state.js +64 -6
  4. package/extension-new/core/websocket.js +124 -19
  5. package/package.json +9 -2
  6. package/server/proxy-server.js +45 -34
  7. package/.github/workflows/publish.yml +0 -92
  8. package/.github/workflows/release-assets.yml +0 -50
  9. package/PUBLISH.md +0 -65
  10. package/console-test.js +0 -52
  11. package/docs/README_CN.md +0 -204
  12. package/docs/config-page-screenshot.png +0 -0
  13. package/final-console-test.js +0 -105
  14. package/simple-tab-group-test.js +0 -56
  15. package/test-cdp-connection.js +0 -85
  16. package/test-cdp-groups.js +0 -71
  17. package/test-check-newtab.js +0 -144
  18. package/test-chrome-native.js +0 -140
  19. package/test-client-connected.js +0 -99
  20. package/test-compare-formats.js +0 -88
  21. package/test-context-features.js +0 -113
  22. package/test-create-tab.js +0 -113
  23. package/test-debug-broadcast.js +0 -52
  24. package/test-debug-targets.js +0 -127
  25. package/test-expose-newtab.js +0 -164
  26. package/test-expose-shared.js +0 -189
  27. package/test-final-logs.js +0 -110
  28. package/test-fresh-chromium.js +0 -153
  29. package/test-init-script.js +0 -128
  30. package/test-keepalive.js +0 -89
  31. package/test-launch-chromium.js +0 -140
  32. package/test-launch-vs-connect.js +0 -149
  33. package/test-listen-events.js +0 -102
  34. package/test-monitor.js +0 -83
  35. package/test-multiple-cdp-groups.js +0 -78
  36. package/test-native.js +0 -96
  37. package/test-page-connection.js +0 -74
  38. package/test-playwright-connection.js +0 -45
  39. package/test-playwright-groups.js +0 -47
  40. package/test-playwright-pages.js +0 -47
  41. package/test-playwright-sequence.js +0 -81
  42. package/test-proper-context.js +0 -129
  43. package/test-real-final.js +0 -251
  44. package/test-real-scenario-v2.js +0 -166
  45. package/test-real-scenario-v3.js +0 -231
  46. package/test-real-scenario.js +0 -104
  47. package/test-server-logs.js +0 -98
  48. package/test-session-id.js +0 -91
  49. package/test-simple-cdp-groups.js +0 -44
  50. package/test-simple-context.js +0 -137
  51. package/test-tab-group-simple.js +0 -58
  52. package/test-tab-grouping.js +0 -48
  53. package/test-three-pages.js +0 -192
  54. package/test-wait-for-page.js +0 -95
  55. package/test-with-logs.js +0 -118
  56. package/test-ws-groups.js +0 -59
  57. package/tests/e2e-auto-test.js +0 -304
  58. package/tests/iframe-test-page.html +0 -89
  59. package/tests/playwright-demo.js +0 -45
  60. package/tests/playwright-interactive.js +0 -261
  61. package/tests/playwright-multi-demo.js +0 -60
  62. package/tests/playwright-multi.js +0 -85
  63. package/tests/playwright-single.js +0 -41
  64. package/tests/screenshot-config.js +0 -35
  65. package/tests/test-client.js +0 -89
  66. package/tests/test-douyin-iframe.js +0 -171
  67. package/tests/test-iframe-debug.js +0 -204
  68. package/tests/test-multi-client.js +0 -129
@@ -1,171 +0,0 @@
1
- const { chromium } = require('playwright');
2
-
3
- const SERVER_URL = process.env.CDP_SERVER || 'http://localhost:9221';
4
- const DOUYIN_URL = 'https://www.douyin.com/user/MS4wLjABAAAAnKeRN8QUgooS1pPRqOf_N_jnuztzUyocl0_vUndQFJs?modal_id=7635666432337351530';
5
-
6
- async function sleep(ms) {
7
- return new Promise(r => setTimeout(r, ms));
8
- }
9
-
10
- async function main() {
11
- console.log('=== Douyin IFrame Disconnect Test ===');
12
- console.log(`Server: ${SERVER_URL}\n`);
13
-
14
- let browser;
15
- try {
16
- console.log('[1] Connecting to CDP tunnel...');
17
- browser = await chromium.connectOverCDP(SERVER_URL, { timeout: 15000 });
18
- console.log('[1] Connected!\n');
19
-
20
- const context = browser.contexts()[0];
21
- const page = context.pages()[0] || await context.newPage();
22
-
23
- console.log('[2] Navigating to Douyin page...');
24
- await page.goto(DOUYIN_URL, { waitUntil: 'domcontentloaded', timeout: 30000 });
25
- console.log(`[2] Page loaded: ${page.url()}\n`);
26
-
27
- await sleep(3000);
28
- console.log('[3] Waiting for page to fully render...');
29
- await sleep(2000);
30
-
31
- // Check frame tree first
32
- console.log('[4] Checking frame tree...');
33
- try {
34
- const cdpSession = await page.context().newCDPSession(page);
35
- const frameTree = await cdpSession.send('Page.getFrameTree');
36
-
37
- function printFrame(tree, indent) {
38
- if (!tree || !tree.frame) return;
39
- const pad = ' '.repeat(indent);
40
- console.log(`${pad}Frame: id=${tree.frame.id} url=${(tree.frame.url || '').substring(0, 80)}`);
41
- if (tree.childFrames) {
42
- for (const child of tree.childFrames) printFrame(child, indent + 1);
43
- }
44
- }
45
- printFrame(frameTree.frameTree, 0);
46
- await cdpSession.detach();
47
- } catch (e) {
48
- console.error('[4] Frame tree error:', e.message);
49
- }
50
- console.log('');
51
-
52
- // Try to find and click the entry button
53
- // The button has data-popupid attribute and contains an SVG
54
- console.log('[5] Looking for the entry button...');
55
- const selectors = [
56
- '[data-popupid]',
57
- 'svg.wNbQukcA',
58
- '.r68hW_1W',
59
- ];
60
-
61
- let clicked = false;
62
- for (const sel of selectors) {
63
- try {
64
- const el = page.locator(sel).first();
65
- const count = await el.count();
66
- if (count > 0) {
67
- console.log(`[5] Found element with selector: ${sel}`);
68
- await el.click({ timeout: 5000 });
69
- console.log(`[5] Clicked!`);
70
- clicked = true;
71
- break;
72
- }
73
- } catch (e) {
74
- console.log(`[5] Selector ${sel}: ${e.message.substring(0, 80)}`);
75
- }
76
- }
77
-
78
- if (!clicked) {
79
- console.log('[5] Could not find entry button with known selectors, trying to list clickable elements...');
80
- const buttons = await page.$$eval('[data-popupid]', els => els.map(e => ({
81
- tag: e.tagName,
82
- popupid: e.getAttribute('data-popupid'),
83
- html: e.innerHTML.substring(0, 100)
84
- })));
85
- console.log('[5] Elements with data-popupid:', JSON.stringify(buttons, null, 2));
86
- }
87
-
88
- await sleep(3000);
89
-
90
- // Check frame tree again after click
91
- console.log('\n[6] Checking frame tree AFTER click...');
92
- try {
93
- const cdpSession = await page.context().newCDPSession(page);
94
- const frameTree = await cdpSession.send('Page.getFrameTree');
95
- printFrameTree(frameTree.frameTree, 0);
96
- await cdpSession.detach();
97
- } catch (e) {
98
- console.error('[6] Frame tree error:', e.message);
99
- }
100
-
101
- // List all iframes on the page
102
- console.log('\n[7] Listing all iframes...');
103
- const iframes = await page.$$eval('iframe', els => els.map(e => ({
104
- id: e.id,
105
- src: e.src || e.getAttribute('srcdoc')?.substring(0, 50) || '(empty)',
106
- className: e.className,
107
- visible: e.offsetParent !== null
108
- })));
109
- console.log('[7] Iframes found:', JSON.stringify(iframes, null, 2));
110
-
111
- // Try to find and interact with iframe input
112
- console.log('\n[8] Trying to find input in iframes...');
113
- const frames = page.frames();
114
- console.log(`[8] Total frames: ${frames.length}`);
115
- for (let i = 0; i < frames.length; i++) {
116
- const frame = frames[i];
117
- console.log(`[8] Frame ${i}: url=${frame.url().substring(0, 80)} name=${frame.name()}`);
118
-
119
- if (frame === page.mainFrame()) continue;
120
-
121
- try {
122
- const inputs = await frame.locator('input, textarea').count();
123
- console.log(`[8] Found ${inputs} input/textarea elements`);
124
-
125
- if (inputs > 0) {
126
- console.log(`[8] Attempting to click first input in frame ${i}...`);
127
- const input = frame.locator('input, textarea').first();
128
- await input.click({ timeout: 5000 });
129
- console.log(`[8] CLICK SUCCEEDED - no disconnect!`);
130
-
131
- await sleep(1000);
132
- await input.fill('test input');
133
- console.log(`[8] FILL SUCCEEDED`);
134
- }
135
- } catch (e) {
136
- console.error(`[8] Frame ${i} error: ${e.message.substring(0, 120)}`);
137
- }
138
- }
139
-
140
- console.log('\n=== Test completed - Playwright did NOT disconnect ===');
141
-
142
- } catch (e) {
143
- console.error('\n!!! FATAL ERROR - Possible disconnect !!!');
144
- console.error('Error:', e.message);
145
- console.error('This might indicate Playwright disconnected');
146
- } finally {
147
- if (browser) {
148
- try {
149
- await browser.close();
150
- console.log('\nBrowser closed normally');
151
- } catch (e) {
152
- console.error('\nBrowser close FAILED:', e.message);
153
- console.error('This confirms Playwright disconnected');
154
- }
155
- }
156
- }
157
- }
158
-
159
- function printFrameTree(tree, indent) {
160
- if (!tree || !tree.frame) return;
161
- const pad = ' '.repeat(indent);
162
- console.log(`${pad}Frame: id=${tree.frame.id} url=${(tree.frame.url || '').substring(0, 80)}`);
163
- if (tree.childFrames) {
164
- for (const child of tree.childFrames) printFrameTree(child, indent + 1);
165
- }
166
- }
167
-
168
- main().catch(e => {
169
- console.error('UNHANDLED:', e);
170
- process.exit(1);
171
- });
@@ -1,204 +0,0 @@
1
- const { chromium } = require('playwright');
2
-
3
- const SERVER_URL = process.env.CDP_SERVER || 'http://localhost:9221';
4
- const TEST_PAGE = `file://${__dirname}/iframe-test-page.html`;
5
-
6
- async function sleep(ms) {
7
- return new Promise(r => setTimeout(r, ms));
8
- }
9
-
10
- async function main() {
11
- console.log('=== IFrame Debug Test ===');
12
- console.log(`Server: ${SERVER_URL}`);
13
- console.log(`Test page: ${TEST_PAGE}\n`);
14
-
15
- let browser;
16
- try {
17
- console.log('[1] Connecting to CDP tunnel...');
18
- browser = await chromium.connectOverCDP(SERVER_URL, {
19
- timeout: 10000
20
- });
21
- console.log('[1] Connected!\n');
22
-
23
- const context = browser.contexts()[0];
24
- if (!context) {
25
- throw new Error('No default context found');
26
- }
27
-
28
- const pages = context.pages();
29
- let page;
30
- if (pages.length > 0) {
31
- page = pages[0];
32
- console.log(`[2] Using existing page: ${page.url()}`);
33
- } else {
34
- page = await context.newPage();
35
- console.log('[2] Created new page');
36
- }
37
-
38
- console.log(`[2] Navigating to test page...`);
39
- await page.goto(TEST_PAGE, { waitUntil: 'domcontentloaded', timeout: 15000 });
40
- console.log(`[2] Page loaded: ${page.url()}\n`);
41
-
42
- // --- Test 1: Main page input ---
43
- console.log('[Test 1] Main page input...');
44
- try {
45
- await page.fill('#main-input-1', 'Hello from main');
46
- const val1 = await page.inputValue('#main-input-1');
47
- console.log(`[Test 1] OK - value: "${val1}"\n`);
48
- } catch (e) {
49
- console.error(`[Test 1] FAIL: ${e.message}\n`);
50
- }
51
-
52
- // --- Test 2: Main page button ---
53
- console.log('[Test 2] Main page button click...');
54
- try {
55
- await page.click('#main-btn');
56
- await sleep(500);
57
- const status = await page.textContent('#status');
58
- console.log(`[Test 2] OK - status: "${status}"\n`);
59
- } catch (e) {
60
- console.error(`[Test 2] FAIL: ${e.message}\n`);
61
- }
62
-
63
- // --- Test 3: Same-origin iframe ---
64
- console.log('[Test 3] Same-origin iframe input...');
65
- try {
66
- const frame = page.frameLocator('#same-origin-iframe');
67
- const input = frame.locator('#iframe-input-1');
68
- await input.fill('Hello from iframe');
69
- const val = await input.inputValue();
70
- console.log(`[Test 3] OK - value: "${val}"\n`);
71
- } catch (e) {
72
- console.error(`[Test 3] FAIL: ${e.message}\n`);
73
- }
74
-
75
- // --- Test 4: Same-origin iframe button ---
76
- console.log('[Test 4] Same-origin iframe button click...');
77
- try {
78
- const frame = page.frameLocator('#same-origin-iframe');
79
- await frame.locator('#iframe-btn').click();
80
- await sleep(500);
81
- const result = await frame.locator('#iframe-result').textContent();
82
- console.log(`[Test 4] OK - result: "${result}"\n`);
83
- } catch (e) {
84
- console.error(`[Test 4] FAIL: ${e.message}\n`);
85
- }
86
-
87
- // --- Test 5: Cross-origin iframe (Wikipedia) ---
88
- console.log('[Test 5] Cross-origin iframe (Wikipedia)...');
89
- try {
90
- const frame = page.frameLocator('#cross-origin-iframe');
91
- // Just try to access the frame - this will likely fail
92
- const title = await frame.locator('h1').first().textContent({ timeout: 5000 });
93
- console.log(`[Test 5] OK - title: "${title}"\n`);
94
- } catch (e) {
95
- console.error(`[Test 5] FAIL (expected): ${e.message}\n`);
96
- }
97
-
98
- // --- Test 6: Nested iframe ---
99
- console.log('[Test 6] Nested iframe (level 1 input)...');
100
- try {
101
- const frame = page.frameLocator('#nested-iframe');
102
- await frame.locator('#l1-input').fill('Level 1');
103
- const val = await frame.locator('#l1-input').inputValue();
104
- console.log(`[Test 6] OK - value: "${val}"\n`);
105
- } catch (e) {
106
- console.error(`[Test 6] FAIL: ${e.message}\n`);
107
- }
108
-
109
- // --- Test 7: Nested iframe level 2 ---
110
- console.log('[Test 7] Nested iframe (level 2 input)...');
111
- try {
112
- const frame = page.frameLocator('#nested-iframe').frameLocator('#nested-inner');
113
- await frame.locator('#l2-input').fill('Level 2');
114
- const val = await frame.locator('#l2-input').inputValue();
115
- console.log(`[Test 7] OK - value: "${val}"\n`);
116
- } catch (e) {
117
- console.error(`[Test 7] FAIL: ${e.message}\n`);
118
- }
119
-
120
- // --- Test 8: Dynamic iframe ---
121
- console.log('[Test 8] Dynamic iframe...');
122
- try {
123
- await page.click('#create-iframe-btn');
124
- await sleep(1000);
125
- const frame = page.frameLocator('#dynamic-iframe');
126
- await frame.locator('#dyn-input').fill('Dynamic!');
127
- const val = await frame.locator('#dyn-input').inputValue();
128
- console.log(`[Test 8] OK - value: "${val}"\n`);
129
- } catch (e) {
130
- console.error(`[Test 8] FAIL: ${e.message}\n`);
131
- }
132
-
133
- // --- Test 9: Page.getFrameTree via CDP directly ---
134
- console.log('[Test 9] CDP Page.getFrameTree...');
135
- try {
136
- const cdpSession = await page.context().newCDPSession(page);
137
- const frameTree = await cdpSession.send('Page.getFrameTree');
138
- console.log(`[Test 9] Frame tree:`);
139
- printFrameTree(frameTree.frameTree, 0);
140
- await cdpSession.detach();
141
- console.log('');
142
- } catch (e) {
143
- console.error(`[Test 9] FAIL: ${e.message}\n`);
144
- }
145
-
146
- // --- Test 10: Target.setAutoAttach + Target.attachedToTarget ---
147
- console.log('[Test 10] CDP Target.setAutoAttach + iframe sessions...');
148
- try {
149
- const cdpSession = await page.context().newCDPSession(page);
150
-
151
- let attachedEventCount = 0;
152
- cdpSession.on('Target.attachedToTarget', (event) => {
153
- attachedEventCount++;
154
- console.log(`[Test 10] Target.attachedToTarget event #${attachedEventCount}:`);
155
- console.log(` sessionId: ${event.sessionId}`);
156
- console.log(` targetInfo.type: ${event.targetInfo?.type}`);
157
- console.log(` targetInfo.targetId: ${event.targetInfo?.targetId}`);
158
- console.log(` targetInfo.url: ${event.targetInfo?.url}`);
159
- console.log(` waitingForDebugger: ${event.waitingForDebugger}`);
160
- });
161
-
162
- cdpSession.on('Target.targetCreated', (event) => {
163
- console.log(`[Test 10] Target.targetCreated: type=${event.targetInfo?.type} targetId=${event.targetInfo?.targetId}`);
164
- });
165
-
166
- await cdpSession.send('Target.setAutoAttach', {
167
- autoAttach: true,
168
- waitForDebuggerOnStart: false,
169
- flatten: true
170
- });
171
-
172
- await sleep(3000);
173
-
174
- console.log(`[Test 10] Total attachedToTarget events: ${attachedEventCount}`);
175
- await cdpSession.detach();
176
- console.log('');
177
- } catch (e) {
178
- console.error(`[Test 10] FAIL: ${e.message}\n`);
179
- }
180
-
181
- console.log('=== All tests completed ===');
182
-
183
- } catch (e) {
184
- console.error('Fatal error:', e);
185
- } finally {
186
- if (browser) {
187
- await browser.close().catch(() => {});
188
- }
189
- }
190
- }
191
-
192
- function printFrameTree(tree, indent) {
193
- if (!tree || !tree.frame) return;
194
- const pad = ' '.repeat(indent);
195
- const frame = tree.frame;
196
- console.log(`${pad}Frame: id=${frame.id} url=${frame.url?.substring(0, 60)}`);
197
- if (tree.childFrames) {
198
- for (const child of tree.childFrames) {
199
- printFrameTree(child, indent + 1);
200
- }
201
- }
202
- }
203
-
204
- main().catch(console.error);
@@ -1,129 +0,0 @@
1
- const WebSocket = require('ws');
2
-
3
- const SERVER_URL = process.argv[2] || 'ws://localhost:9221';
4
- const NUM_CLIENTS = parseInt(process.argv[3]) || 2;
5
-
6
- console.log(`Starting ${NUM_CLIENTS} test clients connecting to ${SERVER_URL}...\n`);
7
-
8
- const clients = [];
9
-
10
- for (let i = 0; i < NUM_CLIENTS; i++) {
11
- const clientId = `test-client-${i + 1}`;
12
- const client = createClient(clientId);
13
- clients.push(client);
14
- }
15
-
16
- function createClient(clientId) {
17
- console.log(`[${clientId}] Connecting...`);
18
-
19
- const ws = new WebSocket(SERVER_URL);
20
- let commandId = 1;
21
-
22
- ws.on('open', () => {
23
- console.log(`[${clientId}] Connected!`);
24
-
25
- ws.send(JSON.stringify({
26
- type: 'identify',
27
- clientId: clientId
28
- }));
29
-
30
- ws.send(JSON.stringify({
31
- id: commandId++,
32
- method: 'Target.setDiscoverTargets',
33
- params: { discover: true }
34
- }));
35
- });
36
-
37
- ws.on('message', (data) => {
38
- try {
39
- const msg = JSON.parse(data.toString());
40
-
41
- if (msg.method === 'Target.targetCreated') {
42
- console.log(`[${clientId}] Target created: ${msg.params.targetInfo?.url || msg.params.targetInfo?.type}`);
43
- } else if (msg.method === 'Target.attachedToTarget') {
44
- console.log(`[${clientId}] Attached to target: sessionId=${msg.params.sessionId?.substring(0, 8)}...`);
45
- } else if (msg.method === 'Target.targetDestroyed') {
46
- console.log(`[${clientId}] Target destroyed`);
47
- } else if (msg.id) {
48
- if (msg.result?.targetInfos) {
49
- console.log(`[${clientId}] Got ${msg.result.targetInfos.length} targets`);
50
- }
51
- }
52
- } catch (e) {}
53
- });
54
-
55
- ws.on('close', () => {
56
- console.log(`[${clientId}] Disconnected`);
57
- });
58
-
59
- ws.on('error', (err) => {
60
- console.error(`[${clientId}] Error:`, err.message);
61
- });
62
-
63
- return {
64
- ws,
65
- clientId,
66
- send: (method, params) => {
67
- ws.send(JSON.stringify({ id: commandId++, method, params }));
68
- },
69
- close: () => ws.close()
70
- };
71
- }
72
-
73
- function interactiveTest() {
74
- const readline = require('readline');
75
- const rl = readline.createInterface({
76
- input: process.stdin,
77
- output: process.stdout
78
- });
79
-
80
- console.log('\n=== Interactive Test Commands ===');
81
- console.log(' n <client_idx> <url> - Client #n creates new page');
82
- console.log(' c <client_idx> - Client #n closes current page');
83
- console.log(' s <client_idx> - Client #n scrolls page');
84
- console.log(' l - List all clients');
85
- console.log(' q - Quit');
86
- console.log('================================\n');
87
-
88
- rl.on('line', (input) => {
89
- const parts = input.trim().split(' ');
90
- const cmd = parts[0];
91
-
92
- if (cmd === 'q') {
93
- console.log('Closing all clients...');
94
- clients.forEach(c => c.close());
95
- setTimeout(() => process.exit(0), 500);
96
- } else if (cmd === 'l') {
97
- console.log(`Active clients: ${clients.length}`);
98
- clients.forEach((c, i) => {
99
- console.log(` #${i + 1}: ${c.clientId} - ${c.ws.readyState === WebSocket.OPEN ? 'connected' : 'disconnected'}`);
100
- });
101
- } else if (cmd === 'n' && parts.length >= 3) {
102
- const idx = parseInt(parts[1]) - 1;
103
- const url = parts[2] || 'https://www.baidu.com';
104
- if (clients[idx]) {
105
- console.log(`Client #${idx + 1} creating page: ${url}`);
106
- clients[idx].send('Target.createTarget', { url });
107
- }
108
- } else if (cmd === 's' && parts.length >= 2) {
109
- const idx = parseInt(parts[1]) - 1;
110
- if (clients[idx]) {
111
- console.log(`Client #${idx + 1} scrolling...`);
112
- clients[idx].send('Runtime.evaluate', {
113
- expression: 'window.scrollBy(0, 100)'
114
- });
115
- }
116
- }
117
- });
118
- }
119
-
120
- setTimeout(interactiveTest, 1000);
121
-
122
- process.on('SIGINT', () => {
123
- console.log('\nClosing all clients...');
124
- clients.forEach(c => c.close());
125
- process.exit(0);
126
- });
127
-
128
- console.log('Usage: node test-multi-client.js [server_url] [num_clients]');
129
- console.log('Example: node test-multi-client.js ws://localhost:9221 2\n');