feat: implement browser extension UI with WebAssembly integration
This commit is contained in:
102
extension/public/background/index.js
Normal file
102
extension/public/background/index.js
Normal file
@@ -0,0 +1,102 @@
|
||||
// Background service worker for Modular Vault Extension
|
||||
// Handles session, keypair, and WASM logic
|
||||
|
||||
// We need to use dynamic imports for service workers in MV3
|
||||
let wasmModule;
|
||||
let init;
|
||||
let wasm;
|
||||
let wasmReady = false;
|
||||
|
||||
// Initialize WASM on startup with dynamic import
|
||||
async function loadWasm() {
|
||||
try {
|
||||
// Using importScripts for service worker
|
||||
const wasmUrl = chrome.runtime.getURL('wasm/wasm_app.js');
|
||||
wasmModule = await import(wasmUrl);
|
||||
init = wasmModule.default;
|
||||
wasm = wasmModule;
|
||||
|
||||
// Initialize WASM with explicit WASM file path
|
||||
await init(chrome.runtime.getURL('wasm/wasm_app_bg.wasm'));
|
||||
wasmReady = true;
|
||||
console.log('WASM initialized in background');
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize WASM:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Start loading WASM
|
||||
loadWasm();
|
||||
|
||||
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
|
||||
if (!wasmReady) {
|
||||
sendResponse({ error: 'WASM not ready' });
|
||||
return true;
|
||||
}
|
||||
// Session unlock/create
|
||||
if (request.action === 'init_session') {
|
||||
try {
|
||||
const result = await wasm.init_session(request.keyspace, request.password);
|
||||
// Persist current session info
|
||||
await chrome.storage.local.set({ currentKeyspace: request.keyspace });
|
||||
sendResponse({ ok: true });
|
||||
} catch (e) {
|
||||
sendResponse({ error: e.message });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Lock session
|
||||
if (request.action === 'lock_session') {
|
||||
try {
|
||||
wasm.lock_session();
|
||||
await chrome.storage.local.set({ currentKeyspace: null });
|
||||
sendResponse({ ok: true });
|
||||
} catch (e) {
|
||||
sendResponse({ error: e.message });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Add keypair
|
||||
if (request.action === 'add_keypair') {
|
||||
try {
|
||||
const keyId = await wasm.add_keypair('Secp256k1', null);
|
||||
let keypairs = (await chrome.storage.local.get(['keypairs'])).keypairs || [];
|
||||
keypairs.push({ id: keyId, label: `Secp256k1-${keypairs.length + 1}` });
|
||||
await chrome.storage.local.set({ keypairs });
|
||||
sendResponse({ keyId });
|
||||
} catch (e) {
|
||||
sendResponse({ error: e.message });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Select keypair
|
||||
if (request.action === 'select_keypair') {
|
||||
try {
|
||||
await wasm.select_keypair(request.keyId);
|
||||
await chrome.storage.local.set({ selectedKeypair: request.keyId });
|
||||
sendResponse({ ok: true });
|
||||
} catch (e) {
|
||||
sendResponse({ error: e.message });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Sign
|
||||
if (request.action === 'sign') {
|
||||
try {
|
||||
// Convert plaintext to Uint8Array
|
||||
const encoder = new TextEncoder();
|
||||
const msgBytes = encoder.encode(request.message);
|
||||
const signature = await wasm.sign(msgBytes);
|
||||
sendResponse({ signature });
|
||||
} catch (e) {
|
||||
sendResponse({ error: e.message });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Query status
|
||||
if (request.action === 'get_status') {
|
||||
const { currentKeyspace, keypairs, selectedKeypair } = await chrome.storage.local.get(['currentKeyspace', 'keypairs', 'selectedKeypair']);
|
||||
sendResponse({ currentKeyspace, keypairs: keypairs || [], selectedKeypair });
|
||||
return true;
|
||||
}
|
||||
});
|
Reference in New Issue
Block a user