sal-modular/hero_vault_extension/src/background/index.ts

146 lines
4.2 KiB
TypeScript

/**
* Background Service Worker for Hero Vault Extension
*
* Responsibilities:
* - Maintain WebSocket connections
* - Handle incoming script requests
* - Manage session state when popup is closed
* - Provide messaging interface for popup/content scripts
* - Initialize WASM module when extension starts
*/
// Import WASM helper functions
import { initWasm } from '../wasm/wasmHelper';
// Initialize WASM module when service worker starts
initWasm().catch(error => {
console.error('Failed to initialize WASM module:', error);
});
// Store active WebSocket connection
let activeWebSocket: WebSocket | null = null;
let sessionActive = false;
// Listen for messages from popup or content scripts
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
if (message.type === 'SESSION_STATUS') {
sendResponse({ active: sessionActive });
return true;
}
if (message.type === 'SESSION_UNLOCK') {
sessionActive = true;
sendResponse({ success: true });
return true;
}
if (message.type === 'SESSION_LOCK') {
sessionActive = false;
if (activeWebSocket) {
activeWebSocket.close();
activeWebSocket = null;
}
sendResponse({ success: true });
return true;
}
if (message.type === 'CONNECT_WEBSOCKET' && message.serverUrl && message.publicKey) {
connectToWebSocket(message.serverUrl, message.publicKey)
.then(success => sendResponse({ success }))
.catch(error => sendResponse({ success: false, error: error.message }));
return true; // Indicates we'll respond asynchronously
}
if (message.type === 'DISCONNECT_WEBSOCKET') {
if (activeWebSocket) {
activeWebSocket.close();
activeWebSocket = null;
sendResponse({ success: true });
} else {
sendResponse({ success: false, error: 'No active WebSocket connection' });
}
return true;
}
});
/**
* Connect to a WebSocket server with the user's public key
*/
async function connectToWebSocket(serverUrl: string, publicKey: string): Promise<boolean> {
if (activeWebSocket) {
activeWebSocket.close();
}
return new Promise((resolve, reject) => {
try {
const ws = new WebSocket(serverUrl);
ws.onopen = () => {
// Send authentication message with public key
ws.send(JSON.stringify({
type: 'AUTH',
publicKey
}));
activeWebSocket = ws;
resolve(true);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
reject(new Error('Failed to connect to WebSocket server'));
};
ws.onclose = () => {
activeWebSocket = null;
console.log('WebSocket connection closed');
};
ws.onmessage = async (event) => {
try {
const data = JSON.parse(event.data);
// Handle incoming script requests
if (data.type === 'SCRIPT_REQUEST') {
// Notify the user of the script request
chrome.notifications.create({
type: 'basic',
iconUrl: 'icons/icon128.png',
title: 'Script Request',
message: `Received script request: ${data.title || 'Untitled Script'}`,
priority: 2
});
// Store the script request for the popup to handle
await chrome.storage.local.set({
pendingScripts: [
...(await chrome.storage.local.get('pendingScripts')).pendingScripts || [],
{
id: data.id,
title: data.title || 'Untitled Script',
description: data.description || '',
script: data.script,
tags: data.tags || [],
timestamp: Date.now()
}
]
});
}
} catch (error) {
console.error('Error processing WebSocket message:', error);
}
};
} catch (error) {
reject(error);
}
});
}
// Initialize notification setup
chrome.notifications.onClicked.addListener((_notificationId) => {
// Open the extension popup when a notification is clicked
chrome.action.openPopup();
});
console.log('Hero Vault Extension background service worker initialized');