Plug-Ins Software Functional Specification


    Distribution: COMPANY CONFIDENTIAL

    Project:      Java/Shockwave/Browser
    Issue:        0.10
    Author(s):    Steve Hunt, Rhodri James, Simon Middleton
    Date:         04-Sep-96
    Last Issue:   0.09
	    

Contents.


History

        0.01 SAH 02-Apr-96 Started
        0.02 SAH 07-Jun-96 Revised message formats
        0.03 RMJ 25-Jul-96 Added more messages
        0.04 RMJ 30-Jul-96 Inserted message numbers
        0.05 SJM 14-Aug-96 Altered message blocks for consistency
        0.06 SJM 19-Aug-96 Extended protocol to add stream support
        0.07 SJM 27-Aug-96 Opening bits and version numbers
        0.08 SJM 28-Aug-96 Parameter file tweaks
        0.09 SJM 30-Aug-96 Info on system variables
        0.10 SJM 04-Sep-96 STATUS message
      

Outstanding issues

Overview

The World Wide Web is gradually being extended to offer better support for embedding multimedia data inside Web pages. A well-established mechanism known as "helpers" allows a browser to delegate the display of unsupported data types to other applications. However, the helper app displays this data independently, usually in its own window.

The idea of a "plug-in" is to integrate the display of such data into the WWW browser's own window. A number of proposed HTML extensions are being promoted, such as <APPLET> (by Sun for Java), <EMBED> (by Netscape) and <OBJECT> (by W3C).

Technical background

Netscape for the Mac and Windows supports plug-ins in the form of dynamically loaded code resources (DLLs). On finding data of a type it cannot display itself, the browser seeks a DLL which is capable of handling it. If it finds one, it calls standard entrypoints in the DLL to get it to display the data in the browser's window.

This model does not fit well with RISC OS practices. We do not have a standard scheme for DLLs, and the alternative - using relocatable modules - is not practical for very large playback engines for systems like Java and Director. Therefore it is proposed to implement plug-ins as separate Wimp tasks, with a special message protocol between the browser and the plug-in to permit communication and control.

In order to display the data inside the browser's own window, the plug-in needs to be made responsible for updating a certain portion of the browser's work area. This could be done by the browser instructing the plug-in to redraw parts of the window. However, this approach is rejected because it introduces significant differences between a plug-in and a normal wimp application. Instead, we utilise a new facililty that is being added to the Wimp, whereby windows can be created "inside" a parent window. The Wimp takes care of event distribution to the plug-in, and also ensures that the "child" window is in a fixed position relative to the work-area of the parent - so the plug-in's display area will be scrolled within the browser window if the user manipulates the browser window's scrollbars.

User interface

There is no user interface component to this specification.

Programmer interface

A Plug-in accepts one or more types of data, specified using normal RISC OS filetypes. It is the responsibility of the browser to map MIME types to RISC OS filetypes.

Just as normal RISC OS apps may be "single document" or "multiple document", a plug-in implementor may choose whether to handle multiple items at once or not. Ideally, plug-ins should be able to cope with multiple pieces of data, potentially owned by multiple client applications. However, for ease of implementation it may sometimes be preferred to restrict each instance of a plug-in to displaying one piece of data. In this case, were two such pieces of data to be displayed at once, it would be necessary to invoke the plug-in twice.

Invocation

