This document provides an overview of the Mac-specific aspects of implementation of Chromium’s plugin hosting. Except where noted, Chromium for Mac uses the same overall architecture as Windows and Linux.
Much of the complexity of the Mac plugin host implementation is in the drawing and event handling discussed below. There are a few specific areas common to all of them, relating to certain platform APIs that would not work correctly without special handling. Use of platform APIs in plugin is discouraged due to this, but some are very common and have no supported NPAPI equivalent, so must be supported.
Because plugins are in their own process, the window layer and activation for windows created by plugins is not correct. To work around this, Chromium uses DYLD_INSERT_LIBRARIES to hook Carbon window creation and activation calls, and swizzling to hook Cocoa window creation and activation calls. Chromium attempts to manage the process activation to match the window activation, so that plugin windows show on top of browser windows.
Full-screen windows are detected as a special case of plugin-opened windows, and cause the browser to request or relinquish full screen mode as appropriate, since this must be done from the foreground process.
There are two event models and four drawing models on the Mac, and Chromium supports all but the oldest of each. The specific details of each implementation are explained below.This event model is no longer support
The Cocoa event model doesn’t provide a window reference to the plugin, so the out-of-process implementation is mostly straightforward. However, there are two wrinkles:
Cocoa event model IME has extremely specific semantics, which did not mesh cleanly with WebKit’s IME at the time the code was written. As a result, plugin IME is handled explicitly in the browser process, with messages sent back and forth through the renderer process. In the future, it might be possible to move that support into Blink itself.
NPN_ConvertPoint requires that browsers be able to map plugin coordinates to screen and window coordinates, so the plugin host is forced to track the location of the browser window. This function is poorly spec’d, however, and it’s unclear how it should behave in the presence of CSS transforms, so the implementation may need to move to one where the query is passed into the renderer and/or browser process, and answered there, instead of window location being tracked by the plugin process.
This drawing model is no longer supported.
CoreGraphics support is straightforward: plugins are provided a graphics port pointing to the shared buffer. Since plugins are only allowed to draw during a draw event in this model, tearing is not an issue.
Unlike Windows, where the page background must be provided to the plugin in order to allow the plugin to composite, CoreGraphics-based drawing preserves transparency data. As a result, transparent plugins on the Mac do not have the same double-buffer and synchronous drawing requirements that they do on Windows.
Since the purpose of the Core Animation model is to provide hardware accelerated drawing, the normal plugin drawing system is bypassed (as with windowed plugins on other platforms). Instead, an IOSurface is shared between the plugin and gpu processes, and the plugin’s CALayer is drawn into that surface using CARenderer. On the gpu side, the contents of the IOSurface are composited into the page using a hardware-accelerated drawing mechanism.
Because the IOSurface approach requires explicit action on the browser side when drawing is necessary, but CARenderer doesn’t provide a way to know when drawing is necessary, drawing is driven by a high-frequency timer on the plugin side. As a result, the invalidating Core Animation model described below was developed as an alternative. Use of the original Core Animation model in Chromium is discouraged.