clavitor/clavis/clavis-chrome/background.js

107 lines
3.2 KiB
JavaScript

// Clavitor Background Service Worker
// Get settings from storage
async function getSettings() {
const result = await chrome.storage.local.get(['vaultUrl', 'apiToken']);
return {
vaultUrl: result.vaultUrl || 'http://localhost:8765',
apiToken: result.apiToken || ''
};
}
// API call helper
async function apiCall(method, path, body) {
const settings = await getSettings();
if (!settings.apiToken) {
throw new Error('Not configured');
}
const opts = {
method,
headers: {
'Authorization': 'Bearer ' + settings.apiToken,
'Content-Type': 'application/json'
}
};
if (body) {
opts.body = JSON.stringify(body);
}
const res = await fetch(settings.vaultUrl + path, opts);
if (!res.ok) {
throw new Error('API error: ' + res.status);
}
return res.json();
}
// Handle messages from popup and content scripts
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'getMatches') {
apiCall('GET', '/api/ext/match?url=' + encodeURIComponent(request.url))
.then(matches => sendResponse({ success: true, matches }))
.catch(err => sendResponse({ success: false, error: err.message }));
return true; // async response
}
if (request.action === 'getEntry') {
apiCall('GET', '/api/entries/' + request.id)
.then(entry => sendResponse({ success: true, entry }))
.catch(err => sendResponse({ success: false, error: err.message }));
return true;
}
if (request.action === 'getTOTP') {
apiCall('GET', '/api/ext/totp/' + request.id)
.then(data => sendResponse({ success: true, data }))
.catch(err => sendResponse({ success: false, error: err.message }));
return true;
}
if (request.action === 'mapFields') {
apiCall('POST', '/api/ext/map', request.data)
.then(mapping => sendResponse({ success: true, mapping }))
.catch(err => sendResponse({ success: false, error: err.message }));
return true;
}
if (request.action === 'fill') {
// Relay fill request to content script
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (tabs[0]) {
chrome.tabs.sendMessage(tabs[0].id, {
action: 'fillFields',
fields: request.fields
});
}
});
sendResponse({ success: true });
return true;
}
if (request.action === 'getSettings') {
getSettings().then(settings => sendResponse({ success: true, settings }));
return true;
}
if (request.action === 'saveSettings') {
chrome.storage.local.set({
vaultUrl: request.vaultUrl,
apiToken: request.apiToken
}).then(() => sendResponse({ success: true }));
return true;
}
});
// Listen for form detection from content scripts
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'formsDetected') {
// Update badge with form count
if (request.count > 0) {
chrome.action.setBadgeText({ text: String(request.count), tabId: sender.tab.id });
chrome.action.setBadgeBackgroundColor({ color: '#c9a84c', tabId: sender.tab.id });
} else {
chrome.action.setBadgeText({ text: '', tabId: sender.tab.id });
}
}
});