Having determined the best RISC OS filetype for the data, the browser performs the following sequence of actions:-
  1. Broadcast MESSAGE_PLUGIN_OPEN, passing the filename and filetype of the data, and the parent window information. This message also contains an opaque 32 bit value known as the "browser instance handle". This is a word of significance to the browser, and might be different for each instance a plugin. The plugin must always quotes the correct browser instance handle to the browser in subsequent messages.

  2. If a reply MESSAGE_PLUGIN_OPENING is received, an existing invocation of a suitable plugin has agreed to handle the data. The MESSAGE_PLUGIN_OPENING will contain an opaque word value, known as the "plugin instance handle", which together with the task handle of the plugin task uniquely identifies the piece of data. The browser should remember both of these values for use in future messages.

  3. If no task responds to MESSAGE_PLUGIN_OPENING, the browser should attempt to launch the appropriate plug-in. This is done by calling looking for an environment variable called "Alias$@PlugInType_xxx" where xxx is the hexadecimal type value. If this variable is not found, no suitable plug-in is available, and the browser must regard the attempt to display the data as unsuccessful. If the variable is found, then the browser should launch it by calling Wimp_StartTask.

  4. The result of Wimp_StartTask will be the task handle of the new invocation of the plug-in. As soon as Wimp_StartTask returns, the browser should re-broadcast the MESSAGE_PLUGIN_OPEN message.

  5. Normally, the plugin will accept this message and reply with MESSAGE_PLUGIN_OPENING, containing a plugin instance handle as described above.

  6. If no reply was forthcoming, the browser should assume that for some reason the plugin was unable to load the data, and it should regard the attempt to display this data as unsuccessful. This might be because the data is malformatted, erroneous or of an incompatible version than that expected by the plugin, or it might be because of some unexpected eventuality (out of memory, etc). If a detailed falure message is to be issued to the user, it is the responsibility of the plug-in to do this.

    If further data of the same type needs to be displayed, either simultaneously or sequentially, then the browser should repeat the whole process starting with the broadcast.

  7. If the plugin has replied then the browser will now open a data stream for the initial object being embedded and send this data to the plugin according to the plugin stream protocol.

  8. The plugin examines the contents of the file that was named in the MESSAGE_PLUGIN_OPEN message. This file contains all the information from the <OBJECT>, <EMBED> or <APPLET> tag, and is used by the plugin to initialise itself. Possibly the plugin will have to fetch the contents of more URLs in order to do this; it may get the browser to do this on its behalf by using the URL_ACCESS message.

  9. If during startup the plugin encounters an unrecoverable error it should tidy up after itself and send a MESSAGE_PLUGIN_CLOSED message to the browser, setting a flag in the message to indicate that this is due to an error. The message may optionally include an error message for the browser to display.

Shutdown

When the browser wishes the data to be forgotten, for example when the user quits the browser or leaves the current page, the following actions should be taken. If multiple pieces of data have been farmed out (to the same or multiple plug-ins) the sequence below should be carried out for each such piece of data.
  1. Browser sends MESSAGE_PLUGIN_CLOSE directly to the plug-in task, passing the plugin instance handle associated with the data.

  2. Plug-in closes and deletes its window, cleans up state and data, etc.

  3. Plug-in replies with MESSAGE_PLUGIN_CLOSED.

  4. Plug-in decrements its count of active objects. If the count is zero, it is free to exit if it wishes. A flag in the MESSAGE_PLUGIN_CLOSE acts as a hint to the plug-in as to whether the browser would like the plug-in to remain running or not, but the plug-in does not have to honour this if it does not want to.

Plug-in death

If the browser receives a MESSAGE_TASK_CLOSEDOWN, it should check to see whether the exiting task was a plug-in that was currently displaying data on behalf of the browser. If so, all data being displayed by that plugin must be marked as undisplayable. The Wimp will already have deleted the child window(s) associated with the task. It is up to the browser implementor how to cope with this. It could attempt to re-launch the plug-in, or it could simply issue an error message to the user.

Browser death

If the plugin receives a MESSAGE_TASK_CLOSEDOWN, it should check to see whether it is displaying data on behalf of the exiting task. If so, it should deallocate any state or data associated with that task, and reduce its reference count the correct amount. If the reference count reaches zero (i.e. the dead task was the only task using the plugin), then the plugin may exit if it wants to.

Plug-in data requests

Window events

The Wimp's nested window mechanism handles most of the considerations to do with subwindow positioning automatically. If browser window is closed, then the subwindow will be removed from view by the wimp, and it will be reinstated when the parent window is reopened. If the browser window is scrolled, the Wimp will ensure that the plug-in window stays at the same position relative to the browser's work area, if necessary it will reposition the subwindow and possibly clip it if it has scrolled partly or entirely out of view. Repositioning is done by the wimp sending Open_Window_Request messages to the plug-in as usual; therefore the plug-in should respond to these messages in the usual way (ignoring the fact that it is a child window).

