A bootstrapped (restartless) UXP extension that provides a
WebExtensions compatibility shim for Pale Moon (and other UXP
applications). It lets Pale Moon load and run a meaningful subset of
Manifest V2 browser.* / chrome.* extensions — the APIs that map
cleanly onto UXP's toolkit — while honestly reporting what cannot work
on this platform.
This is a compatibility shim, not a port of the real WebExtensions engine: its job is to get useful extensions running and to fail predictably everywhere else.
See docs/SUPPORTED_APIS.md for the full matrix. Highlights:
manifest.jsonv2 parsing with validation + warnings (background,content_scripts,browser_action,options_ui,permissions,commands,_locales, host permissions)runtime,extension— messaging (sendMessage,onMessage,connect/Ports),getURL,getManifest,openOptionsPage, …storage.local(JSON file persistence,onChanged) —syncis aliased to localtabs— query/create/update/remove/reload/duplicate, events,sendMessage,executeScript,insertCSS/removeCSSwindows— get/create/update/remove + focus eventsbrowserAction— real toolbar button with badge, per-tab overrides, popup panelcontextMenus/menus,notifications,alarms,cookies,i18n,permissions(declared-set queries),webNavigation(basic),commands- Content scripts:
matches/exclude_matches,js/css,run_atstart/end/idle,all_frames - An in-browser manager window (Tools → "WebExtensions (UXP Shim)"
or about:addons Options) to install
.xpi/.zip/.crx(Chrome package) files or unpacked directories, enable/disable, reload, and open options pages - Experimental: install-by-URL/ID from the Firefox Add-ons site (AMO) and the Chrome Web Store — disabled by default, see docs/USAGE.md
- A bundled example extension under
examples/hello-webextthat exercises most of the implemented surface
The following are documented as unsupported (the shim logs a warning when a manifest asks for them):
webRequest/webRequestBlocking(no request-interception API)- Manifest V3 (service workers,
action,declarativeNetRequest) - Event pages / non-persistent backgrounds
bookmarks,history,downloads,sessions,topSites,identity,devtools,omnibox,sidebar_action,page_action,theme,find,search,idle,proxy,privacy,browsingData,tabCapture,clipboardWrite,management,pageCapture,saveAsPDF(API stubs reject)- Private-browsing modeling (
inIncognitoContextis alwaysfalse) - Runtime permission prompts (
permissions.requestresolvesfalsefor undeclared permissions) - Store browsing/search, accounts, reviews, and publishing — the experimental store feature is install-by-URL/ID only, and the Chrome Web Store side relies on Chromium's undocumented update endpoint (no official API)
- Extension pages run elevated. Background pages, popups and
options pages are hosted via
document.writeinto chrome-owned<browser>elements, so they run with the chrome principal. This buys synchronousbrowser/chromeinjection and cross-origin XHR (matching the effect of host permissions), but it means an extension's page code is technically chrome-privileged. Only load extensions you trust. - Pale Moon has no e10s, which the shim exploits: content scripts run in sandboxes over the page window in the same process, and the message bus is a direct in-process dispatch rather than a frame- script protocol.
- Toolbar buttons are appended to
nav-bar(Pale Moon dropped Australis'CustomizableUI); they can be removed via toolbar customization but placement is not persisted per-button. tabs.querytitledoes substring matching;urluses proper match patterns.alarms, badge state, and per-tab overrides are session-scoped;storage.localis the only persisted API state.- Frame ids are simple per-tab ordinals (0 = top frame).
- Zip the repository contents (not the repo dir itself) — or run
./pack.sh— intouxp-webextensions.xpi. - In Pale Moon: about:addons → gear → Install Add-on From File…
- Open Tools → WebExtensions (UXP Shim) and use Load unpacked…
on
examples/hello-webext/, or Install .xpi/.crx… on any MV2 extension.
npm test # node tests/run_tests.js
./pack.sh # produce uxp-webextensions.xpi
The node test suite (tests/) loads every JSM under a stubbed
Components and unit-tests match patterns, manifest validation,
storage diffs, and page-wrapping. In-browser behavior cannot be
verified without a Pale Moon install; treat untested-in-browser paths
as "best-effort" (see each module's header comments).
bootstrap.js restartless entry point
install.rdf UXP add-on manifest (Pale Moon 29+)
chrome.manifest chrome://uxpwe/ package registration
chrome/content/ manager UI, page-host window, shim stylesheet
modules/
ExtensionManager.jsm registry + install/uninstall/lifecycle
Extension.jsm one loaded WebExtension
Manifest.jsm MV2 validation/normalization (pure)
MatchPattern.jsm match patterns (pure)
Messaging.jsm contexts + message bus + Ports
PageHost.jsm chrome-hosted extension pages
ContentScripts.jsm content-script sandbox injection
CoreAPI.jsm runtime/extension/storage/i18n/alarms/…
UIAPI.jsm tabs/windows/browserAction/menus/webNav
TabTracker.jsm window+tab tracking, toolkit event bridge
APIUtil.jsm browser.*/chrome.* facade builder
StorageBackend.jsm per-extension JSON storage
CrxPackage.jsm CRX2/CRX3 header parsing (pure)
StoreInstall.jsm experimental AMO/CWS install-by-URL
UIGlue.jsm Tools menu + stylesheet
Log.jsm
examples/hello-webext/ demo extension exercising the shim
tests/ node-based unit tests + JSM load smoke test
docs/ API support matrix, architecture notes, usage