Team LiB
Previous Section Next Section

Hack 49. Script Plug-ins

Drive your plug-ins from JavaScript using the new NPAPI features.

Once upon a time, you could script plug-in content from a web page. The web page surrounding the plug-in content could supply HTML user-interface elements (such as form controls) that could be used to drive the behavior of the plug-in content. A common example was a button that stopped an audio track from playing. That functionality was partially lost to Mozilla products when dependency on Java was reduced. This hack describes recent enhancements that have brought back this functionality.

5.7.1. Requirements for Scriptability

To script a plug-in such as Flash or Adobe Acrobat, there are many hurdles to overcome.

The plug-in to be scripted must be built to support two vendor standards: the original NPAPI (Netscape Plug-in API) and the NPAPI Extensions. These are both C programming API specifications of little interest to web developers, except that it is a requirement for scripting that plug-ins implement them. The original NPAPI standard is unreliably located here:

http://devedge.netscape.com/library/manuals/2002/plugin/1.0/

If it's offline as you read this, you can use the WayBackMachine (http://www.waybackmachine.org) to get a copy. The NPAPI Extensions are documented here:

http://www.mozilla.org/projects/plugins/npruntime.html

Once you're sure the plug-in is built correctly, it must be installed and recognized by Firefox [Hack #24] . Web developers also need to know the MIME type of content that is managed by the plug-in.

When constructing a web page that seamlessly supports plug-ins, a web developer should follows these recommendations:

  • Detect plug-in availability with scripts. A page should gracefully degrade if the window.navigator.plugins array indicates the specific plug-in is not available and if the window.navigator.mimeTypes array indicates that no third-party tool exists for the required content.

  • Specify plug-in content with the <object> tag or, at worst, with the legacy <embed> tag. Attributes of this tag are passed to the plug-in and are plug-in-specific.

  • The URL of the plug-in content must come from the same web site as the surrounding page content; otherwise, security hobbles will prevent access.

  • Initial scripting of the plug-in should only be done from an onload event handler or from a callback function if the plug-in provides a mechanism for registering one.

Finally, if the plug-in is implemented as an ActiveX control, you must drop additional security restrictions [Hack #11] .

5.7.2. Scripting Away

To script a plug-in, access the DOM object for each plug-in instance, either with the document.embeds array or by using document.getElementById(). Any good book on scripting web browsers will provide a basic introduction on doing this. The specific properties and methods available per plug-in instance vary according to each plug-in manufacturer. You'll need to consult their documentation for the detail.

The new NPAPI extensions let you do these things from the web pageall possible long ago but only recently replanned and resupported by browser makers:

var plugin = document.embeds[0];
var temp = "something";
function handler = function (  ) { return true; }

plugin.exampleProp = temp;
temp = plugin.exampleProp;
plugin.exampleFunction( );
plugin.exampleHandlerRegistration(handler)

The names used here are illustrative only. All of this code runs in the context of the web page. Actions performed on the plug-in instance are driven from the web page, even when they're performed as separately invoked handlers, as in the last line. Mozilla's JavaScript interpreter is single-threaded, so all browser scripting stops while any of this code runs. That also means that only one attempt to access the plug-in instance can be in progress at any time. If the plug-in is multithreaded, any streaming content will continue to be loaded and played, and will be unaffected by the single-mindedness of the Mozilla JavaScript interpreter thread.

Some plug-ins, particularly the Adobe SVG Viewer and Adobe PDF Reader, contain a full JavaScript interpreter of their own and have the potential to use NPAPI in reverse:

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20000303 Stylable//EN"
   "http://www.w3.org/TR/2000/03/WD-SVG-20000303/DTD/
   svg-20000303-stylable.dtd">
<svg width="500" height="400">  
  <script>[!CDATA[
    var text;
    text = svgDocument.getElementById("example");
    text = text.firstChild.nodeValue;
    svgDocument.browser.window.document.title(text);   // example syntax.
  ]]>
  </script>
  <g>
    <rect x="35" y="145" width="110" height="85" rx="10"/>
    <rect x="40" y="150" width="100" height="75" rx="10"/>
    <text id="example" x="50" y="180">
      Example
    </text>
  </g>
</svg>

In this illustrative code (at the time of this writing, Adobe hasn't said what NPAPI callbacks they'll make available), the SVG plug-in's implementation of JavaScript runs scripts downloaded as part of the plug-in-specific content. By exploiting NPAPI, such script content can also access a browser object, as shown in the emphasized line. The browser object is called in the SVG interpreter's context, not in the browser interpreter's context, but it can still manipulate objects created by the browser.

    Team LiB
    Previous Section Next Section