Skip to content

Commit e589d34

Browse files
authored
Change from chrome to promise based browser api (#19)
1 parent 8bb0afd commit e589d34

8 files changed

Lines changed: 157 additions & 201 deletions

File tree

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ jobs:
2424

2525
- run: npm ci
2626

27-
- run: npx eslint
27+
- run: npx eslint . --ignore-pattern 'translators/*'

background.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
// background.js (sketch)
2-
chrome.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
2+
// Provide a minimal compatibility shim: if `browser` is missing, alias it to `chrome`.
3+
if (typeof browser === "undefined" && typeof chrome !== "undefined") {
4+
globalThis.browser = chrome;
5+
}
6+
7+
browser.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
38
if (!msg || msg.type !== 'runTranslator') return;
49

510
const { translatorPath, translators, url } = msg;
611

712
// If offscreen is available (Chrome), forward the request so the offscreen
813
// document runs the translator. If not (Firefox), run the translator
914
// directly from the background page which has a DOM.
10-
if (chrome.offscreen) {
15+
if (browser.offscreen) {
1116
try {
1217
sendResponse({ ok: true });
1318
} catch (e) {
@@ -23,7 +28,7 @@ chrome.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
2328
const html = await resp.text();
2429

2530
// Import the runner from the extension bundle.
26-
const runnerModule = await import(chrome.runtime.getURL('sources/translatorRunner.js'));
31+
const runnerModule = await import(browser.runtime.getURL('sources/translatorRunner.js'));
2732
const { runTranslatorOnHtml } = runnerModule;
2833

2934
// Normalize translators list: accept either `translators` array or single `translatorPath`.
@@ -59,17 +64,17 @@ chrome.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
5964

6065
try {
6166
const { result, translator: successful } = await firstFulfilled(attempts);
62-
chrome.runtime.sendMessage({ type: 'offscreenResult', url, result, translator: successful });
67+
await browser.runtime.sendMessage({ type: 'offscreenResult', url, result, translator: successful });
6368
sendResponse({ ok: true });
6469
} catch (errors) {
6570
// All attempts failed
6671
const last = Array.isArray(errors) && errors.length ? errors[errors.length - 1] : errors;
6772
const msg = last && last.err ? String(last.err) : String(last || 'All translators failed');
68-
chrome.runtime.sendMessage({ type: 'offscreenResult', url, error: msg });
73+
await browser.runtime.sendMessage({ type: 'offscreenResult', url, error: msg });
6974
sendResponse({ ok: false, error: msg });
7075
}
7176
} catch (e) {
72-
chrome.runtime.sendMessage({ type: 'offscreenResult', url, error: String(e) });
77+
await browser.runtime.sendMessage({ type: 'offscreenResult', url, error: String(e) });
7378
sendResponse({ ok: false, error: String(e) });
7479
}
7580
return true;

offscreen.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import { runTranslatorOnHtml } from './sources/translatorRunner.js';
22

33
console.debug('[offscreen] started');
44

5-
chrome.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
5+
// Provide a minimal compatibility shim: if `browser` is missing, alias it to `chrome`.
6+
if (typeof browser === "undefined" && typeof chrome !== "undefined") {
7+
globalThis.browser = chrome;
8+
}
9+
10+
browser.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
611
if (!msg || msg.type !== 'runTranslator') return;
712
const { url, translatorPath, translators } = msg;
813
try {
@@ -17,28 +22,26 @@ chrome.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
1722
try {
1823
const result = await runTranslatorOnHtml(t, html, url);
1924
if (result !== null && typeof result !== 'undefined') {
20-
chrome.runtime.sendMessage({ type: 'offscreenResult', url, result });
25+
await browser.runtime.sendMessage({ type: 'offscreenResult', url, result });
2126
sendResponse({ ok: true });
2227
return true;
2328
}
24-
// null result -> try next translator
2529
} catch (e) {
2630
lastError = e;
2731
console.warn('[offscreen] translator failed, trying next:', t, e);
2832
continue;
2933
}
3034
}
3135

32-
// none produced a result
3336
if (lastError) {
34-
chrome.runtime.sendMessage({ type: 'offscreenResult', url, error: String(lastError) });
37+
await browser.runtime.sendMessage({ type: 'offscreenResult', url, error: String(lastError) });
3538
sendResponse({ ok: false, error: String(lastError) });
3639
} else {
37-
chrome.runtime.sendMessage({ type: 'offscreenResult', url, result: null });
40+
await browser.runtime.sendMessage({ type: 'offscreenResult', url, result: null });
3841
sendResponse({ ok: true, result: null });
3942
}
4043
} catch (e) {
41-
chrome.runtime.sendMessage({ type: 'offscreenResult', url, error: String(e) });
44+
await browser.runtime.sendMessage({ type: 'offscreenResult', url, error: String(e) });
4245
sendResponse({ ok: false, error: String(e) });
4346
}
4447
return true;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "jabref-browser-extension",
33
"description": "Tests for JabRef Connector Extension",
44
"scripts": {
5+
"lint": "eslint . --ignore-pattern 'translators/*'",
56
"test": "node test.js arXiv.org.js"
67
},
78
"dependencies": {

popup.js

Lines changed: 28 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
// Provide a minimal compatibility shim: if `browser` is missing, alias it to `chrome`.
2+
if (typeof browser === "undefined" && typeof chrome !== "undefined") {
3+
globalThis.browser = chrome;
4+
}
5+
16
async function findMatchesForUrl(url) {
2-
const manifestUrl = chrome.runtime.getURL("translators/manifest.json");
7+
const manifestUrl = browser.runtime.getURL("translators/manifest.json");
38
const resp = await fetch(manifestUrl);
49
const list = await resp.json();
510

@@ -19,8 +24,6 @@ async function findMatchesForUrl(url) {
1924
}
2025

2126
function renderResults(url, matches) {
22-
const log = document.getElementById("log");
23-
const bib = document.getElementById("bibEntry");
2427
// Log the URL
2528
appendLog(`URL: ${url}`);
2629
if (!matches || !matches.length) {
@@ -30,12 +33,12 @@ function renderResults(url, matches) {
3033
}
3134

3235
async function ensureOffscreen() {
33-
if (!chrome.offscreen) return false;
34-
const has = await chrome.offscreen.hasDocument();
36+
if (!browser.offscreen) return false;
37+
const has = await browser.offscreen.hasDocument();
3538
if (has) return true;
3639
try {
37-
await chrome.offscreen.createDocument({
38-
url: chrome.runtime.getURL("offscreen.html"),
40+
await browser.offscreen.createDocument({
41+
url: browser.runtime.getURL("offscreen.html"),
3942
reasons: ["DOM_PARSER"],
4043
justification: "Run translators offscreen",
4144
});
@@ -47,33 +50,20 @@ async function ensureOffscreen() {
4750
}
4851

4952
async function runTranslatorOffscreen(translatorPaths, url) {
50-
const ok = await ensureOffscreen();
53+
await ensureOffscreen();
5154
const payload = { type: "runTranslator", translators: translatorPaths, url };
5255
try {
5356
appendLog(`Requesting translator run for ${url}`, "info");
54-
chrome.runtime.sendMessage(payload, (resp) => {
55-
if (chrome.runtime.lastError) {
56-
appendLog(
57-
`Background sendMessage failed: ${chrome.runtime.lastError.message}`,
58-
"error",
59-
);
60-
return;
61-
}
62-
if (resp && resp.ok)
63-
appendLog("Background acknowledged run request", "info");
64-
else
65-
appendLog(
66-
`Background error: ${resp && resp.error ? resp.error : "unknown"}`,
67-
"error",
68-
);
69-
});
57+
const resp = await browser.runtime.sendMessage(payload);
58+
if (resp && resp.ok) appendLog("Background acknowledged run request", "info");
59+
else appendLog(`Background error: ${resp && resp.error ? resp.error : "unknown"}`, "error");
7060
} catch (e) {
7161
console.error("Failed to send runTranslator message", e);
7262
}
7363
}
7464

7565
// Listen for offscreen results
76-
chrome.runtime.onMessage.addListener((msg) => {
66+
browser.runtime.onMessage.addListener((msg) => {
7767
if (!msg || msg.type !== "offscreenResult") return;
7868
const bib = document.getElementById("bibEntry");
7969
const error = msg.error;
@@ -129,14 +119,10 @@ function updateStatus(status, className) {
129119

130120
// Connect to JabRef via HTTP POST
131121
let jabrefBaseUrl = null;
132-
function getBaseUrl() {
133-
return new Promise((resolve) => {
134-
chrome.storage.local.get({ jabrefPort: 23119 }, (res) => {
135-
const port = res.jabrefPort || 23119;
136-
const base = `http://localhost:${port}/`;
137-
resolve(base);
138-
});
139-
});
122+
async function getBaseUrl() {
123+
const res = await browser.storage.local.get({ jabrefPort: 23119 });
124+
const port = res.jabrefPort || 23119;
125+
return `http://localhost:${port}/`;
140126
}
141127

142128
async function connectToJabRef() {
@@ -240,18 +226,15 @@ document.addEventListener("DOMContentLoaded", async () => {
240226
if (noneEl) noneEl.style.display = "block";
241227
return;
242228
}
243-
try {
244-
if (!window.chrome || !chrome.tabs) {
245-
urlEl.textContent = "Chrome extension APIs not available.";
246-
document.getElementById("none").style.display = "block";
247-
return;
248-
}
229+
try {
230+
if (!window.browser || !browser.tabs) {
231+
urlEl.textContent = "Extension APIs not available.";
232+
document.getElementById("none").style.display = "block";
233+
return;
234+
}
249235

250-
const tab = await new Promise((resolve) => {
251-
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
252-
resolve(tabs && tabs[0]);
253-
});
254-
});
236+
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
237+
const tab = tabs && tabs[0];
255238
const url = tab && tab.url ? tab.url : "";
256239
if (!url) {
257240
urlEl.textContent = "Unable to determine active tab URL.";
@@ -274,9 +257,7 @@ document.addEventListener("DOMContentLoaded", async () => {
274257
renderResults(url, matches || []);
275258
if (matches && matches.length) {
276259
// Build array of translator URLs and request background/offscreen
277-
const translatorPaths = matches.map((m) =>
278-
chrome.runtime.getURL(m.path || ""),
279-
);
260+
const translatorPaths = matches.map((m) => browser.runtime.getURL(m.path || ""));
280261
runTranslatorOffscreen(translatorPaths, url);
281262
}
282263
} catch (e) {

settings.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,22 @@ const cancelBtn = document.getElementById("cancelBtn");
66
const msg = document.getElementById("msg");
77

88
function loadSettings() {
9-
chrome.storage.local.get({ jabrefPort: DEFAULT_PORT }, (res) => {
9+
browser.storage.local.get({ jabrefPort: DEFAULT_PORT }).then((res) => {
1010
portInput.value = res.jabrefPort;
11+
}).catch((e) => {
12+
console.warn('Failed to load settings', e);
1113
});
1214
}
1315

1416
function saveSettings() {
1517
const port = parseInt(portInput.value, 10) || DEFAULT_PORT;
16-
chrome.storage.local.set({ jabrefPort: port }, () => {
18+
browser.storage.local.set({ jabrefPort: port }).then(() => {
1719
msg.textContent = "Saved.";
1820
setTimeout(() => (msg.textContent = ""), 1500);
21+
}).catch((e) => {
22+
console.warn('Failed to save settings', e);
23+
msg.textContent = "Save failed.";
24+
setTimeout(() => (msg.textContent = ""), 1500);
1925
});
2026
}
2127

0 commit comments

Comments
 (0)