If the plugin receives a keypress or mouse button click that it does not want to handle, it should pass it on to the browser by means of Wimp_SendMessage. It should set the window handle field of the message to the handle of its parent window. Note that this should be used instead of Wimp_ProcessKey.

If the browser wishes to forcibly resize or reposition the subwindow, it should send a MESSAGE_PLUGIN_RESHAPE message to the plug-in, quoting the plug-in instance handle. The plug-in must honour this request by re-opening itself at the new position. The coordinates in this request are work-area coordinates of the parent window. The parent window handle in this message may be different to the original one. The plugin should be prepeared to check for this, and re-create its window as a child of the new parent if necessary.

If the plugin wishes to alter its size, it cannot simply resize its window. Instead it must send a MESSAGE_PLUGIN_RESHAPE_REQUEST to the browser. The browser should respond by reformatting the page (if necessary) and then replying with a suitable MESSAGE_PLUGIN_RESHAPE. The plugin will act on this in the normal way.

Data pointers

Many of the strings passed around in this protocol are of unspecified size and may, especially in the case of URL's, be larger than could fit within the body of a wimp message. Therefore they are defined in this spec as string_values. These are also used in the Browser spec and are defined as being either offsets from the start of the message body (if less than 256) or as pointers to data held in shared memory (ie the RMA or a dynamic area). It is always the responsibility of the sender to free the memory used for any such pointers. The protocol is defined in such a way that there should always be a reply received or the message will be bounced by the wimp. In either case it is then safe for the sender to free the memory allocated.

However to avoid memory leaks it is recommended that careful track is kept of such pointers so that they can be freed when a plugin instance is closed.

Stream protocol

Some plugins may wish the browser to fetch data from the net for them rather than having to implement their own fetching code. A flexible interface is provided for this based, in port, on the API used in the de facto standard plugin API created by Netscape, in order to facilitate porting plugins to the NC.

There are several ways a stream can be instigated, as follows

  1. The browser wishes to transfer the initial data which launched the plugin
  2. The plugin requests some data be fetched for it with URL_ACCESS
  3. The plugin requests some data be posted for it with URL_ACCESS
  4. The plugin wishes to write directly to a browser window
Initial transfer
  1. browser fills in flags, mime type, stream data and sends STREAM_NEW
  2. the plugin returns the same message
    • quoting the reference
    • filling in the plugin stream instance handle
    • updating the stream mode (if necessary)
  3. if mode is applicable
    1. browser sends STREAM_WRITE
    2. plugin replies with STREAM_WRITTEN giving the number of bytes that is could process.
    This is repeated until all data is transferred or an error occurs.
  4. browser sends STREAM_DESTROY with appropriate reason code.
Plugin requests data be fetched or posted
  1. plugin sends the URL_ACCESS message.
  2. when data starts arriving we continue as initial transfer
Plugin write to browser
  1. plugin fills in mime type, target, plugin stream instance and sends STREAM_NEW
  2. the browser returns the same message
    • quoting the reference
    • filling in the stream fields
  3. the plugin writes data

    This is repeated until all data is transferred or an error occurs.

  4. plugin sends STREAM_DESTROY with appropriate reason code.

System variables

For a plugin yyyy whose file type is xxx the variables set should include

yyyy$Dir
the application directory containing !Boot, !Run etc. files
File$Type_xxx
upto 8 character name describing file format
PlugIn$Type_xxx
name of plugin for browser menu
Alias$@RunType_xxx
command to run plugin as a standalone application, takes filename as an argument
Alias$@PlugInType_xxx
command to run plugin as a standalone application, no arguments

For example eg a sample !Boot file might go something like this

  Set Java$Dir <Obey$Dir>
  Set File$Type_AE4 Java
  Set PlugIn$Type_AE4 Java
  SetMacro Alias$@RunType_AE4 /<Java$Dir>.!RunImage -standalone %%*0
  SetMacro Alias$@PlugInType_AE4 /<Java$Dir>.!RunImage -plugin %%*0
      

