chrome-devtools-mcp-for-extension 0.9.7 → 0.9.8
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.
|
@@ -49,76 +49,86 @@ export async function waitForExtensionChildTarget(cdp, pattern, timeoutMs = 8000
|
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
51
|
export async function inspectIframe(cdp, urlPattern, waitMs = 8000) {
|
|
52
|
-
//
|
|
52
|
+
// Strategy: Use DOMSnapshot.captureSnapshot to get iframe-inclusive DOM structure
|
|
53
|
+
// Note: chrome-extension:// iframes may not be included due to SOP/extension isolation
|
|
54
|
+
await cdp.send('DOMSnapshot.enable');
|
|
53
55
|
try {
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// Evaluate outerHTML in child session
|
|
60
|
-
const htmlResult = await sendToChildSession(cdp, child.sessionId, 'Runtime.evaluate', {
|
|
61
|
-
expression: 'document.documentElement.outerHTML',
|
|
62
|
-
returnByValue: true,
|
|
56
|
+
// Capture full DOM snapshot including iframes
|
|
57
|
+
const snapshot = await cdp.send('DOMSnapshot.captureSnapshot', {
|
|
58
|
+
computedStyles: [],
|
|
59
|
+
includeDOMRects: false,
|
|
60
|
+
includePaintOrder: false,
|
|
63
61
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
// Search for matching iframe in the snapshot
|
|
63
|
+
const result = findIframeInSnapshot(snapshot, urlPattern);
|
|
64
|
+
if (result) {
|
|
65
|
+
return {
|
|
66
|
+
frameId: null,
|
|
67
|
+
frameUrl: result.url,
|
|
68
|
+
html: result.html,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// Extension iframe not found in snapshot - this is expected behavior
|
|
72
|
+
// due to Same-Origin Policy and Chrome extension isolation
|
|
73
|
+
throw new Error('EXTENSION_FRAME_UNREADABLE: Chrome extension iframes are isolated by ' +
|
|
74
|
+
'Same-Origin Policy and extension security model. The iframe exists but ' +
|
|
75
|
+
'cannot be read from the page context. This is expected Chrome behavior.');
|
|
70
76
|
}
|
|
71
|
-
catch (
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
(function() {
|
|
76
|
-
const pattern = ${urlPattern};
|
|
77
|
-
const iframes = Array.from(document.querySelectorAll('iframe'));
|
|
78
|
-
|
|
79
|
-
for (const iframe of iframes) {
|
|
80
|
-
if (pattern.test(iframe.src)) {
|
|
81
|
-
try {
|
|
82
|
-
// Try to access contentDocument/contentWindow
|
|
83
|
-
const doc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
84
|
-
if (doc) {
|
|
85
|
-
return {
|
|
86
|
-
success: true,
|
|
87
|
-
src: iframe.src,
|
|
88
|
-
html: doc.documentElement.outerHTML
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
} catch (securityError) {
|
|
92
|
-
// If blocked by same-origin policy, return error details
|
|
93
|
-
return {
|
|
94
|
-
success: false,
|
|
95
|
-
src: iframe.src,
|
|
96
|
-
error: 'SecurityError: ' + securityError.message
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
// If DOMSnapshot fails or iframe not found, provide clear explanation
|
|
79
|
+
if (error.message?.includes('EXTENSION_FRAME_UNREADABLE')) {
|
|
80
|
+
throw error;
|
|
100
81
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
82
|
+
throw new Error(`Failed to capture DOM snapshot: ${error.message}. ` +
|
|
83
|
+
'Note: Chrome extension iframes are typically unreadable due to security policies.');
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
await cdp.send('DOMSnapshot.disable');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function findIframeInSnapshot(snapshot, urlPattern) {
|
|
90
|
+
// DOMSnapshot structure:
|
|
91
|
+
// - documents: array of document snapshots
|
|
92
|
+
// - strings: string table for deduplication
|
|
93
|
+
const documents = snapshot.documents || [];
|
|
94
|
+
for (const doc of documents) {
|
|
95
|
+
const baseURL = doc.baseURL;
|
|
96
|
+
// Check if this document matches the pattern
|
|
97
|
+
if (baseURL && urlPattern.test(baseURL)) {
|
|
98
|
+
// Reconstruct HTML from snapshot
|
|
99
|
+
const html = reconstructHTMLFromSnapshot(doc, snapshot.strings || []);
|
|
100
|
+
return { url: baseURL, html };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
function reconstructHTMLFromSnapshot(doc, strings) {
|
|
106
|
+
// Simple reconstruction - get text content from nodes
|
|
107
|
+
// Note: DOMSnapshot doesn't provide perfect HTML reconstruction
|
|
108
|
+
// but gives us the essential content
|
|
109
|
+
const nodes = doc.nodes || {};
|
|
110
|
+
const nodeNames = nodes.nodeName || [];
|
|
111
|
+
const nodeValues = nodes.nodeValue || [];
|
|
112
|
+
const textValues = nodes.textValue || {};
|
|
113
|
+
// Build a simple HTML representation
|
|
114
|
+
let html = '<html>';
|
|
115
|
+
// Try to find body content
|
|
116
|
+
for (let i = 0; i < nodeNames.length; i++) {
|
|
117
|
+
const nameIdx = nodeNames[i];
|
|
118
|
+
const name = strings[nameIdx] || '';
|
|
119
|
+
const valueIdx = nodeValues[i];
|
|
120
|
+
const value = valueIdx >= 0 ? strings[valueIdx] : '';
|
|
121
|
+
if (name === '#document' || name === 'HTML')
|
|
122
|
+
continue;
|
|
123
|
+
if (name === '#text' && value) {
|
|
124
|
+
html += value;
|
|
125
|
+
}
|
|
126
|
+
else if (name) {
|
|
127
|
+
html += `<${name}>`;
|
|
115
128
|
}
|
|
116
|
-
return {
|
|
117
|
-
frameId: null,
|
|
118
|
-
frameUrl: data.src || '',
|
|
119
|
-
html: data.html || '',
|
|
120
|
-
};
|
|
121
129
|
}
|
|
130
|
+
html += '</html>';
|
|
131
|
+
return html;
|
|
122
132
|
}
|
|
123
133
|
async function sendToChildSession(cdp, sessionId, method, params) {
|
|
124
134
|
const id = Math.floor(Math.random() * 1000000);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrome-devtools-mcp-for-extension",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.8",
|
|
4
4
|
"description": "MCP server for Chrome extension development with Web Store automation. Fork of chrome-devtools-mcp with extension-specific tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": "./build/src/index.js",
|