Electrolysis/Accessibility/Windows

From MozillaWiki
< Electrolysis‎ | Accessibility
Revision as of 19:11, 24 March 2016 by Aklotz (talk | contribs) (More content)
Jump to navigation Jump to search

Overview

The main problem with accessibility on e10s is the need for a11y clients to access and manipulate information about web content -- information that will reside inside one or more sandboxed child processes.

The Windows kernel supports Asynchronous Local Procedure Calls (ALPC). ALPC is a scalable, high-performance IPC mechanism [1] that, while undocumented, is available to application software via Microsoft RPC (when using the "ncalrpc" transport). Since COM marshaling is built atop RPC, it is possible for properly configured COM proxies to take advantage of the performance that ALPC offers. Since MSAA is built atop COM, Gecko could configure its COM proxies to gain the benefits of ALPC "for free."

Preliminary Design

A diagram of the proposed COM Proxy implementation for a11y on Windows e10s

Introduction

We start by observing that the non-e10s implementation starts with a WM_GETOBJECT message being received by a Firefox window. The message's reply is an IAccessible pointer.

When the WM_GETOBJECT sender is out-of-process, this IAccessible is implicitly proxied by Microsoft COM. The a11y client is not directly invoking the object's methods. Instead, the methods are being invoked via COM marshaling. Marshaling and IPC occur automatically and transparently to the caller.

This mechanism will also work in the e10s case, but with the IAccessible interface being provided by content processes. Clever management of the proxy objects by the chrome process will make this entire scheme completely transparent to the a11y client: the client does not need to be aware of which process it is communicating with.

Content Proxies

Unlike the chrome case, COM proxies for content processes must be explicitly created. Microsoft COM provides APIs to create proxies and (de)serialize them, however this must be done with care. In order to take advantage of ALPC, the proxy for a content IAccessible must be created on a background thread that has been initialized to run inside the multi-threaded apartment (MTA). A corollary to this is that any interaction with the stub (the server side of the proxy) must also occur on a MTA thread. Instead of calling straight into a11y APIs on the main thread, proxied calls will arrive on the background thread.

To get from the background thread to the main thread, we propose using a simplified IPDL protocol:

  • This protocol's channel shall avoid IPDL deferred message protection for stability and performance reasons;
  • This protocol shall not serialize complex types. Since it is merely doing an in-process hand-off of data between threads, it should just pass pointers whenever possible (note that due to COM, some types may be exceptions to this);
  • This protocol shall match its corresponding COM interface as closely as possible.

Inside Gecko, a serialized COM proxy shall be encapsulated within a ProxyStream object. The ProxyStream class will be a first-class type in IPDL. The PBrowser protocol will be augmented with APIs to asynchronously transmit ProxyStream objects between chrome and content. This will allow the COM proxy to be moved into the chrome process. Once inside the chrome process, ProxyStream will deserialize the proxy and return an interface pointer that may be used in replies to WM_GETOBJECT requests. Since handling WM_GETOBJECT is synchronous, we want the proxied interfaces to be present in the chrome process ahead of time.

[1] Russinovich, Mark et al. Windows Internals 6ed, Part 1. Microsoft Press, 2012