I am trying to use libsodium.js
, a C-library that has been transpiled to WASM with Emscripten.
I have found two (1, 2) related posts that are now out of date and/or incomplete:
- This old issue identifies that the Chrome Extension environment prevents the use of
eval()
, which for some reasonlibsodium.js
does upon initialization. In Manifest V3, there doesn’t appear to be a way to allow this this other than sandboxed pages, which I will address below. Also, the example project they linked is not for Manifest V3. - The answer to this post is a dead link that is not archived, but seems to imply using a
iframe
and passing messages between it and the containing DOM. This is likely a moot point as I want to uselibsodium.js
from my background service worker anyway.
What I have tried:
- I have successfully gotten
sodium.js
(the standalone build variant) to load and work when linked in the sandbox page, however, it seems, by design, the sandbox page has no means to communicate back to my extensions background service worker, not even external page messaging orwindow.postMessage()
. Thechrome.*
API is not available in this environment. - Importing using methods in this post.
importScripts()
in the background service worker, which gets me right back to violating extension CSP. (Uncaught (in promise) RuntimeError: Aborted(CompileError: WebAssembly.instantiate(): Refused to compile or instantiate WebAssembly module because neither 'wasm-eval' nor 'unsafe-eval' is an allowed source of script in the following Content Security Policy directive: "script-src 'self'"). Build with -sASSERTIONS for more info.
)- Loading the module build variant in my background service worker like
import {_sodium} from '../thirdparty/js/libsodium-wrappers.js;';
after configuring mymanifest.json
to"background": { "service_worker": "js/background.js", "type": "module"}
. This results in the errorUncaught SyntaxError: The requested module '../thirdparty/js/libsodium-wrappers.js' does not provide an export named '_sodium'
. - Loading the module build variant in my background service worker like
import '../thirdparty/js/libsodium-wrappers.js';
. This results in the errorUncaught TypeError: Cannot read properties of undefined (reading 'sodium')
.
2
@woxxom nudged me in the right direction to discover a working solution, so for future readers:
- Follow the offscreen API tutorial to get a page to load offscreen successfully.
- Inline JavaScript is not allowed, so put it in its own file.
- You can debug the offscreen page by visiting
chrome://inspect/#other
and picking your file out.
- Follow the sandbox API tutorial to get a page to load whatever scripts you want.
- You will be able to debug the sandbox page via the offscreen page’s DevTools instance.
- When sending a message from the offscreen page to the sandbox page, use
document.getElementById("your-iframe-id-here").contentWindow.postMessage("your message", "*")
. - When sending a message from the sandbox page to the offscreen page, use
window.parent.postMessage("your message", "*")
.- The
MessageEvent.origin
property will always be"null"
by design, I recommend you instead check that thesource
proprety matches theiframe
object instead, and vice-versa.
- The