Netscape DevEdge

Skip to: [content] [navigation]



Plug-in Development Overview

Writing Plug-ins

Once you decide what you want your plug-in to do, creating it is a simple process. A basic overview of the plug-in development process is given in the following steps.

1. Plan your plug-in: decide on the services you want the plug-in software to provide and how it will interact with the browser and the special media for which the plug-in is created.
2. Decide the MIME type and file extension for the plug-in
(see "Registering Plug-ins").
3. Set up your development environment properly. You can use a variety of environments to create a plug-in, but make sure that you have the necessary files from the mozilla source or from the plug-in SDK.
4. Create a plug-in project.

You can either start from one of the samples provided for your operating system in the mozilla source directory, where plug-ins samples are already being built, or you can construct a new plug-in project in your own development environment using SDK-provided files. See the README in the plug-in SDK for more information about using the SDK and using the samples provided there.

5. Write your plug-in code and implement the appropriate Plug-in API methods for basic plug-in operation. You'll find an overview of the Plug-in API methods in this chapter, as well as separate chapters for all of the major functional areas of the Plug-in API. Also see "Making Plug-ins Scriptable" for more information about making plug-ins accessible from the browser.
6. Build the plug-in for your operating system. See "Building Plug-ins."
7. Install the plug-in in the plug-in directory for your operating system. See Installing Plug-ins.
8. Test your plug-in and debug as necessary.
9. Create an HTML page and embed the plug-in object. For information about the HTML tags to use, see "Using HTML to Display Plug-ins." To see your plug-in in action, simply display the HTML page that calls it in the browser.

Registering Plug-ins

Netscape Gecko identifies a plug-in by the MIME type it supports. When it needs to display data of a particular MIME type, the browser finds and invokes the plug-in object that supports that type. The data can come from either an EMBED tag in an HTML file (where the OBJECT or EMBED tag either specifies the MIME type directly or references a file of that type), from a separate non-HTML file of that MIME type, or from the server.

The server looks for the MIME type registered by a plug-in, based on the file extension, and starts sending the file to the browser. The browser looks up the media type, and if it finds a plug-in registered to that type, loads the plug-in software.

When it starts up, the browser checks for plug-in modules in the plug-in directory for the platform and registers them. It determines which plug-ins are installed and which types they support through a combination of user preferences that are private to the browser and the contents of the plug-ins directory.

A MIME type is made up of a major type (such as application or image) and a minor type, for example, image/jpeg . If you define a new MIME type for a plug-in, you must register it with IETF (Internet Engineering Task Force). Until your new MIME type is registered, preface its name with "x-", for example, image/x-nwim. For more information about MIME types, see these MIME RFCs:

There are some variations to how plug-ins are handled on different platforms. The following sections describe platform-specific discovery and registration:

MS Windows

On Windows, the plugins directory is located in the same directory as the browser application. Typical installations locate the plugins directory here:

C:\Program Files\Netscape\Netscape 6\Plugins

You can also find this directory through the Registry. The browser does not search subdirectories. Plug-ins must have a 8.3 filename beginning with NP and ending with .DLL.

The Windows version information for the plug-in DLL determines the MIME types, file extensions, file open template, plug-in name, and description. In the MIME types and file extensions strings, multiple types and extensions are separated by the "|" character, for example:


For the browser to recognize the plug-in, the version stamp of the plug-in DLL must contain the following lines:

  • File Extents: for file extensions
  • MIME Type: for MIME types
  • Language: for language in use

In your development environment, make sure your language is set to "US English" and the character set to "Windows Multilingual." The resource code for this language and character set combination is 040904E4.


On Unix, plug-ins are found according to the section How Netscape Gecko Finds Plug-ins. Note that exported function begin with NP while browser called function in the plugin begin with NPP.

To determine the MIME types and file extensions that the plug-in handles, the browser loads each library and calls into the NP_GetMIMEDescription entry point. This exported C function should return a string containing the type, extension list, and type description separated by semicolons. For example: image/xbm;xbm;X Bitmap. This information will then appear in the DOM navigator.mimetypes array which populates about:plugins.

