// CrowdProof Observe - Chrome Background Service Worker // Handles side panel toggle and context menus // Create context menus on install chrome.runtime.onInstalled.addListener(() => { chrome.contextMenus.create({ id: "send-url-to-crowdproof", title: "Send URL to CrowdProof", contexts: ["link"] }); chrome.contextMenus.create({ id: "send-image-to-crowdproof", title: "Send Image to CrowdProof", contexts: ["image"] }); }); // Open side panel when action button is clicked chrome.action.onClicked.addListener((tab) => { chrome.sidePanel.open({ windowId: tab.windowId }); }); // Handle context menu click chrome.contextMenus.onClicked.addListener((info, tab) => { // Open side panel chrome.sidePanel.open({ windowId: tab.windowId }); if (info.menuItemId === "send-url-to-crowdproof") { chrome.storage.local.set({ pendingUrl: info.linkUrl }); } else if (info.menuItemId === "send-image-to-crowdproof") { // Store the image source URL - sidepanel will fetch it chrome.storage.local.set({ pendingImage: { sourceUrl: info.srcUrl } }); } }); // API helper const API = { async getServerUrl() { const result = await chrome.storage.local.get('serverUrl'); return result.serverUrl || null; }, async request(endpoint, options = {}) { const serverUrl = await this.getServerUrl(); if (!serverUrl) { throw new Error('Server URL not configured. Please set it in extension options.'); } const url = `${serverUrl}${endpoint}`; const fetchOptions = { credentials: 'include', ...options }; const response = await fetch(url, fetchOptions); return response; }, async login(username, password) { const formData = new FormData(); formData.append('username', username); formData.append('password', password); const response = await this.request('/login', { method: 'POST', body: formData }); return { success: response.ok && !response.url.includes('/login'), response }; }, async logout() { const response = await this.request('/logout', { method: 'GET' }); return response.ok; }, async checkAuth() { const response = await this.request('/profile', { method: 'GET' }); return !response.url.includes('/login'); }, async createObservation(type, formData) { const response = await this.request(`/create_observation/${type}`, { method: 'POST', body: formData }); return { success: response.ok, response }; } }; // Handle messages from sidepanel chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { (async () => { try { switch (message.action) { case 'getServerUrl': sendResponse({ serverUrl: await API.getServerUrl() }); break; case 'checkAuth': const isAuthenticated = await API.checkAuth(); sendResponse({ authenticated: isAuthenticated }); break; case 'login': const loginResult = await API.login(message.username, message.password); sendResponse({ success: loginResult.success }); break; case 'logout': const logoutSuccess = await API.logout(); sendResponse({ success: logoutSuccess }); break; case 'createObservation': const obsResult = await API.createObservation(message.type, message.formData); sendResponse({ success: obsResult.success }); break; default: sendResponse({ error: 'Unknown action' }); } } catch (error) { sendResponse({ error: error.message }); } })(); return true; // Keep message channel open for async response });