2025-02-10 04:21:21 -05:00
|
|
|
// Store settings
|
|
|
|
let settings = {
|
|
|
|
logLimit: 50,
|
|
|
|
queryLimit: 30000,
|
|
|
|
stringSizeLimit: 500,
|
|
|
|
showRequestHeaders: false,
|
|
|
|
showResponseHeaders: false,
|
|
|
|
maxLogSize: 20000,
|
2025-02-11 00:56:07 -05:00
|
|
|
screenshotPath: "",
|
2025-03-01 21:08:24 -05:00
|
|
|
// Add server connection settings
|
|
|
|
serverHost: "localhost",
|
|
|
|
serverPort: 3025,
|
2025-02-10 04:21:21 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
// Load saved settings on startup
|
|
|
|
chrome.storage.local.get(["browserConnectorSettings"], (result) => {
|
|
|
|
if (result.browserConnectorSettings) {
|
|
|
|
settings = { ...settings, ...result.browserConnectorSettings };
|
|
|
|
updateUIFromSettings();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Initialize UI elements
|
|
|
|
const logLimitInput = document.getElementById("log-limit");
|
|
|
|
const queryLimitInput = document.getElementById("query-limit");
|
|
|
|
const stringSizeLimitInput = document.getElementById("string-size-limit");
|
|
|
|
const showRequestHeadersCheckbox = document.getElementById(
|
|
|
|
"show-request-headers"
|
|
|
|
);
|
|
|
|
const showResponseHeadersCheckbox = document.getElementById(
|
|
|
|
"show-response-headers"
|
|
|
|
);
|
|
|
|
const maxLogSizeInput = document.getElementById("max-log-size");
|
2025-02-11 00:56:07 -05:00
|
|
|
const screenshotPathInput = document.getElementById("screenshot-path");
|
2025-02-14 04:18:43 -05:00
|
|
|
const captureScreenshotButton = document.getElementById("capture-screenshot");
|
|
|
|
|
2025-03-01 21:08:24 -05:00
|
|
|
// Server connection UI elements
|
|
|
|
const serverHostInput = document.getElementById("server-host");
|
|
|
|
const serverPortInput = document.getElementById("server-port");
|
|
|
|
const discoverServerButton = document.getElementById("discover-server");
|
|
|
|
const testConnectionButton = document.getElementById("test-connection");
|
|
|
|
const connectionStatusDiv = document.getElementById("connection-status");
|
|
|
|
const statusIcon = document.getElementById("status-icon");
|
|
|
|
const statusText = document.getElementById("status-text");
|
|
|
|
|
2025-02-14 04:18:43 -05:00
|
|
|
// Initialize collapsible advanced settings
|
|
|
|
const advancedSettingsHeader = document.getElementById(
|
|
|
|
"advanced-settings-header"
|
|
|
|
);
|
|
|
|
const advancedSettingsContent = document.getElementById(
|
|
|
|
"advanced-settings-content"
|
|
|
|
);
|
|
|
|
const chevronIcon = advancedSettingsHeader.querySelector(".chevron");
|
|
|
|
|
|
|
|
advancedSettingsHeader.addEventListener("click", () => {
|
|
|
|
advancedSettingsContent.classList.toggle("visible");
|
|
|
|
chevronIcon.classList.toggle("open");
|
|
|
|
});
|
2025-02-10 04:21:21 -05:00
|
|
|
|
|
|
|
// Update UI from settings
|
|
|
|
function updateUIFromSettings() {
|
|
|
|
logLimitInput.value = settings.logLimit;
|
|
|
|
queryLimitInput.value = settings.queryLimit;
|
|
|
|
stringSizeLimitInput.value = settings.stringSizeLimit;
|
|
|
|
showRequestHeadersCheckbox.checked = settings.showRequestHeaders;
|
|
|
|
showResponseHeadersCheckbox.checked = settings.showResponseHeaders;
|
|
|
|
maxLogSizeInput.value = settings.maxLogSize;
|
2025-02-11 00:56:07 -05:00
|
|
|
screenshotPathInput.value = settings.screenshotPath;
|
2025-03-01 21:08:24 -05:00
|
|
|
serverHostInput.value = settings.serverHost;
|
|
|
|
serverPortInput.value = settings.serverPort;
|
2025-02-10 04:21:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Save settings
|
|
|
|
function saveSettings() {
|
|
|
|
chrome.storage.local.set({ browserConnectorSettings: settings });
|
|
|
|
// Notify devtools.js about settings change
|
|
|
|
chrome.runtime.sendMessage({
|
|
|
|
type: "SETTINGS_UPDATED",
|
|
|
|
settings,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add event listeners for all inputs
|
|
|
|
logLimitInput.addEventListener("change", (e) => {
|
|
|
|
settings.logLimit = parseInt(e.target.value, 10);
|
|
|
|
saveSettings();
|
|
|
|
});
|
|
|
|
|
|
|
|
queryLimitInput.addEventListener("change", (e) => {
|
|
|
|
settings.queryLimit = parseInt(e.target.value, 10);
|
|
|
|
saveSettings();
|
|
|
|
});
|
|
|
|
|
|
|
|
stringSizeLimitInput.addEventListener("change", (e) => {
|
|
|
|
settings.stringSizeLimit = parseInt(e.target.value, 10);
|
|
|
|
saveSettings();
|
|
|
|
});
|
|
|
|
|
|
|
|
showRequestHeadersCheckbox.addEventListener("change", (e) => {
|
|
|
|
settings.showRequestHeaders = e.target.checked;
|
|
|
|
saveSettings();
|
|
|
|
});
|
|
|
|
|
|
|
|
showResponseHeadersCheckbox.addEventListener("change", (e) => {
|
|
|
|
settings.showResponseHeaders = e.target.checked;
|
|
|
|
saveSettings();
|
|
|
|
});
|
|
|
|
|
|
|
|
maxLogSizeInput.addEventListener("change", (e) => {
|
|
|
|
settings.maxLogSize = parseInt(e.target.value, 10);
|
|
|
|
saveSettings();
|
|
|
|
});
|
2025-02-11 00:56:07 -05:00
|
|
|
|
|
|
|
screenshotPathInput.addEventListener("change", (e) => {
|
|
|
|
settings.screenshotPath = e.target.value;
|
|
|
|
saveSettings();
|
|
|
|
});
|
2025-02-14 04:18:43 -05:00
|
|
|
|
2025-03-01 21:08:24 -05:00
|
|
|
// Add event listeners for server settings
|
|
|
|
serverHostInput.addEventListener("change", (e) => {
|
|
|
|
settings.serverHost = e.target.value;
|
|
|
|
saveSettings();
|
|
|
|
});
|
|
|
|
|
|
|
|
serverPortInput.addEventListener("change", (e) => {
|
|
|
|
settings.serverPort = parseInt(e.target.value, 10);
|
|
|
|
saveSettings();
|
|
|
|
});
|
|
|
|
|
|
|
|
// Test server connection
|
|
|
|
testConnectionButton.addEventListener("click", async () => {
|
|
|
|
await testConnection(settings.serverHost, settings.serverPort);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Function to test server connection
|
|
|
|
async function testConnection(host, port) {
|
|
|
|
connectionStatusDiv.style.display = "block";
|
|
|
|
statusIcon.className = "status-indicator";
|
|
|
|
statusText.textContent = "Testing connection...";
|
|
|
|
|
|
|
|
try {
|
2025-03-01 21:11:14 -05:00
|
|
|
// Use the identity endpoint instead of .port for more reliable validation
|
|
|
|
const response = await fetch(`http://${host}:${port}/.identity`, {
|
2025-03-01 21:08:24 -05:00
|
|
|
signal: AbortSignal.timeout(5000), // 5 second timeout
|
|
|
|
});
|
|
|
|
|
|
|
|
if (response.ok) {
|
2025-03-01 21:11:14 -05:00
|
|
|
const identity = await response.json();
|
|
|
|
|
|
|
|
// Verify this is actually our server by checking the signature
|
|
|
|
if (identity.signature !== "mcp-browser-connector-24x7") {
|
|
|
|
statusIcon.className = "status-indicator status-disconnected";
|
|
|
|
statusText.textContent = `Connection failed: Found a server at ${host}:${port} but it's not the Browser Tools server`;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2025-03-01 21:08:24 -05:00
|
|
|
statusIcon.className = "status-indicator status-connected";
|
2025-03-01 21:11:14 -05:00
|
|
|
statusText.textContent = `Connected successfully to ${identity.name} v${identity.version} at ${host}:${port}`;
|
2025-03-01 21:08:24 -05:00
|
|
|
|
|
|
|
// Update settings if different port was discovered
|
2025-03-01 21:11:14 -05:00
|
|
|
if (parseInt(identity.port, 10) !== port) {
|
|
|
|
console.log(`Detected different port: ${identity.port}`);
|
|
|
|
settings.serverPort = parseInt(identity.port, 10);
|
2025-03-01 21:08:24 -05:00
|
|
|
serverPortInput.value = settings.serverPort;
|
|
|
|
saveSettings();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
statusIcon.className = "status-indicator status-disconnected";
|
|
|
|
statusText.textContent = `Connection failed: Server returned ${response.status}`;
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
statusIcon.className = "status-indicator status-disconnected";
|
|
|
|
statusText.textContent = `Connection failed: ${error.message}`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Server discovery function
|
|
|
|
discoverServerButton.addEventListener("click", async () => {
|
|
|
|
connectionStatusDiv.style.display = "block";
|
|
|
|
statusIcon.className = "status-indicator";
|
|
|
|
statusText.textContent = "Discovering server...";
|
|
|
|
|
|
|
|
// Common IPs to try
|
|
|
|
const hosts = ["localhost", "127.0.0.1", "0.0.0.0"];
|
|
|
|
|
|
|
|
// Get local IP addresses on common networks
|
|
|
|
const commonLocalIps = ["192.168.0.", "192.168.1.", "10.0.0.", "10.0.1."];
|
|
|
|
|
|
|
|
// Add common local networks with last octet from 1 to 10
|
|
|
|
for (const prefix of commonLocalIps) {
|
|
|
|
for (let i = 1; i <= 10; i++) {
|
|
|
|
hosts.push(`${prefix}${i}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Common ports to try
|
|
|
|
const ports = [3025, parseInt(settings.serverPort, 10)];
|
|
|
|
|
|
|
|
// Ensure the current port is in the list
|
|
|
|
if (!ports.includes(parseInt(settings.serverPort, 10))) {
|
|
|
|
ports.push(parseInt(settings.serverPort, 10));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a progress indicator
|
|
|
|
let progress = 0;
|
|
|
|
const totalAttempts = hosts.length * ports.length;
|
|
|
|
statusText.textContent = `Discovering server... (0/${totalAttempts})`;
|
|
|
|
|
|
|
|
// Try each host:port combination
|
|
|
|
for (const host of hosts) {
|
|
|
|
for (const port of ports) {
|
|
|
|
try {
|
|
|
|
// Skip duplicates if current port is in the ports list multiple times
|
|
|
|
if (
|
|
|
|
port === parseInt(settings.serverPort, 10) &&
|
|
|
|
host === settings.serverHost
|
|
|
|
) {
|
|
|
|
progress++;
|
|
|
|
statusText.textContent = `Discovering server... (${progress}/${totalAttempts})`;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update progress
|
|
|
|
progress++;
|
|
|
|
statusText.textContent = `Discovering server... (${progress}/${totalAttempts}) - Trying ${host}:${port}`;
|
|
|
|
|
|
|
|
const controller = new AbortController();
|
|
|
|
const timeoutId = setTimeout(() => controller.abort(), 1000); // 1 second timeout per attempt
|
|
|
|
|
2025-03-01 21:11:14 -05:00
|
|
|
// Use identity endpoint instead of .port for more reliable server validation
|
|
|
|
const response = await fetch(`http://${host}:${port}/.identity`, {
|
2025-03-01 21:08:24 -05:00
|
|
|
signal: controller.signal,
|
|
|
|
});
|
|
|
|
|
|
|
|
clearTimeout(timeoutId);
|
|
|
|
|
|
|
|
if (response.ok) {
|
2025-03-01 21:11:14 -05:00
|
|
|
const identity = await response.json();
|
|
|
|
|
|
|
|
// Verify this is actually our server by checking the signature
|
|
|
|
if (identity.signature !== "mcp-browser-connector-24x7") {
|
|
|
|
console.log(
|
|
|
|
`Found a server at ${host}:${port} but it's not the Browser Tools server`
|
|
|
|
);
|
|
|
|
continue;
|
|
|
|
}
|
2025-03-01 21:08:24 -05:00
|
|
|
|
|
|
|
// Update settings with discovered server
|
|
|
|
settings.serverHost = host;
|
2025-03-01 21:11:14 -05:00
|
|
|
settings.serverPort = parseInt(identity.port, 10);
|
2025-03-01 21:08:24 -05:00
|
|
|
serverHostInput.value = settings.serverHost;
|
|
|
|
serverPortInput.value = settings.serverPort;
|
|
|
|
saveSettings();
|
|
|
|
|
|
|
|
statusIcon.className = "status-indicator status-connected";
|
2025-03-01 21:11:14 -05:00
|
|
|
statusText.textContent = `Discovered ${identity.name} v${identity.version} at ${host}:${identity.port}`;
|
2025-03-01 21:08:24 -05:00
|
|
|
|
|
|
|
// Stop searching once found
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
// Ignore connection errors during discovery
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we get here, no server was found
|
|
|
|
statusIcon.className = "status-indicator status-disconnected";
|
|
|
|
statusText.textContent =
|
|
|
|
"No server found. Please check server is running and try again.";
|
|
|
|
});
|
|
|
|
|
|
|
|
// Screenshot capture functionality
|
2025-02-14 04:18:43 -05:00
|
|
|
captureScreenshotButton.addEventListener("click", () => {
|
|
|
|
captureScreenshotButton.textContent = "Capturing...";
|
|
|
|
|
2025-02-19 09:56:59 -06:00
|
|
|
// Send message to background script to capture screenshot
|
2025-03-01 21:08:24 -05:00
|
|
|
chrome.runtime.sendMessage(
|
|
|
|
{
|
|
|
|
type: "CAPTURE_SCREENSHOT",
|
|
|
|
tabId: chrome.devtools.inspectedWindow.tabId,
|
|
|
|
screenshotPath: settings.screenshotPath,
|
|
|
|
},
|
|
|
|
(response) => {
|
|
|
|
console.log("Screenshot capture response:", response);
|
|
|
|
if (!response) {
|
|
|
|
captureScreenshotButton.textContent = "Failed to capture!";
|
|
|
|
console.error("Screenshot capture failed: No response received");
|
|
|
|
} else if (!response.success) {
|
|
|
|
captureScreenshotButton.textContent = "Failed to capture!";
|
|
|
|
console.error("Screenshot capture failed:", response.error);
|
|
|
|
} else {
|
|
|
|
captureScreenshotButton.textContent = `Captured: ${response.title}`;
|
|
|
|
console.log("Screenshot captured successfully:", response.path);
|
|
|
|
}
|
|
|
|
setTimeout(() => {
|
|
|
|
captureScreenshotButton.textContent = "Capture Screenshot";
|
|
|
|
}, 2000);
|
2025-02-14 04:18:43 -05:00
|
|
|
}
|
2025-03-01 21:08:24 -05:00
|
|
|
);
|
2025-02-14 04:18:43 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
// Add wipe logs functionality
|
|
|
|
const wipeLogsButton = document.getElementById("wipe-logs");
|
|
|
|
wipeLogsButton.addEventListener("click", () => {
|
2025-03-01 21:08:24 -05:00
|
|
|
const serverUrl = `http://${settings.serverHost}:${settings.serverPort}/wipelogs`;
|
|
|
|
console.log(`Sending wipe request to ${serverUrl}`);
|
|
|
|
|
|
|
|
fetch(serverUrl, {
|
2025-02-14 04:18:43 -05:00
|
|
|
method: "POST",
|
|
|
|
headers: { "Content-Type": "application/json" },
|
|
|
|
})
|
|
|
|
.then((response) => response.json())
|
|
|
|
.then((result) => {
|
|
|
|
console.log("Logs wiped successfully:", result.message);
|
|
|
|
wipeLogsButton.textContent = "Logs Wiped!";
|
|
|
|
setTimeout(() => {
|
|
|
|
wipeLogsButton.textContent = "Wipe All Logs";
|
|
|
|
}, 2000);
|
|
|
|
})
|
|
|
|
.catch((error) => {
|
|
|
|
console.error("Failed to wipe logs:", error);
|
|
|
|
wipeLogsButton.textContent = "Failed to Wipe Logs";
|
|
|
|
setTimeout(() => {
|
|
|
|
wipeLogsButton.textContent = "Wipe All Logs";
|
|
|
|
}, 2000);
|
|
|
|
});
|
|
|
|
});
|