NPP_GetValue is called after the plugin is initilized to get the scripting interface while NP_GetValue is called during initilization to retreive the plug-in's name and description which will appear in the DOM navigator.plugins array which populates about:plugins.

Caution: Gecko caches the values returned by these functions and will only call it if the plug-ins timestamp has changed. See bug 125469.

Mac OS

On the Mac OS platform, the Plug-ins folder is located in the same folder as the browser application. Plug-ins are identified by file type NSPL. When the browser starts up, it searches subfolders of the Plug-ins folder for plug-ins and follows aliases to folders and NSPL files. Plug-in filenames must begin with NP.

The MIME types supported by a plug-in are determined by its resources. 'STR#' 128 should contain a list of MIME types and file extensions in alternating strings. For example:
str 128
String 1
String 2
mov, moov
String 3
String 4
String 5
String 6

Several other optional strings may contain useful information about the plug-in. Plug-ins must support 'STR#' 128 but are not required to support any of these others:

  • STR#' 127 can contain a list of MIME type descriptions corresponding to the types in 'STR#' 128 . For example, this description list corresponds to the types in the previous example: String 1: "QuickTime Video", String 4: "AIFF Audio", and String 5: "JPEG Image Format."
  • STR#' 126: String 1 can contain a descriptive message about the plug-in. This message, which is in HTML format, is displayed by the browser in its "About Plug-ins" page. String 2 can contain the name of the plug-in, thus allowing the name the user sees to be different from the name of the file on disk.


On Mac OSX, if Gecko finds a NP_GetMIMEDescription entry point, it will use the information returned by this function instead of looking in the resources.

Drawing a Plug-in Instance

Before drawing itself on the page, the plug-in must provide information about itself, set the window or other target in which it draws, arrange for redrawing, and handle events.

A windowless plug-in can call the following Netscape methods to draw itself:

The browser calls these Plug-in methods:

The plug-in can call these Netscape methods to query and set information:

For information about these processes, see "Drawing and Event Handling."

Handling Memory

Plug-in developers can take advantage of the memory features provided in the Plug-in API to allocate and free memory.

  • Use the NPN_MemAlloc method to allocate memory from the browser.
  • Use the NPN_MemFree method to free memory allocated with NPN_MemAlloc.
  • Use the NPN_MemFlush method to free memory (Mac OS only) before calling memory-intensive Mac Toolbox calls.

Sending and Receiving Streams

Streams are objects that represent URLs and the data they contain. A stream is associated with a specific instance of a plug-in, but a plug-in can have more than one stream per instance. Streams can be produced by the browser and consumed by a plug-in instance, or produced by an instance and consumed by the browser. Each stream has an associated MIME type identifying the format of the data in the stream.

Streams produced by the browser can be automatically sent to the plug-in instance or requested by the plug-in. The plug-in can select one of these transmission modes:

  • Normal mode: the browser sends the stream data sequentially to the plug-in as the data becomes available.
  • Random-access mode: the browser allows the plug-in to request specific ranges of bytes from anywhere in the stream. This mode requires server support.
  • File mode: the browser saves the data to a local file in cache and passes that file path to the plug-in.

Streams produced by the plug-in to send to the browser are like normal-mode streams produced by the browser, but in reverse. In the browser's normal-mode streams, the browser calls the plug-in to inform it that the stream was created and to push more data. In streams produced by the plug-in, by contrast, the plug-in calls Netscape functions to create a stream, push data into it, and delete it.

Working with URLs

The Plug-in API provides methods that plug-ins can use to retrieve data from or post data to a URL anywhere on the network, provide hyperlinks to other documents, post form data to CGI scripts using HTTP, or upload files to a remote server using FTP.

  • Use NPN_GetURL to request the browser to load a URL into a particular browser window or frame for display, or to deliver the data of that URL to the plug-in instance in a new stream
  • The NPN_GetURLNotify function operates like NPN_GetURL, except that it notifies the plug-in of the result when the operation completes.
  • Use NPN_PostURL to send data to a URL from a memory buffer or file. The result from the server can also be sent to a particular browser window or frame for display, or delivered to the plug-in instance in a new stream.
  • The NPN_PostURLNotify function operates like NPN_PostURL, except that it notifies the plug-in of the result when the operation completes.

