DOs and DON'Ts
- traverse the DOM tree expecting to reach subframe's contents
- For example:
- Tree Walker APIs
- window.parent / top / opener
- For example:
- add listeners in the top-level expecting to receive iframes' events
- For example, calling addEventListener in a framescript scope
- send messages to the content process about something related to anything that happened in an iframe
- rely on storage in the child process for information that should be available across navigations
- write any new code in a frame script or process script
- coordinate the walking of the DOM of each content window from the parent process, and aggregate the results there
- add listeners through the Actors infrastructure, and figure out if your actor needs to handle only top-level events or events from all subframes
- declare message listeners through the Actors infrastructure, and send the message directly to the right actor associated with the content you care about
- store long-lived data in the parent, because a child process might be killed if navigation happens to a new domain (which will spawn a new process)
- write all new code using the Actors infrastructure
JS IPDL Actors
What are actors?
In the Fission world, Actors will be the replacement for framescripts. Framescripts were how we structured code to be aware of the parent (UI) and child (content) separation, including establishing the communication channel between the two (via the message manager).
However, the framescripts had no way to establish further process separation downwards (that is, for out-of-process iframes). Actors will be the replacement.
How are they structured?
Currently, in the post-e10s Firefox codebase, we have code living in the parent process (UI) that is in plain JS (.js files) or in JS modules (.jsm). In the child process (hosting the content), we use framescripts (.js) and also JS modules. The framescripts are instantiated once per top-level frame (or, in simpler terms, once per tab). This code has access to all of the DOM from the web content, including iframes on it.
The two processes communicate between them through the message manager (mm) using the sendAsyncMessage API, and any code in the parent can communicate with any code in the child (and vice versa), by just listening to the messsages of interest.
For Fission, all the framescripts will be gone, and the actors replacing them will be structured in pairs. For each frame from the web content (i.e., top-level or subframe), a pair of actors will be instantiated: one in the parent and one in the child process hosting that frame, and a direct channel of communication between the two will be established.
The objects will be instances of classes exported by a module. For example, for an actor Foo, a file FooParent.jsm will export a constructor for the parent instances, and a file FooChild.jsm will export a constructor for the child instances.
Communicating between actors
The communication between the actors' pairs will go through the IPC channel, and all the messages need to be declared in an IPDL file. This means that the actors are, in reality, a JS-implemented IPDL protocol, and that will provide a more strict type checking and validation, differently from the message manager which allowed free-form JS objects to be passed with the messages.
Another difference is that the actors will only communicate between each other. To communicate, the parent and child classes will need to implement send/recv functions, just like C++-implemented IPDL actors.