diff --git a/manifest-chrome.partial.json b/manifest-chrome.partial.json index 6296876..5232b1a 100644 --- a/manifest-chrome.partial.json +++ b/manifest-chrome.partial.json @@ -5,5 +5,12 @@ "background": { "service_worker": "dist/backgroundScript.js", "type": "module" - } + }, + "content_scripts": [ + { + "matches": ["*://codeforces.com/*", "*://*.codeforces.com/*"], + "js": ["dist/contentScript.js"], + "run_at": "document_start" + } + ] } diff --git a/manifest-firefox.partial.json b/manifest-firefox.partial.json index 4ad3bee..311ff3b 100644 --- a/manifest-firefox.partial.json +++ b/manifest-firefox.partial.json @@ -14,5 +14,12 @@ "id": "{5dd8fd6e-0733-41a7-abc4-e19fba703de9}", "strict_min_version": "49.0" } - } + }, + "content_scripts": [ + { + "matches": ["*://codeforces.com/*", "*://*.codeforces.com/*"], + "js": ["dist/contentScript.js"], + "run_at": "document_start" + } + ] } diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..cbfc18d --- /dev/null +++ b/manifest.json @@ -0,0 +1,24 @@ +{ + "name": "CPH Submit", + "author": "agrawal-d@outlook.com", + "homepage_url": "https://github.com/agrawal-d/cph-submit", + "version": "1.4.0", + "description": "Codeforces Submit add-on for Competitive Programming Helper.", + "icons": { + "48": "icon-48.png" + }, + "manifest_version": 3, + "permissions": ["scripting", "webNavigation"], + "host_permissions": ["http://localhost/*", "https://codeforces.com/*"], + "background": { + "service_worker": "dist/backgroundScript.js", + "type": "module" + }, + "content_scripts": [ + { + "matches": ["*://codeforces.com/*", "*://*.codeforces.com/*"], + "js": ["dist/contentScript.js"], + "run_at": "document_start" + } + ] +} diff --git a/src/backgroundScript.ts b/src/backgroundScript.ts index 7171167..afe16e9 100644 --- a/src/backgroundScript.ts +++ b/src/backgroundScript.ts @@ -4,6 +4,27 @@ import { CphSubmitResponse, CphEmptyResponse } from './types'; import { handleSubmit } from './handleSubmit'; import log from './log'; +declare const browser: any; + +if (typeof browser !== 'undefined') { + self.chrome = browser; +} + +// Track connected ports to keep service worker alive +const connectedPorts: Set = new Set(); + +chrome.runtime.onConnect.addListener((port) => { + if (port.name === 'cph-keep-alive') { + connectedPorts.add(port); + log('Keep-alive port connected, total ports:', connectedPorts.size); + + port.onDisconnect.addListener(() => { + connectedPorts.delete(port); + log('Keep-alive port disconnected, total ports:', connectedPorts.size); + }); + } +}); + const mainLoop = async () => { let cphResponse; try { diff --git a/src/contentScript.ts b/src/contentScript.ts new file mode 100644 index 0000000..373a530 --- /dev/null +++ b/src/contentScript.ts @@ -0,0 +1,33 @@ +// Content script for Codeforces pages - keeps service worker alive +import log from './log'; + +declare const browser: any; +declare const self: any; + +if (typeof browser !== 'undefined') { + self.chrome = browser; +} + +log('CPH-Submit content script loaded on Codeforces'); + +// Establish keep-alive connection +let port: any = null; + +const connectKeepAlive = () => { + try { + port = chrome.runtime.connect({ name: 'cph-keep-alive' }); + log('Keep-alive port connected'); + + port.onDisconnect.addListener(() => { + log('Keep-alive port disconnected'); + port = null; + // Reconnect after short delay + setTimeout(connectKeepAlive, 1000); + }); + } catch (err) { + log('Failed to connect keep-alive port', err); + setTimeout(connectKeepAlive, 1000); + } +}; + +connectKeepAlive(); diff --git a/src/handleSubmit.ts b/src/handleSubmit.ts index 3b0c677..c4238e5 100644 --- a/src/handleSubmit.ts +++ b/src/handleSubmit.ts @@ -60,14 +60,26 @@ export const handleSubmit = async ( files: ['/dist/injectedScript.js'], }); } - chrome.tabs.sendMessage(tabId, { - type: 'cph-submit', - problemName, - languageId, - sourceCode, - url: problemUrl, - }); - log('Sending message to tab with script'); + // Wait for tab to fully load before sending message + const sendMessageWhenReady = () => { + chrome.tabs.get(tabId, (tab) => { + if (tab.status === 'complete') { + chrome.tabs.sendMessage(tabId, { + type: 'cph-submit', + problemName, + languageId, + sourceCode, + url: problemUrl, + }); + log('Message sent to fully loaded tab'); + } else { + // Retry after short delay + log('Tab not ready, retrying...'); + setTimeout(sendMessageWhenReady, 100); + } + }); + }; + sendMessageWhenReady(); const filter = { url: [{ urlContains: 'codeforces.com/problemset/status' }], diff --git a/webpack.config.js b/webpack.config.js index c430d13..f063491 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,6 +4,7 @@ module.exports = { entry: { backgroundScript: './src/backgroundScript.ts', injectedScript: './src/injectedScript.ts', + contentScript: './src/contentScript.ts', }, output: { filename: '[name].js',