If a file is embedded with APPLET, EMBED or OBJECT then the Alias$@PlugInType_xxx variable is used to start the application.

If a file is pointer to with an anchor (eg <A HREF="applets/myapplet.class">) then the file will be downloaded and the Alias$@Runtype_xxx variable will be used.

The OBJECT tag

Note that plugins should be able to be launched from an OBJECT tag as well as EMBED or APPLET. When this happens there are some minor differences to the values in the parameter file.

For EMBED

  1. The SRC attribute will instead be named DATA

For APPLET

  1. The ALT attribute will be named STANDBY.
  2. The CODE attribute will be named CLASSID.
  3. The value of CLASSID will not have the .class suffix
  4. The value of CLASSID may have a prefix java:

Standards

Plug-ins may support the Wimp Help protocol. Messages should be limited to at most 40 characters.

Data interchange

The following new Wimp messages are defined:-

MESSAGE_PLUGIN_OPEN (&4D540)

Sent by the browser to create a plugin instance.

    R1+16   Message_PlugIn_Open
	    Common fields
    R1+20    Flags (reserved, must be zero)
    R1+24    reserved
    R1+28    Browser instance handle (invented by the browser)
    R1+32   Parent window handle
    R1+36   Left     (bounding box in parent's
    R1+40   Bottom    work area co-ordinates)
    R1+44   Right
    R1+48   Top
    R1+52   File type
    R1+56   File name (string_value)
	

The file specified by "Filename" contains a series of parameters in the form of name-value pairs. This data is the list of attributes and parameters from the APPLET, OBJECT or EMBED tag - see their respective definitions. This data is used by the plugin to understand what is being requested of it - see Data formats for details.

MESSAGE_PLUGIN_OPENING (&4D541)

Sent by the plugin task to say an instance has been created.

    R1+12   my_ref field from Message_PlugIn_Open
    R1+16   Message_PlugIn_Opening
	    Common fields
    R1+20    Flags
	     Bit 0: 1 = plugin can accept input focus
		    0 = plugin cannot use input focus
	     Bit 1: 1 = plugin wants code resource fetched
		    0 = plugin will fetch code resource itself
	     Bit 2: 1 = plugin wants data resource fetched
		    0 = plugin will data code resource itself
	     Bit 3: 1 = plugin will delete the parameter file itself
		    0 = parent should delete parameter file now
    R1+24    Plugin instance handle (invented by the plugin)
    R1+28    Browser instance handle (copied from Message_PlugIn_Open)
	

MESSAGE_PLUGIN_CLOSE (&4D542)

    R1+16   Message_PlugIn_Close
	    Common fields
    R1+20    Flags
              Bit 0: Browser would also like plugin to exit
              Other bits reserved, must be zero.
    R1+24    Plugin instance handle to close
    R1+28    Browser instance handle

	

MESSAGE_PLUGIN_CLOSED (&4D543)

    R1+12   my_ref field from Message_PlugIn_Close
    R1+16   Message_PlugIn_Closed
	    Common fields
    R1+20    Flags
              Bit 0: Plugin will exit after this message
              Bit 1: This message is NOT in reply to a
                     Message_PlugIn_Close.
              Bit 2: Set if there is an error message at R1+32
              Other bits reserved, must be zero.
    R1+24    Plugin instance handle of the closed instance
    R1+28    Browser instance handle of the closed instance

            If flags bit 2 is set:
    R1+32   Error number.
    R1+36   Zero-terminated message to be displayed by the browser.
	    (NB This message is always embedded here as the plugin 
             may be exiting).
	

MESSAGE_PLUGIN_RESHAPE (&4D544)

    R1+12   my_ref field from Message_PlugIn_Request (if applicable)
    R1+16   Message_PlugIn_Reshape
	    Common fields
    R1+20    Flags (reserved, must be zero)
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
    R1+32   Parent window handle
    R1+36   Left     (bounding box in parent's
    R1+40   Bottom    work area co-ordinates)
    R1+44   Right
    R1+48   Top
	