For information about using these methods, see "URLs."

Getting Version and UI Information

The Netscape group of Plug-in API methods provides some basic services to the plug-in. You can use these Netscape methods:

  • To identify the browser in which your plug-in is displayed: Use the NPN_UserAgent method to read this information.
  • To determine whether plug-in and the browser versions are compatible and possibly provide alternative processing for different versions: Use the NPN_Version method to check for changes in major and minor version numbers.

For information about using these methods, see "Version, UI, and Status Information."

Displaying Messages on the Status Line

Functionally, your plug-in is seamlessly integrated into the browser and operates as an addition to current browser capabilities. To make the user feel that the plug-in is part of the the browser user interface, your plug-in can emulate the browser behavior by providing status line messages. Use the NPN_Status method to display a message on the status line.

For information about using this method, see "Version, UI, and Status Information."

Making Plug-ins Scriptable

Scriptable plug-ins are plug-ins that have that have been extended to provide methods that can be called from JavaScript and the DOM when accessed through the OBJECT or EMBED tag. Consider the following example, where a media player plug-in can be controlled with an AdvanceToNextSong() method called inside the SCRIPT tag:

<OBJECT id="myPlugin" 
  var thePlugin = document.getElementById('myPlugin');
  if (thePlugin)
    alert("Plugin not installed correctly");

LiveConnect provided this sort of behavior for 4.x NPAPI plug-ins, but Netscape Gecko plug-ins now use XPConnect. Plug-ins that formerly used LiveConnect to make themselves scriptable in 4.x Netscape browsers have lost this possibility in the new XPCOM architecture upon which Netscape Gecko-based browsers are based. This is because there is no longer a guarantee of Java compatibility on a binary level due to the JRI/JNI switch. Plug-ins now use a mechanism called XPConnect to expose Netscape Communicator 4.x plug-ins to JavaScript in the browser interface.

Where LiveConnect was a bridge between Java and JavaScript, XPCOM is a more general framework for making components scriptable from the browser. In order to make plug-ins accessible via XPConnect, however, some changes have been made to the Mozilla code, and there are also some modifications you will have to make to your plug-in code.

For more information about plug-in scriptability-the ability to call native plug-in methods from JavaScript-see:

This article describes the necessary modifications to your plug-in code and provides a sample implementation of NPP_GetValue, one of the APIs that has been updated to provide this scriptability.

Note that from your plug-in you can also call methods on the browser and other DOM objects to which JavaScript provides access. This "bi-directional scriptability" of plug-ins is described in the following article:

Building Plug-ins

Once you have added the special code and additional files to make your plug-in scriptable as described in the previous section, the build process is quite straight-forward. In addition to the DLL that goes in the plugins folder, you must also place a type library and an extra header file in the appropriate places in your application directory. This section describes those extra scriptability steps in more detail.

Building, Platforms, and Compilers

Build resources have been supplied with the SDK for all of the major platforms. There are makefiles for the Unix platform, project files for the Windows and Macintosh IDEs, definition files, resources files, and other resources for building the samples in the SDK and your own plug-in projects. Netscape Gecko plug-ins can also be compiled by well-known compilers on all the major platforms-though using those compilers competently is of course outside the scope of this manual.

All the resources you need-the definition files, the source files, the resource files-can be found in the Plug-in SDK, which is available in the mozilla source tree and also as separately downloadable and buildable software kit. The basic plug-in example, located in the mozilla source at
mozilla/modules/plugin/tools/sdk/samples/basic, has all the files you need to build a simple plug-in on the major platforms.

Building Carbonized Plug-ins for Mac OSX

The building process for Mac OSX plug-ins is very like that forMac "classic" plug-ins and plug-ins on other platforms. There are, however, a couple of differences you must be aware of if you are going to successfully compile your plug-in for the Mac OSX platform.

