Skip to content

Commit 2f87e51

Browse files
committed
Apply PR #85: Fix screenshots when separate dev tools windows opened
- Add DELEGATE_SCREENSHOT message handler in background.js - Enhance window focusing and tab activation logic - Add DevTools tab detection and filtering - Improve error handling and logging in devtools.js - Add fallback delegation to background script for screenshot capture - Maintain backward compatibility for normal scenarios
1 parent de29c70 commit 2f87e51

File tree

2 files changed

+170
-71
lines changed

2 files changed

+170
-71
lines changed

chrome-extension/background.js

Lines changed: 110 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,42 @@ async function retestConnectionOnRefresh(tabId) {
339339
});
340340
}
341341

342+
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
343+
if (message.type === "DELEGATE_SCREENSHOT" && message.tabId) {
344+
// Get the tab we want to capture
345+
chrome.tabs.get(message.tabId, (tab) => {
346+
if (chrome.runtime.lastError) {
347+
sendResponse({ success: false, error: chrome.runtime.lastError.message });
348+
return;
349+
}
350+
351+
// Get the window containing this tab
352+
chrome.windows.get(tab.windowId, { populate: true }, (window) => {
353+
// Make sure the tab is active in its window
354+
chrome.tabs.update(message.tabId, { active: true }, () => {
355+
// Focus the window
356+
chrome.windows.update(tab.windowId, { focused: true }, () => {
357+
// Wait a moment for the window to focus
358+
setTimeout(() => {
359+
// Capture the visible tab in that window
360+
chrome.tabs.captureVisibleTab(tab.windowId, { format: "png" }, (dataUrl) => {
361+
if (chrome.runtime.lastError) {
362+
sendResponse({ success: false, error: chrome.runtime.lastError.message });
363+
return;
364+
}
365+
366+
sendResponse({ success: true, dataUrl: dataUrl });
367+
});
368+
}, 100);
369+
});
370+
});
371+
});
372+
});
373+
374+
return true; // Keep the message channel open for the async response
375+
}
376+
});
377+
342378
// Function to capture and send screenshot
343379
function captureAndSendScreenshot(message, settings, sendResponse) {
344380
// Get the inspected window's tab
@@ -352,6 +388,16 @@ function captureAndSendScreenshot(message, settings, sendResponse) {
352388
return;
353389
}
354390

391+
// Skip DevTools tabs
392+
if (tab.url && tab.url.startsWith('devtools://')) {
393+
console.error("Cannot capture DevTools tab:", tab.url);
394+
sendResponse({
395+
success: false,
396+
error: "Cannot capture DevTools tabs. Please capture the actual application tab.",
397+
});
398+
return;
399+
}
400+
355401
// Get all windows to find the one containing our tab
356402
chrome.windows.getAll({ populate: true }, (windows) => {
357403
const targetWindow = windows.find((w) =>
@@ -367,65 +413,71 @@ function captureAndSendScreenshot(message, settings, sendResponse) {
367413
return;
368414
}
369415

370-
// Capture screenshot of the window containing our tab
371-
chrome.tabs.captureVisibleTab(
372-
targetWindow.id,
373-
{ format: "png" },
374-
(dataUrl) => {
375-
// Ignore DevTools panel capture error if it occurs
376-
if (
377-
chrome.runtime.lastError &&
378-
!chrome.runtime.lastError.message.includes("devtools://")
379-
) {
380-
console.error(
381-
"Error capturing screenshot:",
382-
chrome.runtime.lastError
383-
);
384-
sendResponse({
385-
success: false,
386-
error: chrome.runtime.lastError.message,
387-
});
388-
return;
389-
}
390-
391-
// Send screenshot data to browser connector using configured settings
392-
const serverUrl = `http://${settings.serverHost}:${settings.serverPort}/screenshot`;
393-
console.log(`Sending screenshot to ${serverUrl}`);
394-
395-
fetch(serverUrl, {
396-
method: "POST",
397-
headers: {
398-
"Content-Type": "application/json",
399-
},
400-
body: JSON.stringify({
401-
data: dataUrl,
402-
path: message.screenshotPath,
403-
}),
404-
})
405-
.then((response) => response.json())
406-
.then((result) => {
407-
if (result.error) {
408-
console.error("Error from server:", result.error);
409-
sendResponse({ success: false, error: result.error });
410-
} else {
411-
console.log("Screenshot saved successfully:", result.path);
412-
// Send success response even if DevTools capture failed
413-
sendResponse({
414-
success: true,
415-
path: result.path,
416-
title: tab.title || "Current Tab",
417-
});
416+
console.log(`Capturing screenshot of window ${targetWindow.id} containing tab ${message.tabId}`);
417+
418+
// First focus the window and activate the tab
419+
chrome.windows.update(targetWindow.id, { focused: true }, () => {
420+
chrome.tabs.update(message.tabId, { active: true }, () => {
421+
// Small delay to ensure the window and tab are focused
422+
setTimeout(() => {
423+
// Capture screenshot of the window containing our tab
424+
chrome.tabs.captureVisibleTab(
425+
targetWindow.id,
426+
{ format: "png" },
427+
(dataUrl) => {
428+
if (chrome.runtime.lastError) {
429+
console.error(
430+
"Error capturing screenshot:",
431+
chrome.runtime.lastError
432+
);
433+
sendResponse({
434+
success: false,
435+
error: chrome.runtime.lastError.message,
436+
});
437+
return;
438+
}
439+
440+
// Send screenshot data to browser connector using configured settings
441+
const serverUrl = `http://${settings.serverHost}:${settings.serverPort}/screenshot`;
442+
console.log(`Sending screenshot to ${serverUrl}`);
443+
444+
fetch(serverUrl, {
445+
method: "POST",
446+
headers: {
447+
"Content-Type": "application/json",
448+
},
449+
body: JSON.stringify({
450+
data: dataUrl,
451+
path: message.screenshotPath,
452+
}),
453+
})
454+
.then((response) => response.json())
455+
.then((result) => {
456+
if (result.error) {
457+
console.error("Error from server:", result.error);
458+
sendResponse({ success: false, error: result.error });
459+
} else {
460+
console.log("Screenshot saved successfully:", result.path);
461+
// Send success response
462+
sendResponse({
463+
success: true,
464+
path: result.path,
465+
title: tab.title || "Current Tab",
466+
});
467+
}
468+
})
469+
.catch((error) => {
470+
console.error("Error sending screenshot data:", error);
471+
sendResponse({
472+
success: false,
473+
error: error.message || "Failed to save screenshot",
474+
});
475+
});
418476
}
419-
})
420-
.catch((error) => {
421-
console.error("Error sending screenshot data:", error);
422-
sendResponse({
423-
success: false,
424-
error: error.message || "Failed to save screenshot",
425-
});
426-
});
427-
}
428-
);
477+
);
478+
}, 100); // 100ms delay
479+
});
480+
});
429481
});
430482
});
431483
}

