4.6 KiB
MOSTLY OUT-OF-DATE (Feb. 2021)
Guide to the code
The control flow starts from chrome/bootstrap.js
where we specify
window scripts like pepmessengercompose.js
and
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 window
is
accessible.
The three-pane window is always running when Thunderbird is running,
so its pepmsghdrview.js
script performs most of the application
initialisation. One of the main objects to be initialised is the
controller within chrome/content/p4tb.js
.
The window
object
In bootstrap.js
we subscribe to notifications from a ww
service
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 window
is
accessible. An unpaint
notification will be sent when the window is
closed.
pEpController and p4tb.js
The pEpController
is a module defined in
chrome/content/modules/pEp.js
and is meant to be independent from
Thunderbird. Within p4tb.js
, the controller gets augmented with
Thunderbird-specific logic.
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 pepmessengercompose.js
script
is executed.
Types of modules
Above we mentioned the pEpController
module. Here we have mainly two
types of modules:
ChromeUtils
modulesChromeUtils
& Node modules
Most files in chrome/content
define a module of the first type. The
files in chrome/content/modules
are 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
dependency injection.
Encryption & Decryption
Encryption and decryption are performed via components and factories
defined in pEpMimeEncrypt.js
and pEpMimeDecrypt.js
(branch
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.
Other notes
Environment setup
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).
Relevant entry points to the engine code
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:
pEpEngine.h
message_api.h
message.h
pEp_internal.h
After that, grep is your friend/enemy (darthmama
's quote)
Adapter
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
(Roker
's quote).
Updating the options
When we want to change the plugin preferences we can do so by modifying different areas in the code:
options.xul
the markup, here you define the identifier for the option that will be used also elsewhereprefsFactory.js
update getter and setter functions corresponding to the option and the default valueoptions.js
updateaddAll
, the window load handler, the dialogAccept handlerbootstrap.js
update the defaults
Compat and Prefs
Are defined in options.js
and globally available