Name Description Size Coverage
components.conf 3333 -
EwsClient.h 536 -
EwsCopyMoveTransaction.cpp 4200 -
EwsCopyMoveTransaction.h A transaction representing an intra-server EWS copy or move operation. 3223 -
EwsFetchMsgsToOffline.cpp Helper class for EwsFetchMsgsToOffline(). It calls IEwsClient.GetMessage() to download each message in turn, passing itself as a listener. As the message data arrives, it is written to the local message store. When each message completes (see OnFetchStop()), it will update the message database to set `.storeToken`, `.offlineMessageSize` and the `Offline` message flag. If there are remaining messages to download, the next one will then be started. If there are no more messages or if an error occurs, the onDone function will be called and the async operation will finish. 7535 -
EwsFetchMsgsToOffline.h Asynchronously download the given messages, write them to the local messageStore, update db to set storeToken/offlineMessageSize etc... When all messages are successfully downloaded: - onDone() will be invoked with NS_OK. If an error occurs while downloading a message: - onDone() will be invoked with the failure code. - no more messages will be downloaded. If the call to EwsFetchMsgsToOffline() returns an error code, no async operation will be started and onDone() will _not_ be invoked. If the call to EwsFetchMsgsToOffline() succeeds, it will return NS_OK and the async operation will be started. If the async operation is started, onDone() will _always_ be invoked when it completes, with the resultant status. NOTE: writes to mbox stores can be preempted - this is where something starts writing a message when a write is already ongoing. When this happens, the old write will be failed (and rolled back) and the new write will be allowed. If that happens while this function is running, it'll manifest itself as a failure code passed out to onDone(), most likely NS_BASE_STREAM_CLOSED. 1874 -
EwsFolder.cpp 68004 -
EwsFolder.h Create a new local folder with the given EWS ID and name under the given parent. 8257 -
EwsFolderCopyHandler.cpp 6538 -
EwsFolderCopyHandler.h A handler for a single folder copy/move operation. An instance of `FolderCopyHandler` is created for each copy/move operation. A single operation always targets a single folder, but includes its subfolders, meaning we might end up copying or moving multiple folders. The current process of copying or moving a folder is the following (assuming no failure): 1. A consumer requests a folder to be copied to an EWS folder (`EwsFolder::CopyFolder()`). 2. The EWS folder class instantiates a copy handler, and instructs it to start the operation (`FolderCopyHandler::CopyNextFolder()`). 3. The copy handler instructs its EWS client to begin creating a folder with the current source folder's name on the server, underneath its logical parent in the destination folder's hierarchy (`IEwsClient::CreateFolder()`). It is called with an instance of `FolderCreateCopyCallbacks`. 4. Once the folder has been created on the EWS server, the EWS client instructs its callbacks instance to create the new folder locally (`FolderCreateCopyCallbacks::OnSuccess()`). 5. The callbacks instance notifies the copy handler of the operation's success (`FolderCopyHandler::OnFolderCreateFinished()`). 6. The copy handler iterates over all the subfolders in the source folders, and adds them to the end of the list of folders to copy. 7. The copy handler builds a list of all the messages in the source folder (non-recursively). If there are messages in this list, it instructs the newly-created folder to start copying them from the source folder (`EwsFolder::CopyMessages()`). It is called with an instance of `MessageCopyListener`. If there are no messages to copy, it skips straight to step 9. 8. The new folder notifies the listener when all the messages have been copied (`MessageCopyListener::OnStopCopy()`). 9. `FolderCopyHandler::CopyNextFolder()` is called. If there are more folders to copy, the copy handler moves to the next folder in the list and starts the process again from step 3. Otherwise the operation stops there. 5682 -
EwsIncomingServer.cpp Creates a new folder with the specified parent, name, and flags. If a folder with the specified EWS ID already exists, then succeed without creating the folder, assuming the folder has already been created locally and we are processing the corresponding EWS message. If a folder with the same name, but a different EWS ID exists, then return an error. 33083 -
EwsIncomingServer.h Locally creates a folder with the given properties. Intended to be called by a friend class such as `FolderSyncListener`. 3820 -
EwsLanguageInteropFactory.cpp 734 -
EwsLanguageInteropFactory.h Factory implementation for creating instances of EWS interfaces to span language boundaries. 821 -
EwsListeners.cpp 5429 -
EwsListeners.h A listener for "simple" EWS operations, i.e. operations that only need to report a success to the consumer. When the operation succeeds, the lambda function passed to this class's constructor is called, with an array containing changed/new EWS identifier(s), as well as a boolean indicating whether a resync of the relevant entity (folder list, message list, etc) is required. 11941 -
EwsMessageChannel.cpp nsIChannel/nsIRequest impl for EwsOfflineMessageChannel 12159 -
EwsMessageChannel.h A channel for streaming an EWS message out of the relevant message store. The message URI is expected to use the form: x-moz-ews://{user}@{server}/{Path/To/Folder}/{MessageKey} Note that no specific encoding is applied to the folder path (besides the standard URL path encoding). Translating this URI into a message header (which we can use to stream the message's content from the message store) is done through calling `EwsService::MessageURIToMsgHdr`. Design considerations on the form of "x-moz-ews" URIs: it includes the message key in the path to follow RESTful semantics. The message is the resource the URI is pointing to, "located" to the path preceding its key (i.e. the path to the folder). Some alternatives that were considered are: * Setting the key as a query parameter, however we seem to use query parameters to control how the message is fetched and/or rendered/streamed, not which message the operation is about, so it would be inconsistent with the rest of the code. * Following the lead of `[protocol]-message` URIs, with the message key located in the "ref" part of the URI. However, this does not work well for displaying messages, as the DocShell does not take this part of the URI into account to decide whether it matches with a document that's already currently rendered (so it doesn't need to render it again); this would lead to every message in a folder being considered the same document. 4265 -
EwsMessageCopyHandler.cpp 13650 -
EwsMessageCopyHandler.h A handler for a single message copy/move operation, the source for which can be either a file or a folder. An instance of `MessageCopyHandler` is created for each copy/move operation, but a single copy/move operation can target multiple messages. It iterates over each message in the queue sequentially and 1. streams it from the relevant message service 2. creates a new item on the server for the message 3. creates a local copy of the message 4. triggers step 1 for the next message (if there is one) The current process of copying or moving a message from a folder is the following (assuming no failures, and excepting signaling start/stop/progress updates to the source folder and the copy listener): 1. A consumer requests an array of messages to be copied to an EWS folder (`EwsFolder::CopyMessages()`). 2. The EWS folder class instantiates a copy handler, and instructs it to start the operation (`MessageCopyHandler::StartCopyingNextMessage()`). 3. The copy handler instructs the message service relevant to the first message in line to stream said message's content to the handler (`nsIMsgMessageService::CopyMessage()`). 4. Once the full message content has been streamed, the message service then signals to the copy handler that it has finished streaming the message's content (`MessageCopyHandler::EndCopy()`). 5. The copy handler instructs its EWS client to begin creating an item for the message on the EWS server (`IEwsClient::CreateMessage()`). It is called with an instance of `MessageCreateCallbacks`, which performs database operations and notifies the copy handler about the operation's progress. 6. Once the item has been created on the EWS server, the EWS client instructs its callbacks instance to save the message's content to the relevant local database and message store (`MessageCreateCallbacks::OnRemoteCreateSuccessful()`). 7. The EWS client then notifies the copy handler (through its callbacks) that the new message has been successfully created, both on the EWS server and locally (`MessageCopyHandler::OnCreateFinished()`). 8. If the operation is a move, the copy handler deletes the source message on the source folder. 9. The copy handler repeats this process from steps 3 onwards until every message in the original array has been copied or moved. 10. Once the operation has completed, or if there has been a failure during the operation, the copy handler notifies the source folder and the global copy service about the end and final status of the operation (`MessageCopyHandler::OnCopyCompleted()`). When copying from a file, the same process is followed, apart from a few changes: * Step 3 is skipped, as the copy handler already holds a copy of the message's content (in the file). * Step 8 is skipped, as we're always dealing with a copy operation when the source is a file. * Step 9 is skipped, as we're always dealing with a single message when the source is a file. 8880 -
EwsMessageSync.cpp Helper class for orchestrating a message sync operation for an EwsFolder. You can think of it as an object which represents the sync operation as it progresses. It works by asking EwsClient to start a message sync operation. As the operation progresses, EwsClient communicates updates via IEwsMessageSyncListener callbacks. This class implements those callbacks and responds by applying whatever changes need to be made to the local folder, database, whatever. It exists for the duration of the sync operation. This removes most protocol-specific message sync code out of EwsFolder. Architectural aside (potential future directions): While other protocols might employ quite different approaches to synchronising server and local state, the changes such operations need to apply to the folder (and database et al) are actually very generic. So, while the operation implementation is tightly coupled to the protocol, it can be loosely coupled to the folder via protocol-agnostic interfaces. We can use this pattern to strip such operations out of the various folder implementations (nsImapMailFolder et al) leaving a small, shared folder core. The historical folder implementations tend to add all their operation state tracking as member variables of the their folder class. Some folder classes are huge. This vastly complicates the folder code itself and the code flow followed during such operations. Even without going to the logical extreme of sharing a single folder class across all protocols, this pattern could help move complex protocol operations out of folder code and into understandable units, making the code vastly easier to reason with. NOTE: we're using C++ derivation here to implement the IEwsMessageSyncListener callbacks, as opposed to the lambda-based approach used for other EWS operations. Using derivation to implement listener callbacks is often a bad idea: - it exposes implementation details which shouldn't be part of the public class interface. - it often leads to an obfuscated flow of execution (crossing multiple class and source file boundaries). - it gets complicated where multiple operations use the same listener interface, so derived callback implementations have to "demultiplex" and figure out which in context they are being called. The rationale for using derivation here: - All the callback code is in the same source file as the function call which initiates the operation so flow of execution is easier to track. - The class itself is never exposed, being hidden away in this .cpp file. - We need a ref-counted object to hold the ongoing state of the operation (e.g. a list of messages added so far), and the derivation gives us that. - It sidesteps some of the awkwardness and scoping foot-guns around sharing state across multiple Lambda closures. As this code evolves over time, this rationale should be re-evaluated. This message sync code could be radically rewritten and nothing outside this file needs to know. 12615 -
EwsMessageSync.h Starts an EWS message sync operation running upon the given folder. `onStart` is called when the operation successfully starts. `onStop` is called when the operation finishes or fails. It is passed the final result status and a list of messages which have been added to the folder. Even if the operation fails, some messages still may have been added. If this function returns a failure code, the operation has failed to start and neither `onStart` or `onStop` will be called. 1127 -
EwsOAuth2CustomDetails.cpp 5992 -
EwsOAuth2CustomDetails.h Configured OAuth2 connection parameters for EWS/Microsoft Office365. Microsoft exchange exposes a single Tenant connection parameter that is then used in conjunction with the endpoint host (issuer) and a standard URL scheme to construct the authorization and token endpoints. This class enables configuration of the user-facing values and maps those values to the `IOAuth2CustomDetails` interface to provide the standard OAuth2 connection parameter set. All other configured values are passed through the interface verbatim to their corresponding connection parameters. 3001 -
EwsProtocolHandler.cpp 3103 -
EwsProtocolHandler.h 617 -
EwsProtocolInfo.cpp 4382 -
EwsProtocolInfo.h 599 -
EwsService.cpp 12545 -
EwsService.h Retrieves the message at the given URI, downloading it first if requested, then optionally converting it to the desired output format. When fetching a part of a message (e.g. to save an attachment), the URI's query is expected to describe which part to isolate and what the output format should be. This query is processed by the stream converter, and thus will be ignored unless `aConvert` is true. 3332 -
GraphClient.h 557 -
IEwsClient.idl A client for communicating with a Microsoft Exchange server via Exchange Web Services. This interface is intended to provide an abstraction of EWS operations to bridge the foreign function interface between the components of a Thunderbird mail protocol implementation and a single implementation of those EWS ops. With the exception of initialization, all client operations are intended to be asynchronous, with implementations of the callback interfaces used to handle the results of the operations or handle errors. 23144 -
IEwsFolder.idl Specialized interface to folders on an EWS server. 3080 -
IEwsIncomingServer.idl IEwsIncomingServer is intended as a workaround for limitations in the folder lookup service. EWS folders require an EWS client object in order to fetch new messages. The folder itself, however, does not have access to all of the details needed to create such a client. This information is part of the incoming server. Due to depending on the folder lookup service to create new folders, it is not possible to give the folder a direct handle to its associated server, so we are forced to go through XPCOM. 3260 -
IEwsLanguageInteropFactory.idl Interface for constructing XPCOM object parameterized on a value. 609 -
moz.build 1157 -
nsEwsOutgoingServer.h 692 -