Files

89 lines
3.2 KiB
JavaScript

// Background service worker for Chrome extension
chrome.runtime.onInstalled.addListener(() => {
console.log('GreasyBoii extension installed');
refreshBadge();
});
// Listen for messages from content script
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'getRules') {
chrome.storage.sync.get(['rules'], (result) => {
sendResponse({ rules: result.rules || [] });
});
return true; // Keep channel open for async response
}
// Execute JavaScript via scripting API to bypass CSP
if (request.action === 'executeScript') {
if (!sender.tab || !sender.tab.id) {
sendResponse({ success: false, error: 'No tab ID available' });
return;
}
const tabId = sender.tab.id;
const code = request.code;
const ruleName = request.ruleName;
console.log(`[GreasyBoii Background] Executing script for rule "${ruleName}" on tab ${tabId}`);
// Use chrome.scripting.executeScript which bypasses CSP
chrome.scripting.executeScript({
target: { tabId: tabId },
world: 'MAIN', // Execute in main world (page context), not isolated world
func: (jsCode) => {
try {
// Use indirect eval to execute in global scope
(1, eval)(jsCode);
} catch (e) {
console.error('[GreasyBoii] Script execution error:', e);
}
},
args: [code]
}).then(() => {
console.log(`[GreasyBoii Background] ✓ Script executed successfully`);
sendResponse({ success: true });
}).catch((error) => {
console.error(`[GreasyBoii Background] ✗ Script execution failed:`, error);
sendResponse({ success: false, error: error.message });
});
return true; // Keep channel open for async response
}
// The popup closes the instant the user clicks the page to pick an element, so the
// content script can't hand the selector straight back to it — relay it through
// storage instead; the popup picks it up next time it opens (see popup.js).
if (request.action === 'pickerResult') {
chrome.storage.local.set({ pendingPickResult: request.selector });
} else if (request.action === 'pickerCancelled') {
chrome.storage.local.remove(['pickerPending', 'pendingPickResult']);
}
});
// Master enable/disable keyboard shortcut (see manifest.json "commands")
chrome.commands.onCommand.addListener((command) => {
if (command === 'toggle-greasyboii') {
chrome.storage.sync.get(['masterEnabled'], (result) => {
const enabled = result.masterEnabled !== false;
chrome.storage.sync.set({ masterEnabled: !enabled });
// badge refresh happens via the storage.onChanged listener below
});
}
});
// Keep the toolbar badge in sync whenever masterEnabled changes, from any source
// (the shortcut above, the popup's toggle switch, or a rules import)
chrome.storage.onChanged.addListener((changes, area) => {
if (area === 'sync' && changes.masterEnabled) {
refreshBadge();
}
});
function refreshBadge() {
chrome.storage.sync.get(['masterEnabled'], (result) => {
const enabled = result.masterEnabled !== false;
chrome.action.setBadgeText({ text: enabled ? '' : 'OFF' });
chrome.action.setBadgeBackgroundColor({ color: '#dc3545' });
});
}