The main change is visible in the npupp.h header file, where the preprocessor variable _NPP_USE_UPP_ is set to FALSE or 0, because TARGET_API_MAC_CARBON is true:

/* NPP_Initialize */


typedef UniversalProcPtr NPP_InitializeUPP;

enum {
	uppNPP_InitializeProcInfo = kThinkCStackBased

#define NewNPP_InitializeProc(FUNC)		\
		(NPP_InitializeUPP) NewRoutineDescriptor((ProcPtr)(FUNC),
uppNPP_InitializeProcInfo, GetCurrentArchitecture())
#define CallNPP_InitializeProc(FUNC)		\

typedef void (* NP_LOADDS NPP_InitializeUPP)(void);
#define NewNPP_InitializeProc(FUNC)		\
		((NPP_InitializeUPP) (FUNC))
#define CallNPP_InitializeProc(FUNC)		\



When this is the case, all of the function pointers in the NPPluginFuncs struct, also described in the npupp.h header file, will be actual function pointers and not "routine descriptors," which aren't supported in the Carbon runtime:

typedef struct _NPPluginFuncs {
    uint16 size;
    uint16 version;
    NPP_NewUPP newp;
    NPP_DestroyUPP destroy;
    NPP_SetWindowUPP setwindow;
    NPP_NewStreamUPP newstream;
    NPP_DestroyStreamUPP destroystream;
    NPP_StreamAsFileUPP asfile;
    NPP_WriteReadyUPP writeready;
    NPP_WriteUPP write;
    NPP_PrintUPP print;
    NPP_HandleEventUPP event;
    NPP_URLNotifyUPP urlnotify;
    JRIGlobalRef javaClass;
    NPP_GetValueUPP getvalue;
    NPP_SetValueUPP setvalue;
} NPPluginFuncs;


Finally, in the Mac Classic plug-ins, the main entry point is required to be an exported symbol called "mainRD", which is a routine descriptor for the plug-ins main function:

#ifdef XP_MAC
 * Mac platform-specific plugin glue stuff

 * Main entry point of the plugin.
 * This routine will be called when the plugin is loaded. The function
 * tables are passed in and the plugin fills in the NPPluginFuncs table
 * and NPPShutdownUPP for Netscape's use.


typedef UniversalProcPtr NPP_MainEntryUPP;
enum {
	uppNPP_MainEntryProcInfo = kThinkCStackBased
		| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPNetscapeFuncs*)))
		| RESULT_SIZE(SIZE_CODE(sizeof(NPError)))
#define NewNPP_MainEntryProc(FUNC)		\
		(NPP_MainEntryUPP) NewRoutineDescriptor((ProcPtr)(FUNC), 
uppNPP_MainEntryProcInfo, GetCurrentArchitecture())
#define CallNPP_MainEntryProc(FUNC,  netscapeFunc, pluginFunc, shutdownUPP)		\
(ProcInfoType)uppNPP_MainEntryProcInfo, (netscapeFunc), 
(pluginFunc), (shutdownUPP))


However, in the Carbon runtime plug-ins, it's good form if the plug-in exports a "main" entry point, which is expected to have the same prototype. At a bare minimum, the shared library's "main" entry point must be set to such a routine.

Getting and Using the xpidl Compiler

The xpidl compiler that you must use to create the type library and the header file for your plug-in is a regular product of the mozilla build process. In the bin directory of your mozilla build, you ought to see the xpidl binary. Use the -m option to specify which kind of output you want, as in the following usage note.

Usage: ./xpidl [-m mode] [-w] [-v]
          [-I path] [-o basename | -e filename.ext] filename.idl
       -a emit annotations to typelib
       -w turn on warnings (recommended)
       -v verbose mode (NYI)
       -I add entry to start of include path for ``#include "nsIThing.idl"''
       -o use basename (e.g. ``/tmp/nsIThing'') for output
       -e use explicit output filename
       -m specify output mode:
          header        Generate C++ header            (.h)
          typelib       Generate XPConnect typelib     (.xpt)
          doc           Generate HTML documentation    (.html)
          java          Generate Java interface        (.java)


