107 lines
3.2 KiB
JavaScript
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 });
|
|
}
|
|
}
|
|
});
|