Embed libsodium.js in Google Chrome Extension Manifest V3

  Kiến thức lập trình

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:

  1. This old issue identifies that the Chrome Extension environment prevents the use of eval(), which for some reason libsodium.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.
  2. 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 use libsodium.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 or window.postMessage(). The chrome.* 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 my manifest.json to "background": { "service_worker": "js/background.js", "type": "module"}. This results in the error Uncaught 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 error Uncaught 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 the source proprety matches the iframe object instead, and vice-versa.

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website Kho Theme wordpress Kho Theme WP Theme WP

LEAVE A COMMENT