For example, to create a header file for a plug-in IDL file nsITestPlugin.idl, you would type the following at the command prompt:

./xpidl -m header nsITestPlugin.idl

The resulting header file, nsITestPlugin.h, should then be included when the nsTestPlug.dll is built.

Type Libraries

In addition to the header file, you must also create a type library file for your plug-in. This file-in our example, nsITestPlugin.xpt-can also easily be generated from the xpidl compiler, and should be placed in the Plugins subdirectory of the browser application.

The type library is a special binary independent interface file that exposes the interface(s) of an object in a way that allows them to be used uniformly across platforms, languages, and programming environments. The type library provides the information about the interface at run-time, which is required in a cross-platform component framework like XPCOM.

To create a type library file for the nsITestPlugin.idl IDL, you would type the following at the command prompt:

./xpidl -m typelib nsITestPlugin.idl

Installing Plug-ins

With the redesign of the Netscape and Mozilla browsers, there has been a dramatic change to the way that plug-ins and other software are installed. Netscape Gecko now provides a cross-platform installation API that you can use to install new browser components, plug-ins, applications, or any other software.

This API can be used in one of two ways. You can create a small installation script to download and execute a binary installer for the plug-in, as described in the Native Installers below. Or you can do the entire installation using the XPInstall API, which is documented in the XPI Plug-ins Installations section below that.

For more general information about the API, see:

The XPInstall API Reference

Native Installers

Plug-ins must use the XPInstall API to install themselves in the appropriate area. They may also use other binary installers, as before, in which case the XPInstall archive and its installation script are effectively a small wrapper for the installer executable, downloading that binary and executing it on the user's system. The following installation script example gives you some idea of how simple this "wrapper" can be.

