Skip to content

Commit

Permalink
[311] Mozilla Add-ons manifest v3 (#422)
Browse files Browse the repository at this point in the history
* [311] Mozilla Add-ons manifest v3

Ticket: #311

Closes #311

* Update web-ext to v7.12.0

This is the last version before the version change to v8.

Update to v8 requires a bit more action eventually:
/~https://github.com/mozilla/web-ext/releases/tag/8.0.0

* Update manifest to v3 for Firefox

Firefox does not support background service workers. They still want
scripts. So this setup still works fine in Firefox.

* Refactor background script

Instead of relying on the background page instance (which is not
recommended, see link to the docs), we communicate with the background
script (or service worker script in Chrome) via message passing.

This way, we can use the same script in both browsers.

Mozilla docs on the topic: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Background_scripts#update_calls_for_background_script_functions)
  • Loading branch information
klappradla authored Oct 10, 2024
1 parent e6f0579 commit 1f33bc8
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 146 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"bundle:chrome": "cross-env BUNDLE=true run-s build:chrome",
"bundle:firefox": "cross-env BUNDLE=true run-s build:firefox",
"lint": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx .",
"format:js": "eslint --ignore-path .gitignore --fix --ext .js,.ts,.tsx .",
"stylelint": "stylelint --ignore-path .gitignore 'src/**/*.scss'",
"test": "jest",
"typecheck": "tsc --noEmit",
Expand Down Expand Up @@ -79,7 +80,7 @@
"stylelint-junit-formatter": "^0.2.2",
"stylelint-prettier": "^4.0.2",
"typescript": "^5.2.2",
"web-ext": "^7.6.0",
"web-ext": "7.12.0",
"webpack": "5.94.0",
"webpack-chain": "6.5.1",
"webpack-cli": "^5.1.4",
Expand Down
11 changes: 10 additions & 1 deletion src/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import browser from "webextension-polyfill";

import type { BackgroundMessage } from "../popup/types";

async function getTickets() {
const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
const results = await browser.tabs.sendMessage(tab.id!, { tickets: true }); // eslint-disable-line @typescript-eslint/no-non-null-assertion
return results;
}

Object.assign(window, { getTickets });
async function handleMessage(msg: BackgroundMessage) {
if (msg.getTickets) {
return getTickets();
}
return null;
}

browser.runtime.onMessage.addListener(handleMessage);
4 changes: 2 additions & 2 deletions src/content/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import browser from "webextension-polyfill";
import stdsearch from "../core/search";

if (window === window.top) {
browser.runtime.onMessage.addListener((req) => {
if (req.tickets) {
browser.runtime.onMessage.addListener((msg) => {
if (msg.tickets) {
const url = new URL(window.location.toString());
return stdsearch(url, document);
}
Expand Down
29 changes: 12 additions & 17 deletions src/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"manifest_version": 2,
"manifest_version": 3,
"name": "",
"version": "",
"description": "",
Expand All @@ -11,25 +11,18 @@
"128": "icon-128.png"
},
"background": {
"scripts": ["background.js"]
"scripts": ["background.js"],
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": ["content.js"]
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"]
}
],
"web_accessible_resources": [
],
"permissions": [
"activeTab",
"clipboardWrite",
"storage"
],
"browser_action": {
"web_accessible_resources": [],
"permissions": ["activeTab", "clipboardWrite", "storage"],
"action": {
"default_title": "Git Branch/Message",
"default_popup": "popup.html",
"default_icon": {
Expand Down Expand Up @@ -59,12 +52,14 @@
"page": "options.html"
},
"commands": {
"_execute_browser_action": {
"_execute_action": {
"suggested_key": {
"default": "Ctrl+T",
"mac": "MacCtrl+T"
}
}
},
"content_security_policy": "default-src 'none'; img-src 'self' data:; style-src 'self'; script-src 'self';"
"content_security_policy": {
"extension_pages": "default-src 'none'; img-src 'self' data:; style-src 'self'; script-src 'self';"
}
}
32 changes: 19 additions & 13 deletions src/popup/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,20 @@ import enhance from "../core/enhance";
import { deserialize } from "../errors";
import store from "../store";
import render from "./render";
import type { BackgroundPage } from "./types";
import type { BackgroundWorker } from "./types";

const mockBackgroundWorker: BackgroundWorker = { getTickets: jest.fn() };

jest
.mock("webextension-polyfill", () => {
const result = { tickets: [], errors: [] };
const background = { getTickets: jest.fn().mockResolvedValue(result) };
const extension = { getBackgroundPage: () => background };
return { extension };
const runtime = {
sendMessage: jest
.fn()
.mockImplementation((_msg, _sender) =>
mockBackgroundWorker.getTickets(),
),
};
return { runtime };
})
.mock("../core/enhance", () => jest.fn(() => jest.fn()))
.mock("../store", () => ({ get: jest.fn().mockResolvedValue({}) }))
Expand All @@ -27,11 +33,8 @@ jest
describe("popup", () => {
const initialize = window.onload as () => Promise<void>;

let background: BackgroundPage;

beforeEach(() => {
background = browser.extension.getBackgroundPage() as BackgroundPage;
(background.getTickets as jest.Mock).mockResolvedValue({
(mockBackgroundWorker.getTickets as jest.Mock).mockResolvedValue({
tickets: [],
errors: [],
});
Expand All @@ -40,7 +43,7 @@ describe("popup", () => {
});

afterEach(() => {
(background.getTickets as jest.Mock).mockReset();
(mockBackgroundWorker.getTickets as jest.Mock).mockReset();
(store.get as jest.Mock).mockReset();
(enhance as jest.Mock).mockReset();
(render as jest.Mock).mockReset();
Expand All @@ -53,7 +56,10 @@ describe("popup", () => {
it("fetches ticket information through the background page", async () => {
await initialize();

expect(background.getTickets).toHaveBeenCalled();
expect(browser.runtime.sendMessage).toHaveBeenCalledWith({
getTickets: true,
});
expect(mockBackgroundWorker.getTickets).toHaveBeenCalled();
});

it("loads settings from storage", async () => {
Expand All @@ -76,7 +82,7 @@ describe("popup", () => {
const tickets = ["uno", "dos"].map((title, id) =>
make({ id: id.toString(), title }),
);
(background.getTickets as jest.Mock).mockResolvedValue({
(mockBackgroundWorker.getTickets as jest.Mock).mockResolvedValue({
tickets,
errors: [],
});
Expand All @@ -98,7 +104,7 @@ describe("popup", () => {

it("renders the popup content with errors", async () => {
const errors = [{ message: "Test Error" }];
(background.getTickets as jest.Mock).mockResolvedValue({
(mockBackgroundWorker.getTickets as jest.Mock).mockResolvedValue({
tickets: [],
errors,
});
Expand Down
6 changes: 3 additions & 3 deletions src/popup/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { deserialize } from "../errors";
import store from "../store";
import onmedia from "./observe-media";
import render from "./render";
import type { BackgroundPage } from "./types";

async function load() {
const background = browser.extension.getBackgroundPage() as BackgroundPage;
const { tickets, errors } = await background.getTickets();
const { tickets, errors } = await browser.runtime.sendMessage({
getTickets: true,
});
const { options = {}, templates } = await store.get(null);

const enhancer = await enhance(templates, options.autofmt);
Expand Down
8 changes: 8 additions & 0 deletions src/popup/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ import type { Ticket } from "../types";
export type BackgroundPage = Window & {
getTickets: () => { tickets: Ticket[]; errors: ErrorObject[] };
};

export type BackgroundWorker = {
getTickets: () => { tickets: Ticket[]; errors: ErrorObject[] };
};

export type BackgroundMessage = {
getTickets?: boolean;
};
5 changes: 1 addition & 4 deletions webpack.config.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,11 @@ config.plugin("copy").use(CopyWebpackPlugin, [
mf.description = pkg.description;

if (variant === "firefox") {
mf.options_ui.browser_style = true;
mf.applications = {
mf.browser_specific_settings = {
gecko: {
id: "jid1-ynkvezs8Qn2TJA@jetpack",
},
};
} else {
mf.options_ui.chrome_style = true;
}

return JSON.stringify(mf);
Expand Down
Loading

0 comments on commit 1f33bc8

Please sign in to comment.