diff --git a/Makefile b/Makefile index 4338a0a..bcae899 100644 --- a/Makefile +++ b/Makefile @@ -24,20 +24,28 @@ # Usage: # make # typecheck and bundle into build/ # make test # run the unit tests -# make dist # build, then zip build/ into logsdu-.zip -# make clean # remove build/ and the zip +# make xpi # build, then package build/ as logsdu-.xpi +# make clean # remove build/ and the package # # Dependencies are installed with pnpm, never npm: # corepack pnpm install # -# Load build/ in Firefox: about:debugging -> This Firefox -> -# Load Temporary Add-on -> pick build/manifest.json +# Permanent install (Firefox ESR, Developer Edition or Nightly): +# set xpinstall.signatures.required=false in about:config, then +# about:addons -> gear -> Install Add-on From File -> pick the .xpi +# +# Release Firefox refuses unsigned add-ons whatever that pref says. There the +# same .xpi has to go through addons.mozilla.org as an unlisted add-on first, +# which signs it automatically without publishing or reviewing it. +# +# Throwaway install for development: about:debugging -> This Firefox -> +# Load Temporary Add-on -> pick build/manifest.json (dropped on restart). EXT_ID := logsdu VERSION := $(shell node -p "require('./package.json').version") -DIST := $(EXT_ID)-$(VERSION).zip +XPI := $(EXT_ID)-$(VERSION).xpi -.PHONY: all build test dist clean check-deps +.PHONY: all build test xpi clean check-deps all: build @@ -53,16 +61,19 @@ build: check-deps node_modules/.bin/tsc -noEmit -skipLibCheck node esbuild.config.mjs production -# A plain zip of build/ is exactly what AMO wants for signing. -dist: build - rm -f $(DIST) - cd build && zip -qr ../$(DIST) . - @echo "Package: $(DIST)" - @echo "Upload it to addons.mozilla.org as an unlisted add-on to get a signed .xpi." +# An .xpi is just a zip of the extension directory, with the manifest at the +# top level rather than inside a wrapper folder. The same file installs +# directly on ESR and uploads to AMO for signing. +xpi: build + rm -f $(XPI) + cd build && zip -qr ../$(XPI) . + @echo "Package: $(XPI)" + @echo "Install: about:addons -> gear -> Install Add-on From File" + @echo "Needs xpinstall.signatures.required=false on ESR/Developer/Nightly." clean: rm -rf build - rm -f $(EXT_ID)-*.zip + rm -f $(EXT_ID)-*.xpi $(EXT_ID)-*.zip # Fail with a useful message rather than a confusing "tsc: not found". check-deps: diff --git a/README.md b/README.md index 80bac64..e072079 100644 --- a/README.md +++ b/README.md @@ -20,20 +20,22 @@ Node 22+ ships `corepack`, so pnpm does not have to be installed globally. ``` corepack pnpm install # first time, or after a dependency change -make # typecheck and bundle into build/ +make xpi # typecheck, bundle, and package logsdu-.xpi ``` -Then load it into Firefox: +Then install it permanently. Firefox will not load an unsigned add-on unless +you tell it to, and only the ESR, Developer Edition and Nightly builds accept +being told: -1. Open `about:debugging` -2. Click **This Firefox** -3. Click **Load Temporary Add-on** -4. Select `build/manifest.json` +1. Open `about:config`, accept the warning +2. Set `xpinstall.signatures.required` to **false** +3. Open `about:addons`, click the **gear** icon, choose **Install Add-on From + File**, and pick `logsdu-.xpi` -Open the extension's options page, fill in the four values, and save. +It survives restarts. On **release** Firefox that pref is ignored -- see +"Release Firefox" below. -A temporary add-on is dropped when Firefox restarts. See "Installing it -permanently" for the fix. +Finally, open the extension's options page, fill in the four values, and save. ## The four values @@ -77,17 +79,18 @@ anywhere. That is the same protection a browser-saved password gets, and it has the same limit -- anyone with your unlocked account can read it. If that is not good enough for your threat model, this extension is the wrong tool. -## Installing it permanently +## Release Firefox -Firefox only keeps unsigned add-ons until the next restart. Two ways around it: +`xpinstall.signatures.required` only works on ESR, Developer Edition and +Nightly. Release Firefox ignores it and refuses unsigned add-ons outright, so +there the same `.xpi` has to be signed first: upload it to +[addons.mozilla.org](https://addons.mozilla.org) as an **unlisted** add-on. +Signing is automated -- nothing is published publicly or reviewed by hand -- and +you install the signed file it hands back. -- **Sign it (recommended).** `make dist` produces `logsdu-.zip`. Upload - it to [addons.mozilla.org](https://addons.mozilla.org) as an **unlisted** - add-on: signing is automated, nothing is published publicly or reviewed by - hand, and you install the signed `.xpi` it hands back. -- **Turn signing off.** Firefox Developer Edition, Nightly or ESR will install - unsigned add-ons with `xpinstall.signatures.required=false` in `about:config`. - Release Firefox ignores that setting. +The `browser_specific_settings.gecko.id` in the manifest is what gives the +add-on a stable identity across both routes, so settings survive an upgrade +from one to the other. ## Chrome @@ -101,15 +104,19 @@ do not assume it works. ``` corepack pnpm install make test # unit tests -make # typecheck and bundle +make # typecheck and bundle into build/ corepack pnpm run dev # rebuild on change make clean ``` -After a rebuild, press **Reload** next to the extension in `about:debugging`. +While iterating, reinstalling an `.xpi` for every edit is tedious. Load the +unpacked directory instead: `about:debugging` -> **This Firefox** -> **Load +Temporary Add-on** -> `build/manifest.json`, then press **Reload** there after +each rebuild. That copy disappears on restart, which is the point -- it is for +development, not for daily use. -`corepack pnpm run dev` watches and rebuilds, including the static files, but -Firefox still needs that Reload click to pick anything up. +`corepack pnpm run dev` watches and rebuilds, static files included, but +Firefox still needs the Reload click to pick anything up. ### Layout