chrome-extension/devtools.js

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ function captureAndSendElement() {
893893
top: rect.top,
894894
left: rect.left
895895
},
896-
innerHTML: el.innerHTML.substring(0, 500)
896+
innerHTML: el.innerHTML.substring(0, ${settings.stringSizeLimit})
897897
};
898898
})()`,
899899
(result, isException) => {
@@ -1149,24 +1149,71 @@ async function setupWebSocket() {
11491149
// console.log("Chrome Extension: Received heartbeat response");
11501150
} else if (message.type === "take-screenshot") {
11511151
console.log("Chrome Extension: Taking screenshot...");
1152-
// Capture screenshot of the current tab
1152+
1153+
// Try to capture screenshot directly first
11531154
chrome.tabs.captureVisibleTab(null, { format: "png" }, (dataUrl) => {
11541155
if (chrome.runtime.lastError) {
1155-
console.error(
1156-
"Chrome Extension: Screenshot capture failed:",
1157-
chrome.runtime.lastError
1156+
console.log(
1157+
"Chrome Extension: Direct screenshot capture failed, delegating to background:",
1158+
chrome.runtime.lastError.message
11581159
);
1159-
ws.send(
1160-
JSON.stringify({
1161-
type: "screenshot-error",
1162-
error: chrome.runtime.lastError.message,
1163-
requestId: message.requestId,
1164-
})
1160+
1161+
// If direct capture fails (e.g., DevTools in separate window), delegate to background
1162+
chrome.runtime.sendMessage(
1163+
{
1164+
type: "DELEGATE_SCREENSHOT",
1165+
tabId: chrome.devtools.inspectedWindow.tabId,
1166+
},
1167+
(response) => {
1168+
if (chrome.runtime.lastError) {
1169+
console.error(
1170+
"Chrome Extension: Background screenshot delegation failed:",
1171+
chrome.runtime.lastError
1172+
);
1173+
ws.send(
1174+
JSON.stringify({
1175+
type: "screenshot-error",
1176+
error: chrome.runtime.lastError.message,
1177+
requestId: message.requestId,
1178+
})
1179+
);
1180+
return;
1181+
}
1182+
1183+
if (response && response.success && response.dataUrl) {
1184+
console.log("Chrome Extension: Background screenshot captured successfully");
1185+
const screenshotResponse = {
1186+
type: "screenshot-data",
1187+
data: response.dataUrl,
1188+
requestId: message.requestId,
1189+
// Only include path if it's configured in settings
1190+
...(settings.screenshotPath && { path: settings.screenshotPath }),
1191+
// Include auto-paste setting
1192+
autoPaste: settings.allowAutoPaste,
1193+
};
1194+
1195+
console.log("Chrome Extension: Sending background screenshot data response", {
1196+
...screenshotResponse,
1197+
data: "[base64 data]",
1198+
});
1199+
1200+
ws.send(JSON.stringify(screenshotResponse));
1201+
} else {
1202+
console.error("Chrome Extension: Background screenshot failed:", response?.error);
1203+
ws.send(
1204+
JSON.stringify({
1205+
type: "screenshot-error",
1206+
error: response?.error || "Background screenshot capture failed",
1207+
requestId: message.requestId,
1208+
})
1209+
);
1210+
}
1211+
}
11651212
);
11661213
return;
11671214
}
11681215

1169-
console.log("Chrome Extension: Screenshot captured successfully");
1216+
console.log("Chrome Extension: Direct screenshot captured successfully");
11701217
// Just send the screenshot data, let the server handle paths
11711218
const response = {
11721219
type: "screenshot-data",
@@ -1178,7 +1225,7 @@ async function setupWebSocket() {
11781225
autoPaste: settings.allowAutoPaste,
11791226
};
11801227

1181-
console.log("Chrome Extension: Sending screenshot data response", {
1228+
console.log("Chrome Extension: Sending direct screenshot data response", {
11821229
...response,
11831230
data: "[base64 data]",
11841231
});

0 commit comments

Comments
 (0)