MESSAGE_PLUGIN_RESHAPE_REQUEST (&4D545)

    R1+16   Message_PlugIn_Reshape_Request
	    Common fields
    R1+20    Flags (reserved, must be zero)
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
    R1+32   Width   (in OS units)
    R1+36   Height
	

MESSAGE_PLUGIN_FOCUS (&4D546)

    R1+16   Message_Plugin_Focus
	    Common fields
    R1+20    Flags (reserved, must be zero)
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
	

This message is used to transfer the input focus between a plugin and its parent. It can be sent in either direction. If the recipient cannot or does not wish to accept the focus then it just ignores the message. Otherwise it should acknowledge the message with message type 19 to prevent it being bounced back to the originator.

MESSAGE_PLUGIN_UNLOCK (&4D547)

    R1+16   Message_Plugin_Unlock
	    Common fields
    R1+20    Flags (reserved, must be zero)
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
    R1+32   URL for which to unlock the cache file (string_value)
	

MESSAGE_PLUGIN_STREAM_NEW (&4D548)

    R1+16   Message_Plugin_StreamNew
	    Common fields
    R1+20    Flags
	     Bits 0-3: stream type field
		= 0: normal
		= 1: seek only
		= 2: as file
		= 3: as file only
	     Bit 4: 1 = stream is seekable
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
            Common stream fields
    R1+32    Plugin stream instance handle
    R1+36    Browser stream instance handle 
    R1+40    URL of stream source/dest (string_value)
    R1+44    end of stream in bytes, or 0 if unknown
    R1+48    last modified data of URL
    R1+52    notify data
    R1+56   mime type of URL (string_value)
    R1+60   window target (string_value)
	

MESSAGE_PLUGIN_STREAM_DESTROY (&4D549)

    R1+16   Message_Plugin_StreamDestroy
	    Common fields
    R1+20    Flags (reserved, must be zero)
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
            Common stream fields
    R1+32    Plugin stream instance handle
    R1+36    Browser stream instance handle 
    R1+40    URL of stream source/dest (string_value)
    R1+44    end of stream in bytes, or 0 if unknown
    R1+48    last modified data of URL
    R1+52    notify data
    R1+56   Reason
	

MESSAGE_PLUGIN_STREAM_WRITE (&4D54A)

    R1+16   Message_Plugin_StreamWrite
	    Common fields
    R1+20    Flags
	     Bits 0-3: Data type field
		= 0: string_value
		= 1: anchor
		= 2: file handle
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
            Common stream fields
    R1+32    Plugin stream instance handle
    R1+36    Browser stream instance handle 
    R1+40    URL of stream source/dest (string_value)
    R1+44    end of stream in bytes, or 0 if unknown
    R1+48    last modified data of URL
    R1+52    notify data
    R1+56   Logical offset in stream of data
    R1+60   Length of data
    R1+64   Data ptr 
	

MESSAGE_PLUGIN_STREAM_WRITTEN (&4D54B)

    R1+12   my_ref field from Message_PlugIn_StreamWrite
    R1+16   Message_Plugin_StreamWritten
	    Common fields
    R1+20    Flags (reserved, must be zero)
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
            Common stream fields
    R1+32    Plugin stream instance handle
    R1+36    Browser stream instance handle 
    R1+40    URL of stream source/dest (string_value)
    R1+44    end of stream in bytes, or 0 if unknown
    R1+48    last modified data of URL
    R1+52    notify data
    R1+56   Length of data consumed, < 0 if error
	

MESSAGE_PLUGIN_STREAM_AS_FILE (&4D54C)

    R1+16   Message_Plugin_StreamAsFile
	    Common fields
    R1+20    Flags (reserved, must be zero)
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
            Common stream fields
    R1+32    Plugin stream instance handle
    R1+36    Browser stream instance handle 
    R1+40    URL of stream source/dest (string_value)
    R1+44    end of stream in bytes, or 0 if unknown
    R1+48    last modified data of URL
    R1+52    notify data
    R1+56   file name of stream data (string_value)
	