// DJ Double-Decker Plug-in Installer
err    = initInstall("
   DJ Double-Decker Plug-in Installer", 

logComment("initInstall() returned: " + err);

err = execute("djdd.exe", "", true);
logComment("execute() returned: " + err);

  err = performInstall(); 
  logComment("performInstall() returned: " + err);


Even with the optional logging (i.e., the logComment() method used after each main step to check the return value of that function), the installation is less than ten lines.

Using an XPInstall script like this to wrap the installer has the additional advantage of running in the same process as the browser, which means that you can invoke the installer executable and hand back control immediately.

initInstall begins every installation script with parameters representing the name and other information about the installation. The next line uses the execute() method (which is a member of the Install object, implicit in installation script just as the window object is implicit in browser scripts) to execute the installer contained within the archive. performInstall() begins the actual installation. Note that you do not have to install the installer in order to execute it on the local system. See the XPInstall API for more information about cross-platform installations, and see the second example below for a more detailed plug-in installation, in which the XPInstall API performs all of the necessary steps to install the plug-in and its supporting files and register it with the browser.

This script is included in a special archive called a XPI. When a separate executable is performing the actual installation, the contents of that XPI may be nothing other than the installer executable and the install.js installation script.

XPI Plug-ins Installations

You can also use the XPInstall API do the installation yourself, without using a third-party installer. The following script works on any platform, and installs the JRE 1.3 plug-in the JRE in the Netscape 6 browser. This sort of script can easily be adapted to install any type of plug-in.

// this function verifies disk space in kilobytes
function verifyDiskSpace(dirPath, spaceRequired)
  var spaceAvailable;

  // Get the available disk space on the given path
  spaceAvailable = fileGetDiskSpaceAvailable(dirPath);

  // Convert the available disk space into kilobytes
  spaceAvailable = parseInt(spaceAvailable / 1024);

  // do the verification
  if(spaceAvailable < spaceRequired)
    logComment("Insufficient disk space: " + dirPath);
    logComment("  required : " + spaceRequired + " K");
    logComment("  available: " + spaceAvailable + " K");



var srDest = 38628;

var err = initInstall("Sun Java 2", "/Sun/Java2", "1.3"); 
logComment("initInstall: " + err);

var fPlugins= getFolder("Plugins");
logComment("plugins folder: " + fPlugins);

if (verifyDiskSpace(fPlugins, srDest))
    err = addDirectory("JRE_Plugin_Linux_i386",
                       "jre-image-i386",   // jar source folder 
                       fPlugins,           // target folder 
                       "java2",            // target subdir 
                       true );             // force flag 

    logComment("addDirectory() returned: " + err);

    // create symlink: plugins/ ->
    //                 plugins/java2/plugin/i386/
    var lnk = fPlugins + "";
    var tgt = fPlugins + "java2/plugin/i386/ns600/";
    var ignoreErr = execute("", tgt + " " + lnk, true);
    logComment("execute "+tgt+" "+lnk+" returned: "+ignoreErr);

    if (err==SUCCESS)
	    err = performInstall(); 
	    logComment("performInstall() returned: " + err);
	    logComment("cancelInstall() returned: " + err);



Note that this script installs the Linux JRE plug-in and assumes you are running Linux, but you can also use the XPInstall API to check the platform type, check for the presence of other files, and perform other preparatory functions in your installation scripts.

Also note the use of the "Plugins" keyword in the getFolder() function to locate and specify the plug-ins subdirectory in a cross-platform way. The returned object, fPlugins, is used as the target folder for installation of this binary file in the addDirectory() function that actually specifies where the files in the XPI are to be installed on the local machine.

Plug-in Installation and the Windows Registry

An important aspect of the installation process on the Windows platform is the reading of registry keys to determine how many Netscape Gecko-based browsers are installed locally, which they are, and how they are configured for plug-ins.

Whether you are using a native Windows installer like InstallShield or writing installation scripts using the XPInstall API (see "XPI Plug-ins Installations"), you can access the registry, read and write data about your plug-in, and customize your installation for the different Netscape Gecko installation targets, as this section describes.

The registry keys that affect the installation of plug-ins are subkeys of the various Netscape Gecko-based products enumerated under:


The products are listed as subkeys of the Mozilla key. You can enumerate these subkeys to get the Netscape Gecko-based browsers, and further enumerate those subkeys to read such important configuration information as where in the browser application directories the plug-in should be installed, which version is installed, and so on.

The Plugins key-value pair shows where plug-ins should be installed for that Netscape Gecko-based product:

Plugins = C:\Program Files\Netscape\Netscape 6\Plugins

For all but the newest Netscape Gecko-based products, the Components key-value pair also holds an important piece of information: As described in the "Type Libraries" section above, Netscape Gecko-based products require that you put the type library file, or XPT, in the Components subdirectory.

Components = C:\Program Files\Netscape\Netscape 6\Components

Also, the product subkey (e.g., Mozilla/Netscape 6 6.2.1) has a bin subkey which exposes the PathToExe key-value pair:

PathToExe = C:\Program Files\Netscape\Netscape 6\netscp6.exe

See the XPInstall registry manipulation example for more information about how these key values from the registry can be used to steer your installation for different targets.

If you are using a native installer, then that installer will have its own way to access and update the registry. If you are using the XPInstall API, then you can use the winReg function to find the plug-in subdirectories where your software should be installed, as the following example demonstrates.

var winreg = getWinRegistry();

var index = 0;
var baseKey = "Software\\Mozilla";

while ( (MozillaVersion = winreg.enumKeys(baseKey,index)) != null )
  logComment("MozillaVersion = " + MozillaVersion);
  subkey = baseKey + "\\" + MozillaVersion + "\\Extensions";
  pluginsDir = winreg.getValueString ( subkey, "Plugins" );
  if ( pluginsDir )
    logComment("pluginsDir = " +  pluginsDir);
    logComment("No plugins dir for " + baseKey + "\\" + MozillaVersion);


When combined with the installation examples above, this kind of parsing of the Windows registry can make it easy for you to install plug-ins on different platforms and browsers.

Netscape Communications