From cea43d8aa7ca2c6dc020816bddb3015794383b79 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Fri, 16 Feb 2024 22:45:50 +0000 Subject: [PATCH] Bug 1879829 - Add work-in-progress documentation on existing protocol implementations. r=heather Differential Revision: https://phabricator.services.mozilla.com/D201375 --HG-- extra : moz-landing-system : lando --- docs/architecture/LoadMessageCallStack.png | Bin 0 -> 41169 bytes docs/architecture/MessageRenderingSchema.png | Bin 0 -> 24691 bytes docs/architecture/MessageStorageSchema.png | Bin 0 -> 30923 bytes docs/architecture/email_protocols.md | 251 +++++++++++++++++++ docs/architecture/index.md | 5 + docs/index.rst | 1 + 6 files changed, 257 insertions(+) create mode 100644 docs/architecture/LoadMessageCallStack.png create mode 100644 docs/architecture/MessageRenderingSchema.png create mode 100644 docs/architecture/MessageStorageSchema.png create mode 100644 docs/architecture/email_protocols.md create mode 100644 docs/architecture/index.md diff --git a/docs/architecture/LoadMessageCallStack.png b/docs/architecture/LoadMessageCallStack.png new file mode 100644 index 0000000000000000000000000000000000000000..d26fe6d5145029bdde54f1f678264cb38d267942 GIT binary patch literal 41169 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

