NPAPI:Pepper: Difference between revisions

26,957 bytes removed ,  26 May 2011
no edit summary
No edit summary
 
(92 intermediate revisions by 8 users not shown)
Line 1: Line 1:
= Status =
Mozilla is not interested in or working on Pepper at this time. See the Chrome [http://code.google.com/p/ppapi/ Pepper pages].
 
Under consideration.
 
== Background ==
 
Over the past few months a number of us have also been discussing some of the issues facing NPAPI as a platform independent browser plugin framework.  First, we feel there are some changes needed to NPAPI to keep up with recent developments in browser technology, such as out of process plugin execution.  Second, while NPAPI provides an extensive framework for writing plugins, many end up relying on operating system or browser platform specific features.  This is especially true of windowed plugins that implement 2D or 3D graphics, where almost the entirety of the plugin may consist of operating system specific graphics or event APIs. Third, both windowed and windowless plugins are difficult to composite with other layers correctly today, making it difficult for a page author to achieve the same look and feel across browsers and operating systems.  This proposal intends to be a starting point for addressing these issues, and consists of four topics.
 
# Giving a clear semantics to NPAPI across browsers that implement plugins in a separate process from the renderer/browser itself.
# Integrating plugin rendering with the browser's compositing process, allowing HTML overlays, etc., to work correctly with plugins.
# Defining events, 2D rasterization, and an initial take on 3D graphics access in a way that is common across operating systems and browsers.
# Determining which plugins are available to a browser without loading the plugin.  Although a much smaller issue, it is currently one of the more platform specific portions of NPAPI and one that lends itself to a relatively simple solution.
 
A somewhat related issue is how to extend NPAPI to provide platform independent access to new hardware or software features such as digital cameras, SD cards, bar code readers, accelerometers, webcams, microphones, etc.  While certainly important, this is deferred to future discussions.
 
== The "Pepper" Platform ==
 
To provide these improvements to NPAPI we propose that the changes below be another platform, called "Pepper", that may be implemented by a browser and requested by a plugin at startup.
 
A plugin may call NPN_GetValue() with the following NPNVariable to query the browser whether it supports the Pepper platform:
 
<pre>
/* TRUE if the browser supports the Pepper platform */
NPNVsupportsPepperBool = xxxx
</pre>
 
Once the plugin finds Pepper to be supported, it calls NPN_SetValue() to tell the browser to use that platform. We're adding a new NPNVariable for this:
 
<pre>
NPNVpluginUsePepperPlatform = yyyy /* TRUE if we should use the Pepper platform */
</pre>
 
=== Getting the Pepper Extension Methods ===
 
A vector of function pointers is used to provide access to Pepper-specific functionality.  This vector, called NPPepperExtensions, currently looks like
 
<pre>
typedef struct _NPPepperExtensions
{
  /* Renderer extension function pointers */
  /* Audio extension function pointers */
  /* ... */
} NPPepperExtensions;
</pre>
 
It is obtained by calling NPN_GetValue with
<pre>
NPNVPepperExtensions
</pre>
 
== Out of process plugins ==
 
The current NPAPI model defines the threading model within one process such that whatever thread invokes NPP_New is the only thread that may invoke NPN_* functions.  Several browsers either currently support or are considering moving NPAPI plugins to a separate process from the renderer process (responsible for rendering a page 's content).  With these processes distinct, we have the following: 
 
<pre>
R = renderer process
Tr = thread in R that causes NPP_New to be invoked
P = plugin process
Tp = thread in P that invokes NPP_New in response to the renderer
</pre>
 
=== Thread model for NPN_* calls ===
We propose that NPN_* calls, with only one exception, can only be made from Tp.  This allows us to maintain an important invariant, namely that if Tp is executing any NPP code, then Tr is blocked.  This eliminates the possibility of simultaneous JavaScript and plugin activities.
 
=== NPN_PluginThreadAsyncCall ===
 
The one exception to NPN_* calls is NPN_PluginThreadAsyncCall.
 
<pre>
void    NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance,
                                            void (*func) (void *),
                                            void *userData);
</pre>
 
The semantics of NPN_PluginThreadAsyncCall remain fundamentally the same, just with respect to P:
* It can be called from any thread in P.
* Invoking it eventually causes an NPP callback on Tp to func, passing userData.
 
We make a couple of other implementation comments that make this more usable and help avoid possible deadlocks:
* If two callbacks are requested by the same thread, they should be invoked in the same order they were requested.
* The implementation of NPN_PluginThreadAsyncCall may not call func directly, even if called on Tp, because we need to guarantee the state of Tr and this risks deadlock.
 
We observe that implementing NPN_PluginThreadAsyncCall this way results in additional call/callback/call latency for NPN_* calls.  We believe this is reasonable to provide a well-defined interaction, but realize we may need to address the efficiency of this mechanism.
 
== Plugins and rendering ==
 
Currently plugins typically display 2D graphics in one of two modes: windowless or windowed.  In the current state of affairs windowless plugins are typically given an RGB surface containing the contents of lower layers and they composite themselves.  This constrains the use of transparency and complicates plugins that are not the top or bottom layer.  Furthermore, basically all access to 3D accelerated graphics are through the latter.  Windowed plugins provide a number of challenges to plugin and browser writers.  First, windowed plugins are essentially given a handle to an operating system native window, from which all interaction by the plugin is completely platform-specific.  Second, native windows make it very difficult for the browser to do CSS overlays, etc.  Third, although NPAPI provides the NPP_HandleEvent API, this is not well-defined with respect to native windowing system events.
 
To these ends we propose, for both 2D and 3D:
* Only windowless plugins should be supported.
* Compositing should be done by outside the plugin itself, which should only produce an RGBA (2D) or a texture (3D).
* No native windowing system events should be delivered to plugins.
 
This proposal is clearer at this moment regarding 2D graphics. We expect we may need to pass some state (2d vs. 3d, hardware vs. raster, etc.) in through other calls and/or with some extensions to the data structures we propose below.
 
=== An Example ===
 
A video game looks abstractly like
<pre>
  ...
  while (true) {
    HandleEvents()
    Simulate(gettimeofday())
    Draw()
  }
  ...
</pre>
 
We propose that we continue to set graphics attributes through the existing NPN_GetValue/NPN_SetValue interfaces with some new variables TBD.
 
There are four APIs that would be involved in supporting this from the browser.
 
=== NPP_SetWindow and Windowless Plugins ===
 
Whereas currently NPP_SetWindow passes both some geometry information and a handle to a native window (for windowed plugins), in our proposal, it only conveys geometry and format information.  For example.
 
<pre>
typedef struct _NPWindow {
  void*    window;  // UNUSED
  uint32_t x;        // Position of plugin top left corner relative to top left
  uint32_t y;        // of renderer page. Y increases going down.
  uint32_t width;    // maximum window size
  uint32_t height;
  NPRect  clipRect; // UNUSED
  void*    ws_info;  // Pixel format of the raster backing store. A NPRasterWindowInfo struct.
  NPWindowType type; // UNUSED
} NPWindow;
</pre>
 
A plugin will request rendering contexts using the following structure.
 
<pre>
typedef struct _NPRenderContext
{
  union {
    struct {
      void* region;
      int32 stride;
    } graphicsRgba;
  } u;
} NPRenderContext;
</pre>
 
We expect to use the term renderer in a more general sense than just graphics, so we present NPAPI with a structure that can be extended as other interfaces are added (e.g., audio, 3D graphics, hardware accelerators).
 
=== The 2D Graphics API ===
 
The 2D graphics API provides the following methods
 
==== Initialization ====
 
<pre>
typedef NPError (*NPInitializeRenderContextPtr)(NPP instance,
                                                NPRenderType type,
                                                NPRenderContext* context);
</pre>
 
Causes the creation of a render context of the specified type for use by the specified instance. At this moment, only 2D rendering contexts are defined. Geometry information will be conveyed to the plugin by subsequent NPP_SetWindow calls.
 
==== Flushing ====
 
<pre>
typedef void (*NPFlushRenderContextCallbackPtr)(NPRenderContext* context,
                                                NPError err,
                                                void* userData);
 
typedef NPError (*NPFlushRenderContextPtr)(NPP instance,
                                          NPRenderContext* context,
                                          NPFlushRenderContextCallbackPtr callback,
                                          void* userData);
</pre>
 
Causes the contents of the region to be presented to the renderer for display. Because the final rendering may be done by another process (the browser), the call is asynchronous. Return from the flush guarantees it is safe to write to the region again, but does not say that the bits have reached the screen. The callback is provided to add this capability. The callback should be invoked once the bits have been displayed to the screen or an error has been detected.
 
The regions to be updated can be narrowed by calls to NPN_InvalidateRect, or we should add a rectangle to the context.
 
==== Destroy ====
 
<pre>
typedef NPError (*NPDestroyRenderContextPtr)(NPP instance,
                                            NPRenderContext* context);
</pre>
 
Causes the context specified to be destroyed.  The memory pointed to by context may be freed and accesses are undefined.
 
=== Getting a Device Context to Draw Into ===
<pre>
  PARAMS (details remain to be worked out, but at least):
    - rectangle plugin will draw into
    - discard bit (don't bother to initialize the memory in that rectangle)
  2D DC:
    - x, y, width, height
    - visible rectangles[] // serve as hints
    - stride (byte/pixel difference between (x,y) and (x,y+1))
    - x, y for byte zero of the buffer
    - void* buffer // size is as requested by PARAMS regardless of visible rectangles.
 
  void NPN_GetDeviceContext(NPP instance, PARAMS, NPDeviceContext** context)
</pre>
 
* Allows the plugin to request that the renderer create a context to draw into and call the plugin back.
* On return, the renderer informs the plugin where it can draw into (in *context).
 
=== Publishing the Context to the Renderer ===
<pre>
  void NPN_PublishDeviceContext(NPP instance, NPDeviceContext* context)
</pre>
 
* The plugin informs the renderer that it has drawn into context and that the renderer may composite from it.
* After this call the plugin may no longer draw into the context (it may be deallocated, etc.)
 
=== Notification a Context was Displayed ===
 
Video players, video games, and other timing sensitive plugins typically adjust their simulation to adapt to the speed at which frames are placed on the screen.  A call from the renderer indicating when the bits from a context have reached the screen is needed.
 
<pre>
  void NPP_DeviceContextDisplayed(NPP instance)
</pre>
 
* The renderer informs the plugin that the last published device context was displayed on the screen.
* For performance we will most likely want to be able to call NPN_GetDeviceContext before the NPP_DeviceContextDisplayed call from the previous NPN_PublishDeviceContext has arrived.
* This API could also perhaps be done through an NPEvent of the appropriate type.
 
=== Optimizations and Legacy APIs ===
 
There are two possible performance opportunities that should be noted.
First, given the threading model we have defined, it may be desirable to allow NPN_GetDeviceContext and NPN_PublishDeviceContext to be called from other plugin threads than Tp.  This would eliminate the need to do the associated NPN_PluginThreadAsyncCall, and avoid the context switch penalties that might be associated.
 
Second, in order to avoid drawing an entire region on the screen when only a small portion is updated, it may be useful for the plugin to use existing APIs to mark only a small region as needing to be updated by the next NPN_PublishDeviceContext.
 
<pre>
  void NPN_InvalidateRect(NPP instance, NPRect* invalidRect)
</pre>
* The plugin informs the renderer that it would like to replace the contents of the specified rectangle.
 
== Event Handling ==
 
Plugins should receive all their events from NPP_HandleEvent.  We believe that standardizing the event types and payloads based on, for example, DOM events, would be sufficient to provide browser and OS independent events.  If not, the goal can be accomplished by possibly extending the set of event types or data on the event structures to convey more information.
 
=== Background ===
 
We will use specifically sized types (int32_t, int16_t, int8_t, etc.) to avoid sizeof(int) and sizeof(wchar) differences between compilers and machine architectures, and have very strict padding and alignment specifications.
 
This specification is version 1.0 of events in Pepper. If future events are added, or additional fields are added to existing events, we'll need a way for the client applications to query (or negotiate) what version of events are supported by the browser. If significant changes are made to the event model, we may need to add additional trusted code to maintain backwards compatibility with existing plugin applications. This applies not only to new fields or changes to the ranges of existing fields, but is also especially important for changes or differences in behaviours across multiple operating systems (for example, are mouse movements reported outside the embedded area while a button is held down and the initial mouse down event occurred within the embedded area) Subsequent versions of Pepper events may need to support gesture & touch based events, such as finger pinching and stretching to support zoom in / zoom out for maps & photo editors.
 
The plugin can use NPN_GetValue() & NPN_SetValue() to query and set future event models. Currently, only version 1.0 model is supported, and it should be safe to assume that version 1.0 model will always be available, and will be the default at startup.
 
==== Additional Items ====
 
There is no timer event, see NPN_ScheduleTimer() and NPN_UnscheduleTimer() for timer support. There is no quit event during application shutdown, see JavaScript's "onunload" There is no resize event; see NPN_SetWindow(), which will be correctly serialized with respect to event order.
 
Currently, we are proposing a platform neutral event for focus gained/lost, and a similar event for minimize/background tab. There is also a proposal for NPAPI to support three new NPN functions: NPN_UnfocusInstance(), NPN_LostFocus(), and NPN_GotFocus(). The NPAPI proposal uses NPN functions in leu of events for a few reasons, two of which are: 1) they didn't want to define what the focus event should be for each OS platform, 2) allow the application to explicitly give up focus. Since PEPPER events are platform neutral, the 1st reason doesn't really apply here. The 2nd reason might be good enough to consider using AKH instead of focus events. The downside is that as more events become NPN_* functions, the event model starts to become an inconsistent mix of traditional events and NPN_* functions. https://wiki.mozilla.org/Plugins:AdvancedKeyHandling
 
==== Pepper NPAPI Event Structures ====
 
It is important that all compilers, on all supported platforms, both trusted and untrusted, preserve structure order, field size, and alignment padding, as these structures might be used as a bit copyable wire format between different processes. These seperate processses could be compiled using different compilers and/or compilier options, while sharing these structures via shared memory. For the definitions below, the byte offset for each field is in square brackets. Unused portions of the event structure should be treated as undefined data.
 
<pre>
enum NPMouseButtons {
  // Each value explicitly set, and must match between trusted & untrusted code.
  NPMouseButton_None    = -1,
  NPMouseButton_Left    = 0,
  NPMouseButton_Middle  = 1,
  NPMouseButton_Right  = 2,
  // End of Pepper event specification version 1.0
  // Additional future mouse button enums go here...
};
 
enum NPEventTypes {
  // Each value explicitly set, and must match between trusted & untrusted code.
  NPEventType_Undefined  = -1,
 
  // events                        relevant union to use in NPEvent
  NPEventType_MouseDown  = 0,  // NPMouseEvent struct
  NPEventType_MouseUp    = 1,  // NPMouseEvent struct
  NPEventType_MouseMove  = 2,  // NPMouseEvent struct
  NPEventType_MouseEnter  = 3,  // NPMouseEvent struct
  NPEventType_MouseLeave  = 4,  // NPMouseEvent struct
  NPEventType_MouseWheel  = 5,  // NPMouseWheelEvent struct
  NPEventType_RawKeyDown  = 6,  // NPKeyEvent struct
  NPEventType_KeyDown    = 7,  // NPKeyEvent struct
  NPEventType_KeyUp      = 8,  // NPKeyEvent struct
  NPEventType_Char        = 9,  // NPCharEvent struct
  NPEventType_Minimize    = 10,  // NPMinimizeEvent struct
  NPEventType_Focus      = 11,  // NPFocusEvent struct
  NPEventType_Device      = 12,  // NPDeviceEvent struct
  // End of Pepper specific event specification version 1.0
  // Additional future Pepper events go here...
};
 
enum NPEventModifiers {
  // Each value explicitly set, and must match between trusted & untrusted code.
  NPEventModifier_ShiftKey        = 1 << 0;    // Does not differentiate between left/right keys
  NPEventModifier_ControlKey      = 1 << 1;    // Does not differentiate between left/right keys
  NPEventModifier_AltKey          = 1 << 2;    // Does not differentiate between left/right keys
  NPEventModifier_MetaKey          = 1 << 3;    // Does not differentiate between left/right keys
  NPEventModifier_IsKeyPad        = 1 << 4;
  NPEventModifier_IsAutoRepeat    = 1 << 5;
  NPEventModifier_LeftButtonDown  = 1 << 6;
  NPEventModifier_MiddleButtonDown = 1 << 7;
  NPEventModifier_RightButtonDown  = 1 << 8;
  // End of Pepper event specification version 1.0
  // Additional future event modifiers go here...
};
 
struct NPKeyEvent {
  // Structure layout must match between trusted & untrusted code.
  uint32_t modifier;            // [0] : NPModifier
  uint32_t normalizedKeyCode;    // [4] : key codes from Chromium's keyboard_codes_posix.h
};
 
struct NPCharacterEvent {
  uint32_t modifier;            // [0] : NPModifier
  uint16_t text[4];              // [4] : 32bit wchar
  uint16_t unmodifiedText[4];    // [8] : 32bit wchar
  // End of Pepper event specification version 1.0
  // Additional future key event fields go here...
};
 
struct NPMouseEvent {
  // Structure layout must match between trusted & untrusted code.
  uint32_t modifier;            // [0] : NPModifier
  int32_t button;                // [4] : NPMouseButtons
  int32_t x;                    // [8] : Relative to upper left corner of embedded area, in units of pixels
  int32_t y;                    // [12]: Relative to upper left corner of embedded area (+y down)
  int32_t clickCount;            // [16]: Number of button clicks
  // End of Pepper event specification version 1.0
  // Additional future mouse event fields go here...
};
 
struct NPMouseWheelEvent {
  // Structure layout must match between trusted & untrusted code.
  uint32_t modifier;            // [0] : NPModifier
  float deltaX;                  // [4] : Positive deltaX indicate scroll left, in scroll wheel units.
  float deltaY;                  // [8] : Positive deltaY indicate scroll up, in scroll wheel units.
                                //        On Windows, one scroll wheel click is a delta of 100.0
  float wheelTicksX;            // [12]: Positive wheelTicksX indicate scroll left.
  float wheelTicksY;            // [16]: Positive wheelTicksY indicate scroll up.
                                //        Wheel ticks can be fractional values on certain devices.
  uint32_t scrollByPage;        // [20]: 0 - scroll by line, 1 - scroll by page
  // End of Pepper event specification version 1.0
  // Additional future mouse wheel event fields go here...
};
 
struct NPDeviceEvent {
  // Structure layout must match between trusted & untrusted code.
  // This is a generic event type that devices (discovered via NPN_SetWindow) may use
  // to deliver events to NPN_HandleEvent().
  // Note: this area is under construction
 
  uint32_t device_uid;          // [0] : unique id of device (comes in on PEPPER NPN_SetWindow)
  uint32_t subtype;              // [4] : device event subtype
  uint8_t generic[0];            // [8] : payload is typecast based on device uid & subtype
};
 
struct NPMinimizeEvent {
  // Structure layout must match between trusted & untrusted code.
  // Minimizing may also include becoming a background/foreground tab.
  int32_t value;                // [0] : New value
                                //        0 = transitioning out of minimized state
                                //        1 = transitioning to a minimized state
  // End of Pepper event specification version 1.0
  // Additional future minimize event fields go here...
};
 
struct NPFocusEvent {
  // Structure layout must match between trusted & untrusted code.
  // The embedded Pepper area is gaining or losing keyboard focus.
  int32_t value;                // [0] : New value
                                //        0 = losing focus
                                //        1 = gaining focus
  // End of Pepper event specification version 1.0
  // Additional future focus event fields go here...
};
 
struct NPEvent {
  // Structure layout must match between trusted & untrusted code.
  int32_t type;                  // [0] : NPEventTypes
  uint32_t size;                // [4] : Size in bytes of _this_ event structure.
  double timeStampSeconds;      // [8] : Time of creation; seconds since epoch.
 
  union {
    // [16]: Info specific to each event type
    NPKeyEvent key;
    NPCharacterEvent character;
    NPMouseEvent mouse;
    NPMouseWheelEvent wheel;
    NPMinimizeEvent minimize;
    NPFocusEvent focus;
    NPDeviceEvent device;
    // End of Pepper event specification version 1.0
    // Additional future event type structures go here...
  };
};
 
Keycodes used by NPKeyEvent.normalizedKeyCode (keyboard_codes_posix.h)
 
enum {
  VKEY_BACK = 0x08,
  VKEY_TAB = 0x09,
  VKEY_CLEAR = 0x0C,
  VKEY_RETURN = 0x0D,
  VKEY_SHIFT = 0x10,
  VKEY_CONTROL = 0x11,
  VKEY_MENU = 0x12,
  VKEY_PAUSE = 0x13,
  VKEY_CAPITAL = 0x14,
  VKEY_KANA = 0x15,
  VKEY_HANGUL = 0x15,
  VKEY_JUNJA = 0x17,
  VKEY_FINAL = 0x18,
  VKEY_HANJA = 0x19,
  VKEY_KANJI = 0x19,
  VKEY_ESCAPE = 0x1B,
  VKEY_CONVERT = 0x1C,
  VKEY_NONCONVERT = 0x1D,
  VKEY_ACCEPT = 0x1E,
  VKEY_MODECHANGE = 0x1F,
  VKEY_SPACE = 0x20,
  VKEY_PRIOR = 0x21,
  VKEY_NEXT = 0x22,
  VKEY_END = 0x23,
  VKEY_HOME = 0x24,
  VKEY_LEFT = 0x25,
  VKEY_UP = 0x26,
  VKEY_RIGHT = 0x27,
  VKEY_DOWN = 0x28,
  VKEY_SELECT = 0x29,
  VKEY_PRINT = 0x2A,
  VKEY_EXECUTE = 0x2B,
  VKEY_SNAPSHOT = 0x2C,
  VKEY_INSERT = 0x2D,
  VKEY_DELETE = 0x2E,
  VKEY_HELP = 0x2F,
  VKEY_0 = 0x30,
  VKEY_1 = 0x31,
  VKEY_2 = 0x32,
  VKEY_3 = 0x33,
  VKEY_4 = 0x34,
  VKEY_5 = 0x35,
  VKEY_6 = 0x36,
  VKEY_7 = 0x37,
  VKEY_8 = 0x38,
  VKEY_9 = 0x39,
  VKEY_A = 0x41,
  VKEY_B = 0x42,
  VKEY_C = 0x43,
  VKEY_D = 0x44,
  VKEY_E = 0x45,
  VKEY_F = 0x46,
  VKEY_G = 0x47,
  VKEY_H = 0x48,
  VKEY_I = 0x49,
  VKEY_J = 0x4A,
  VKEY_K = 0x4B,
  VKEY_L = 0x4C,
  VKEY_M = 0x4D,
  VKEY_N = 0x4E,
  VKEY_O = 0x4F,
  VKEY_P = 0x50,
  VKEY_Q = 0x51,
  VKEY_R = 0x52,
  VKEY_S = 0x53,
  VKEY_T = 0x54,
  VKEY_U = 0x55,
  VKEY_V = 0x56,
  VKEY_W = 0x57,
  VKEY_X = 0x58,
  VKEY_Y = 0x59,
  VKEY_Z = 0x5A,
  VKEY_LWIN = 0x5B,
  VKEY_RWIN = 0x5C,
  VKEY_APPS = 0x5D,
  VKEY_SLEEP = 0x5F,
  VKEY_NUMPAD0 = 0x60,
  VKEY_NUMPAD1 = 0x61,
  VKEY_NUMPAD2 = 0x62,
  VKEY_NUMPAD3 = 0x63,
  VKEY_NUMPAD4 = 0x64,
  VKEY_NUMPAD5 = 0x65,
  VKEY_NUMPAD6 = 0x66,
  VKEY_NUMPAD7 = 0x67,
  VKEY_NUMPAD8 = 0x68,
  VKEY_NUMPAD9 = 0x69,
  VKEY_MULTIPLY = 0x6A,
  VKEY_ADD = 0x6B,
  VKEY_SEPARATOR = 0x6C,
  VKEY_SUBTRACT = 0x6D,
  VKEY_DECIMAL = 0x6E,
  VKEY_DIVIDE = 0x6F,
  VKEY_F1 = 0x70,
  VKEY_F2 = 0x71,
  VKEY_F3 = 0x72,
  VKEY_F4 = 0x73,
  VKEY_F5 = 0x74,
  VKEY_F6 = 0x75,
  VKEY_F7 = 0x76,
  VKEY_F8 = 0x77,
  VKEY_F9 = 0x78,
  VKEY_F10 = 0x79,
  VKEY_F11 = 0x7A,
  VKEY_F12 = 0x7B,
  VKEY_F13 = 0x7C,
  VKEY_F14 = 0x7D,
  VKEY_F15 = 0x7E,
  VKEY_F16 = 0x7F,
  VKEY_F17 = 0x80,
  VKEY_F18 = 0x81,
  VKEY_F19 = 0x82,
  VKEY_F20 = 0x83,
  VKEY_F21 = 0x84,
  VKEY_F22 = 0x85,
  VKEY_F23 = 0x86,
  VKEY_F24 = 0x87,
  VKEY_NUMLOCK = 0x90,
  VKEY_SCROLL = 0x91,
  VKEY_LSHIFT = 0xA0,
  VKEY_RSHIFT = 0xA1,
  VKEY_LCONTROL = 0xA2,
  VKEY_RCONTROL = 0xA3,
  VKEY_LMENU = 0xA4,
  VKEY_RMENU = 0xA5,
  VKEY_BROWSER_BACK = 0xA6,
  VKEY_BROWSER_FORWARD = 0xA7,
  VKEY_BROWSER_REFRESH = 0xA8,
  VKEY_BROWSER_STOP = 0xA9,
  VKEY_BROWSER_SEARCH = 0xAA,
  VKEY_BROWSER_FAVORITES = 0xAB,
  VKEY_BROWSER_HOME = 0xAC,
  VKEY_VOLUME_MUTE = 0xAD,
  VKEY_VOLUME_DOWN = 0xAE,
  VKEY_VOLUME_UP = 0xAF,
  VKEY_MEDIA_NEXT_TRACK = 0xB0,
  VKEY_MEDIA_PREV_TRACK = 0xB1,
  VKEY_MEDIA_STOP = 0xB2,
  VKEY_MEDIA_PLAY_PAUSE = 0xB3,
  VKEY_MEDIA_LAUNCH_MAIL = 0xB4,
  VKEY_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5,
  VKEY_MEDIA_LAUNCH_APP1 = 0xB6,
  VKEY_MEDIA_LAUNCH_APP2 = 0xB7,
  VKEY_OEM_1 = 0xBA,
  VKEY_OEM_PLUS = 0xBB,
  VKEY_OEM_COMMA = 0xBC,
  VKEY_OEM_MINUS = 0xBD,
  VKEY_OEM_PERIOD = 0xBE,
  VKEY_OEM_2 = 0xBF,
  VKEY_OEM_3 = 0xC0,
  VKEY_OEM_4 = 0xDB,
  VKEY_OEM_5 = 0xDC,
  VKEY_OEM_6 = 0xDD,
  VKEY_OEM_7 = 0xDE,
  VKEY_OEM_8 = 0xDF,
  VKEY_OEM_102 = 0xE2,
  VKEY_PROCESSKEY = 0xE5,
  VKEY_PACKET = 0xE7,
  VKEY_ATTN = 0xF6,
  VKEY_CRSEL = 0xF7,
  VKEY_EXSEL = 0xF8,
  VKEY_EREOF = 0xF9,
  VKEY_PLAY = 0xFA,
  VKEY_ZOOM = 0xFB,
  VKEY_NONAME = 0xFC,
  VKEY_PA1 = 0xFD,
  VKEY_OEM_CLEAR = 0xFE,
  VKEY_UNKNOWN = 0
};
</pre>
 
== Plugin Registration ==
 
The current process of determining which plugins are available to the browser typically involves loading various shared libraries and querying them for types and extensions addressed by the plugin.  We propose that more efficient method would be to add a special section to the shared library for the plugin.
 
The section, tentatively named .npapidesc, contains a sequence of strings of the form:
 
<pre>
mimetype:[extension][,extension]*:description;
</pre>
 
This enables browsers to scan the plugins without loading them, which becomes more difficult with out-of-process plugins and sandbox protection.
1,295

edits