MOSTLY OUT-OF-DATE (Feb. 2021)
The control flow starts from
chrome/bootstrap.js where we specify
window scripts like
pepmsghdrview.js. These scripts are executed when Thunderbird opens
a window with the matching type.
These "window scripts" are in in
chrome/content like most of the
code. When executed they import other modules with
ChromeUtils.import, passing the window and other global objects if
needed. Outside of this context we cannot assume that
The three-pane window is always running when Thunderbird is running,
pepmsghdrview.js script performs most of the application
initialisation. One of the main objects to be initialised is the
bootstrap.js we subscribe to notifications from a
that calls a
paint method when the
window object is globally
accessible as a global variable, for every open window.
From there we can pass it to all modules that want to access
it. Outside of this context we cannot assume that
unpaint notification will be sent when the window is
pEpController is a module defined in
chrome/content/modules/pEp.js and is meant to be independent from
p4tb.js, the controller gets augmented with
p4tb.js also contains most of the initialisation logic. There the
server gets a
detectJsonAdapter which populates the
server.connectionInfo on initialisation.
Note that this initialisation sequence is confined to the window where
the script has run, so it's executed again for every message
composition window when the matching
Above we mentioned the
pEpController module. Here we have mainly two
types of modules:
ChromeUtils& Node modules
Most files in
chrome/content define a module of the first type. The
ChromeUtils and Node
modules, so they can be tested with our unit tests.
Our Node modules cannot import other Node modules because then they
wouldn't work as
ChromeUtils modules. These modules can be imported
once and that's it. They can be combined with each other using
Encryption and decryption are performed via components and factories
P4TB-43-2 to be merged).
We define component objects and wrap them with factories that get registered on startup and deregistered on teardown. You might want to deregister factories for testing purposes, since only one factory can be registered for every component id.
Component objects are created in isolation when some events happen, for example the encryption component is created when there is an outgoing message. Since they have this ad-hoc, isolated lifecycle, communication between our components and our views is not straightforward.
We suggest to use different profiles, one for your regular mail use and one for extension development.
Testing can be done using one of the test accounts (need VPN access).
Most of the extension code is written under the assumption that the extension developer can read the engine code as a form of documentation and keep the extension synchronised with the engine's (and adapter's) interfaces.
Many interfaces are defined in the following engine's files:
After that, grep is your friend/enemy (
The extension connects to the JSON adapter server using a token which
is found in
~/.pEp/json-token. The whole purpose of the token is to
be sure that the client runs with the same user rights than the server
When we want to change the plugin preferences we can do so by modifying different areas in the code:
options.xulthe markup, here you define the identifier for the option that will be used also elsewhere
prefsFactory.jsupdate getter and setter functions corresponding to the option and the default value
addAll, the window load handler, the dialogAccept handler
bootstrap.jsupdate the defaults
Are defined in
options.js and globally available