November 21, 2021

Inject Script Into Pages As Early As Possible With Web Extension Content Script

Tldr

  1. set run_at to document_start in manifest.json
  2. inject code before <head>
  3. set the injected script tag to async=false
  4. inject with scriptTag.textContent='inpage code' instead of using the src=

Background Knowledge Requirement

  1. know whats web extension manifest.json
  2. know whats content script

Main Article

Web extensions can inject js into web pages with content script.

I’m developing a crypto wallet as browser extension like MetaMask.

These kinds of browser extension usually inject JavaScript code into users’ web pages so that the developer of the web page (usually dapp developers) can use them to contact with users’ wallet.

The problem I was facing early this week is how to inject the js as early as possible so that dapp devs can assume the wallet is available when their code loaded.

What I did is:

  1. set the run_at in content_scripts in manifest.json to document_start
  2. use the content script to inject a <script async=false src="web-extension-xxx/inpage.js></script>" tag into user’s page before <head> tag and after <html> tag.

Since I set async=false, the script is supposed to be loaded, parsed and executed synchronously. And my injected api methods should be present when the page’s js is executed. The truth I found is, it won’t. Actually, it did work once or twice in 10 refresh.

I then changed the content script to inject the inpage.js content directly with scriptTag.textContent = inpageJSContent. The tag is now <script async=false>...inpage.js code...</script>, which requires me to tweak the build process and use mustache and js-string-escape to generate the content script file.

And it works.

You can checkout the code:

  1. the run_at in manifest.json
  2. code in content script that inject the script tag
  3. build script to add the compiled inpage.js string into content script

November 21, 2021 web extension frontend



Previous post
macOS Keychain
Next post
Unprettify Ligatures With Idle Timer in Emacs