VUBr=tMf0lL=b=`cbUHQE&;kPH|- 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�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%0A_H+8TASBp@f~nsya3xK&UVhmo+1k&K18~G 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 literal 0 HcmV?d00001 diff --git a/docs/architecture/email_protocols.md b/docs/architecture/email_protocols.md new file mode 100644 index 0000000000..cfa7f7ffcd --- /dev/null +++ b/docs/architecture/email_protocols.md @@ -0,0 +1,251 @@ +# Implementation architecture for email protocols + +This document describes the code architecture used by protocol implementations +in Thunderbird. Its aim is to give more insight into existing protocol +implementations, by summarizing the interactions between the involved +components, and illustrating with the example of the IMAP protocol +implementation. + +

Warning
+ +This document was initially written during the exploratory phase of the Exchange +protocol implementation into Thunderbird, when it became clear that our +understanding of what a protocol is within Thunderbird was insufficient to +tackle this project. + +While the initial research has allowed us to build a solid base of documentation +on this topic, this is still very much a living document, as there will very +likely be more discoveries made and lessons learned while working through actual +protocol implementations. + +Therefore, this document should be considered a work in progress for now. + +
+ + +## Overview + + +### Components + +These are the main components used to implement a protocol. The frontend is +generic enough to not require protocol-specific component implementations. + +* URL (`nsIURL`): Static description of a resource following a spec defined by + the protocol implementation (therefore it might not correspond to resource + identifiers defined by the protocol's specification, and might translate to + more than one operation on the remote server). Sometimes it is given + additional structures such as message + [sinks](https://en.wikipedia.org/wiki/Sink_(computing)), channels, etc. +* Message service (`nsIMsgMessageService`): Abstraction layer that is capable of + parsing the string representation of a URL. Also provides APIs to run specific + messaging-related operations (load message, delete folder, edit message flags + (if relevant), search, etc) by turning them into URLs. +* Channel (`nsIChannel`): Asynchronous layer enabling communication between a + service (or other parts of the backend) and a server. The channel has the same + lifetime as the request being made, and carries its parameters to the + connection, as well as any listener or event sink needed to ferry messages + back to the caller. It is able to start in a held state until a connection + becomes available. +* Incoming server (`nsIMsgIncomingServer`): Represents a single server to talk to. Keeps + track of the data needed to connect to the server (address, credentials, + connectivity status, etc), as well as a connection pool. +* Protocol / Connection: The component that actually talks to the socket, by + implementing the protocol's specification. Turns the URL into a set of + operations, runs them, then feeds data back to other stakeholders via + listeners and event sinks. This class is designed after the specific needs of + the protocol that is being implemented, rather than based on an existing + interface/class in order to mutualize code (which has created complications + historically). +* Folder (`nsIMsgFolder`): Represents a single folder on the server. Provides + APIs for performing common operations on/interacting with the folder, thus + providing abstraction on the storage side of the operation/interaction. +* Database (`nsIMsgDatabase`): Stores the metadata and headers related to + messages received. +* Message store (`nsIMsgPluggableStore`): Stores the content of the messages + received. + + +### Relationship between components + +The frontend interacts with the backend in two ways: + +* By calling upon the message service to trigger operations that require + interaction with the server +* By interacting with a global instance of `nsMsgDBView` (often wrapped into an + instance of `DBViewWrapper`) to operate on the message database/store, usually + through an `nsIMsgFolder` instance. + +When the message service receives a call, it sends the request through a +channel. This call usually comes with a string representation of the URL for a +folder or message (or other entity, depending on the protocol), or multiple +depending on the operation. The channel is created either directly, or via +`nsIDocShell::LoadURI` if the frontend provides the message service with an +object which implements `nsIDocShell` (sometimes referred to as a display +consumer), and if the operation involves fetching a resource at the given URL. + +Attached to the URL are potential parameters for the request, as well as event +sinks and listeners (which can be provided by the frontend directly) that can be +used to inform the frontend (or other intermediate party) about the state of the +operation and communicate any resulting data. In future implementations (or when +reworking existing ones), these really should be attached to the channel +instead. + +The message service might also be given a reference to the `nsIMsgWindow` used +by the frontend, which it uses to feed progress updates back to it. Note that +this is likely not a viable solution going forwards, as we want to limit the +backend from directly interacting with the frontend's window. + +At the other end of this channel is an incoming server, which then looks for an +available connection in its pool (or opens one if none is open and available), +and calls it with the request parameters (including the URL(s) if any) and +sinks/listeners (and any other reference necessary). The connection then talks +to the remote server via a socket using the protocol’s specification, and +communicates any data back via the listener. + +The database might get a call from the frontend (either directly or through a +folder) that it cannot satisfy by itself. In this case, it can interact with the +message service to retrieve any missing data. The message store isn’t called +directly from the frontend, and is (theoretically) optional. + +Other components might also interact with the message service, for example an +auto-sync loop that frequently checks for new messages (or listens for pull +notifications). + + +## Case study: IMAP + +This section describes at a very high level how the IMAP protocol is implemented +in Thunderbird. + +It is heavily summarized and focuses on understanding the function of each +component involved and the interaction between them, rather than going into +detail into all the features implemented by each of them. This is also why the +references related to inheritance don’t list all of the classes/interfaces +implemented by a given class. + + +### Frontend + +Fortunately, the frontend part is fairly generic and protocol agnostic in most +places. When displaying a message, the frontend identifies the correct service +using `MailServices.messageServiceFromURI` with a URI retrieved from the +database, then calls `loadMessage` (which is defined by `nsIMsgMessageService`) +on this service. + +The frontend is populated via listeners consuming data sent from the backend as +well as a global instance of `nsMsgDBView` (often wrapped into an instance of +`DBViewWrapper`). + + +### Message service + +The interface layer between the frontend and the more hairy bits of the backend +(`nsImapService`, implements `nsIMsgMessageService`). The message service +provides methods for specific operations, then turns them into `nsIImapUrl`, +before passing them onto the `nsIMsgIncomingServer` and `nsImapProtocol` via an +`nsImapMockChannel`. + + +### URL + +A single URL describes a single operation. In IMAP land, this can be your +standard fetch, or deletemsg, addmsgflags, etc. (`nsImapUrl`, implements +`nsIURL` via `nsIMsgMailNewsUrl`). One `nsImapUrl` can result in multiple IMAP +commands. + +One issue with the IMAP URL is the amount of structures that don't strictly +describe the operation to perform it references. For example: instead of +attaching the URL listener and message sink that are used to carry messages +related to the operation to the channel, they're attached to the URL; the URL +keeps a reference of the `nsIImapMockChannel` used to pass it onto the +`nsIImapProtocol` instead of this reference being directly passed onto the +protocol; etc. + +As previously mentioned, IMAP URLs are also used to refer to an operation rather +than a resource to retrieve (which can amount to the same thing, e.g. with a +fetch, but not always, e.g. copying a message, deleting it, etc). In other +words, the URL is the API to IMAP for the message service (and, to some extent, +the frontend). Ideally this API would live elsewhere, for example in +`nsIImapMockChannel`, `nsIMsgIncomingServer` and/or `nsIImapProtocol` which +interacts (asynchronously or not, depending on the layer) directly with the IMAP +server. + + +### Channel + +A channel is used to ferry the information for a specific operation from the +message service to the server (`nsImapMockChannel`, implements `nsIChannel` via +`nsIImapMockChannel`). In a way, a channel can be seen as the representation of +a request to the server (with the caveat that, if the `nsImapUrl` requires it, +it might result in multiple IMAP commands). + + +### Incoming server + +An incoming server represents an IMAP server (`nsImapIncomingServer`, implements +`nsIMsgIncomingServer`). It keeps track of the connection information for the +server, such as credentials, connectivity status, etc, as well as a pool of +active connections (`nsImapProtocol`) to it. + + +### Protocol + +`nsImapProtocol` (implements `nsIImapProtocol` and `nsMsgProtocol`) is the class +in charge of talking to an IMAP server. Each instance is scoped to an IMAP +server, and runs on its own thread (though it’s a special case benefiting from +an exemption, and should not be reproduced in future implementations). It takes +a URL and turns it into the required IMAP commands. First +`nsImapProtocol::LoadImapUrl` is called with a URL (queued by +`nsImapIncomingServer`), then a signal is sent (via `m_urlReadyToRunMonitor`) to +`ImapThreadMainLoop` to let it know there’s a new URL to process. `IsBusy` and +`CanHandleUrl` are used to figure out whether a protocol instance can be used. +Note that these methods are inherited from `nsIImapProtocol`. + +![Sequence diagram illustrating the call stack for loading a message from the frontend to (in order) nsImapService, nsImapMockChannel, nsImapIncomingServer, and finally nsImapProtocol.](LoadMessageCallStack.png) + +_Summarized call stack involved in loading a message._ + + +### Storage + + +There are three layers to storing messages: +* Folders (`nsImapMailFolder` (implements `nsIMsgFolder`)), which provide an + abstraction layer for basic operations on IMAP folders, and a way for the UI + and other parts of the backend to access the database and message store + associated with a given IMAP folder. +* Database (`nsImapMailDatabase` (implements `nsIMsgDatabase`)), which provides + access to metadata and headers of messages. It’s used as the master list of + messages in a folder, wherever the full messages are (stored locally, on a + server, etc). +* Pluggable message store (implementation of `nsIMsgPluggableStore`, not + protocol specific, existing implementations are `nsMsgMaildirStore` and + `nsMsgBrkMBoxStore`), which stores the content of messages. + + +![Schema depicting how nsIMsgFolder depends on nsIMsgDatabase (which itself depends on nsIMsgDBHdr) to store message metadata, and on nsIMsgPluggableStore to store the content of messages.](MessageStorageSchema.png) + +_Relationship between the layers related to storing messages._ + +At the time of writing, this aspect of the protocol implementation is being +redesigned to remove the strong dependency between the database/store and +individual folders. + + +### Rendering messages + +![Schema depicting the rendering process of a message: the frontend makes a call to a message service, which creates a channel that sends the message content to a stream listener. The stream listener then sends the message content to a docshell within the frontend.](MessageRenderingSchema.png) + +_Summarized depiction of message rendering._ + +When fetching a message, the `nsImapService` calls `nsIDocShell::LoadURI`, which +means the call to `nsImapMockChannel::AsyncOpen` is done through +`DocumentLoadListener::AsyncOpen`. It instantiates the `nsImapMockChannel` by +calling `NewChannel` on the class registered with the contract ID +`@mozilla.org/network/protocol;1?name=imap` - in this case `nsImapService`. + +It is likely `DocumentLoadListener` sets relevant callbacks to the +`nsIStreamListener` that is passed to `nsImapMockChannel::AsyncOpen` to load +content into the `nsIDocShell` once a message has been retrieved. More research +is needed to fully understand how this data is fed back into the docshell. diff --git a/docs/architecture/index.md b/docs/architecture/index.md new file mode 100644 index 0000000000..600aaefcc3 --- /dev/null +++ b/docs/architecture/index.md @@ -0,0 +1,5 @@ +# Thunderbird code architecture + +```{toctree} +email_protocols +``` diff --git a/docs/index.rst b/docs/index.rst index a05c1e23ed..9a0aafbdf9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -22,6 +22,7 @@ Thunderbird Source Tree Documentation telemetry/index + architecture/index Indices and tables