All the things

This commit is contained in:
2025-01-25 22:42:04 -06:00
parent d556823350
commit 0db1065d10
16 changed files with 678 additions and 55 deletions

47
extension/background.js Normal file
View File

@@ -0,0 +1,47 @@
console.log("Background script loaded");
async function isContentScriptReady(tabId) {
try {
await browser.tabs.sendMessage(tabId, { type: "PING" });
return true;
} catch (error) {
return false;
}
}
async function waitForContentScript(tabId, maxAttempts = 10) {
console.log(`Waiting for content script in tab ${tabId}`);
for (let i = 0; i < maxAttempts; i++) {
if (await isContentScriptReady(tabId)) {
console.log(`Content script ready in tab ${tabId}`);
return true;
}
console.log(`Attempt ${i + 1}: Content script not ready, waiting...`);
await new Promise(resolve => setTimeout(resolve, 500));
}
console.log(`Content script not ready after ${maxAttempts} attempts`);
return false;
}
async function sendMessageToTab(tabId) {
try {
console.log(`Checking content script status for tab ${tabId}`);
if (await waitForContentScript(tabId)) {
console.log(`Sending GET_PAGE_CONTENT message to tab ${tabId}`);
await browser.tabs.sendMessage(tabId, {
type: "GET_PAGE_CONTENT"
});
console.log(`Successfully sent message to tab ${tabId}`);
}
} catch (error) {
console.error(`Error sending message to tab ${tabId}:`, error);
}
}
browser.webNavigation.onCompleted.addListener(async (details) => {
console.log("Navigation completed", details);
if (details.frameId === 0) { // Only handle main frame navigation
console.log(`Main frame navigation detected for tab ${details.tabId}`);
await sendMessageToTab(details.tabId);
}
});

132
extension/content.js Normal file
View File

@@ -0,0 +1,132 @@
console.log("Content script starting initialization...");
// Function to log WebSocket state
function getWebSocketState(ws) {
const states = {
0: 'CONNECTING',
1: 'OPEN',
2: 'CLOSING',
3: 'CLOSED'
};
return states[ws.readyState] || 'UNKNOWN';
}
class WebSocketClient {
constructor() {
console.log("WebSocketClient constructor called");
this.messageQueue = [];
this.connect();
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
}
connect() {
console.log('Attempting to connect to WebSocket server...');
try {
this.ws = new WebSocket('ws://localhost:8523/ws');
console.log('WebSocket instance created');
this.ws.addEventListener('open', () => {
console.log('WebSocket connection opened successfully');
this.reconnectAttempts = 0;
// Process any queued messages
this.processQueue();
});
this.ws.addEventListener('error', (event) => {
console.error('WebSocket error occurred:', event);
});
this.ws.addEventListener('close', (event) => {
console.log('WebSocket connection closed:', event.code, event.reason);
this.tryReconnect();
});
this.ws.addEventListener('message', (event) => {
console.log('Received message from server:', event.data);
});
} catch (error) {
console.error('Error creating WebSocket:', error);
}
}
processQueue() {
console.log(`Processing message queue (${this.messageQueue.length} messages)`);
while (this.messageQueue.length > 0) {
const data = this.messageQueue.shift();
this.sendMessage(data);
}
}
tryReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
setTimeout(() => this.connect(), 2000 * this.reconnectAttempts);
} else {
console.log('Max reconnection attempts reached');
}
}
sendMessage(data) {
console.log('sendMessage called, WebSocket state:', getWebSocketState(this.ws));
if (this.ws.readyState === WebSocket.OPEN) {
try {
console.log('Preparing to send data:', {
url: data.url,
timestamp: data.timestamp,
htmlLength: data.html.length
});
this.ws.send(JSON.stringify(data));
console.log('Data sent successfully');
return true;
} catch (error) {
console.error('Error sending data:', error);
return false;
}
} else {
console.log('WebSocket not ready, queueing message');
this.messageQueue.push(data);
return true;
}
}
}
console.log("Creating WebSocketClient instance...");
const wsClient = new WebSocketClient();
console.log("Setting up message listener...");
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log('Message received from background script:', message);
if (message.type === "PING") {
console.log('Received PING, responding...');
return Promise.resolve({ status: "ready" });
}
if (message.type === "GET_PAGE_CONTENT") {
console.log('Processing GET_PAGE_CONTENT message');
const pageContent = {
url: window.location.href,
html: document.documentElement.outerHTML,
timestamp: new Date().toISOString().replace(/\.\d{3}Z$/, 'Z')
};
console.log('Created page content object for:', pageContent.url);
wsClient.sendMessage(pageContent);
}
return true;
});
// Send initial page content
console.log('Sending initial page content...');
const pageContent = {
url: window.location.href,
html: document.documentElement.outerHTML,
timestamp: new Date().toISOString().replace(/\.\d{3}Z$/, 'Z')
};
wsClient.sendMessage(pageContent);
console.log("Content script initialization complete for:", window.location.href);

35
extension/manifest.json Normal file
View File

@@ -0,0 +1,35 @@
{
"manifest_version": 2,
"name": "Page Content Sender",
"version": "1.0",
"description": "Sends page content via WebSocket when a page loads",
"permissions": [
"webNavigation",
"activeTab",
"<all_urls>",
"tabs"
],
"background": {
"scripts": [
"background.js"
],
"persistent": true
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"content.js"
],
"run_at": "document_idle",
"all_frames": false
}
],
"browser_specific_settings": {
"gecko": {
"id": "page-content-sender@example.com"
}
}
}