Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion manifest-chrome.partial.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
]
}
9 changes: 8 additions & 1 deletion manifest-firefox.partial.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
]
}
24 changes: 24 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -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"
}
]
}
21 changes: 21 additions & 0 deletions src/backgroundScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<chrome.runtime.Port> = 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 {
Expand Down
33 changes: 33 additions & 0 deletions src/contentScript.ts
Original file line number Diff line number Diff line change
@@ -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();
28 changes: 20 additions & 8 deletions src/handleSubmit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' }],
Expand Down
1 change: 1 addition & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module.exports = {
entry: {
backgroundScript: './src/backgroundScript.ts',
injectedScript: './src/injectedScript.ts',
contentScript: './src/contentScript.ts',
},
output: {
filename: '[name].js',
Expand Down