145 lines
3.7 KiB
JavaScript
145 lines
3.7 KiB
JavaScript
|
|
// 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
|
||
|
|
});
|