MESSAGE_PLUGIN_URL_ACCESS (&4D54CD)

    R1+16   Message_Plugin_URLAccess
	    Common fields
    R1+20    Flags
	     Bit 0: 1 = return a NOTIFY message on completion
	     Bit 1: 1 = POST to the URL
		    0 = GET from the URL
             If bit 1 = 1
             Bit 2: 1 = POST a file
                    0 = POST a block of memory
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
    R1+32    URL to access (string_value)
    R1+36    window target (string_value)
    R1+40    notify data to be returned
    R1+44    length of data to be posted
	    If bit 2=1
    R1+48    file name (string_value)
            If bit 2=0
    R1+48    ptr to data (string_value)
	

If the window target is non-null then the url is fetched to the given window name. Otherwise a stream is opened and data is sent to the plugin.

MESSAGE_PLUGIN_URL_NOTIFY (&4D54CE)

    R1+16   Message_Plugin_URLNotify
	    Common fields
    R1+20    Flags (reserved)
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
    R1+32   URL accessed (string_value)
    R1+36   reason for notify
    R1+40   notify data
	

MESSAGE_PLUGIN_STATUS (&4D54CF)

    R1+16   Message_Plugin_Status
	    Common fields
    R1+20    Flags (reserved)
    R1+24    Plugin instance handle
    R1+28    Browser instance handle
    R1+32   status message (string_value)
	

Requests that the parent display some information in its status bar or similar. The message should be reasonably short.


Data formats

The MESSAGE_PLUGIN_OPEN contains a filename that refers to a file of parameters and attributes. The plugin uses this information to locate the correct data, classes, implementation etc.

The file contains the concatenation of one or more binary records of the form:-

 4 bytes   type:
           0 = terminator (this is the last word in the file)
           1 = data from PARAM
           2 = URL from PARAM
           3 = object ref PARAM
           4 = special parameter from browser
	   5 = data from OBJECT/APPLET
	   6 = URL from OBJECT/APPLET

 4 bytes   m = size of record (without header) (4+n+p) + (4+s+q) + (4+t+r)

 4 bytes   n = size of name (unpadded)
 n bytes   Name
 p bytes   Padding to word boundary

 4 bytes   s = size of data (unpadded)
 s bytes   Data
 q bytes   Padding to word boundary

 4 bytes   t = size of mime type (unpadded)
 t bytes   Mime type
 r bytes   Padding to word boundary
	

Integers are stored in little-endian order.

Flags (parameters with void value whose presence or absence only is significant) are represented by a parameter of type DATA with zero length.

The parameters include:-

These parameters are passed exactly as seen in the HTML without any conversions. The data/url/ref distinction is as given in the DTD (for OBJECT attributes) or in the VALUETYPE attribute of the PARAM element.

See Browser specifications for a list of possible parameters. The plug-in may implement its own URL fetching code, or it may have the Browser fetch URLs on its behalf by issuing a URL_ACCESS message to the browser.

Special parameters are created by the browser (rather than being part of the object element). They are:-

BASEHREF
The full URL of the document containing this object.
USERAGENT
The name of the browser.
UAVERSION
Version number of the browser (user agent) in format x.y. If the plugin needs a specific browser feature it may refuse to initialise if this version is not high enough.
APIVERSION
Version number of this API in format x.y. Changes in x mean a major incompatible change in formats. If the plugin doesn't understand this version it should refuse to initialise. Changes in y mean some new functionality introduced in a backwards compatible way.

API Versions

Released versions of this API that plugins should know about are listed below, with the most recent version at the top.

Version 1.0
As per this spec.

External dependencies

This specification relies on the existence of a Wimp with nested window support.

Acceptance test

The protocol shall be able to cater for the needs of Shockwave and Java plug-ins.

Development test strategy

Product organisation

N/A

Future enhancements

Last modified: Wed Sep 4 15:58:50 BST