Skip to content
Lucio Paiva edited this page Sep 21, 2019 · 8 revisions

Features

Architecture

Witchcraft consists of three main parts: the background script, the content script and the HTTP server.

For the record, there's a fourth part: the pop-up script. Since it is not an essential part of the architecture, I am not going to cover it here yet.

The background script

The background script is loaded only once per browser session. It starts running as soon as the extension is enabled and stays quiet, patiently waiting, listening for content scripts messages. It also communicates with the HTTP server when needed to request scripts for pages that have just started being loaded.

The content script

The content script, on the other hand, runs once per frame loaded in your browser. This means that, when your browser starts loading a new page, a new content script instance starts running. This is guaranteed by the matches property in manifest.json:

"matches":    ["http://*/*", "https://*/*"],

The exact moment the content script runs is dictated by the manifest.json property run_at:

"run_at":     "document_start"

From the Chrome extension developer docs, document_start means:

Scripts are injected after any files from css, but before any other DOM is constructed or any other script is run.

This is as early as any extension can get a chance to execute in any given page, so that's why it was chosen for Witchcraft, giving its users full control of the page and getting a chance to act even before the page starts being constructed. It also means that, if you need the page to be fully constructed before running your Witchcraft script, you need to wait for the load event, like this:

window.addEventListener("load", yourScriptsMainFunction);

A content script is created not once per page, but once per frame. Usually, simple pages have just one frame, called the top frame. Check this example of Witchcraft running in google.com's top frame:

It is not uncommon, however, for pages to have sub-frames. When that is the case, Witchcraft needs to have a way to run inside of them as well, since the instance running in the top frame does not have access to sub-frames. The way this is done is by using the following property in manifest.json:

"all_frames": true

The HTTP server

Scripts files are stored in your file system, but a Chrome extension cannot have direct access to them due to security reasons (the fileSystem API is for Chrome apps only, not extensions). This means that the extension needs some way to get that job done. Since the extension is able to make HTTP requests, Witchcraft was modeled to use a local HTTP server to fetch scripts. Any http server would do, really, but the supported way of doing it with Witchcraft is using a Chrome app that runs a simple HTTP server. Witchcraft would ideally have its own Chrome app for that, but Google does not allow new Chrome apps to be created, so we need to rely on existing ones. Of course, another way of doing it would be to start your own local HTTP server using something in the lines of Python's simple HTTP server:

python -m SimpleHTTPServer 5743