Chapter 8

The Plug-In Application Programming Interface (API)


CONTENTS


Introduction

In order to maintain similarity across multiple platforms, the Windows plug-in Application Programming Interface (API) is not built in the usual Windows fashion. A Netscape Navigator plug-in is implemented in a dynamically linked code module. In Windows, this module is the standard dynamic link library, or DLL. Microsoft designed the dynamic link library with an eye toward implementations such as a Netscape plug-in, but Netscape has taken a slightly different approach.

This chapter explains the difference between a Netscape API and a plug-in API. Implementations are included for both types of APIs and how code is called. Additionally, all APIs (including platform-specific) are briefly explained. More detailed documentation is continued throughout the next chapters.

Who Is Calling Whom?

If you scan through the plug-in documentation, you might notice that there are two types of APIs. The first type begins with the convention NPP_. These routines are implemented by your plug-in and are called from the Navigator. The letters NPP stand for Netscape Plug-in: Plug-in Defined. The second type begins with the convention NPN_. These routines are implemented by the Navigator and are called from your plug-in. The letters NPN stand for Netscape Plug-in: Navigator Defined. Figure 8.1 shows the calling direction for NPN_ and NPP_ plug-in APIs.

Figure 8.1 : API Calling techniques.

Dynamically Loaded

All plug-in types-whether they are UNIX, Macintosh, or Windows 3.1/95/NT-are dynamically loaded code modules. As explained previously in this book, this architecture has been proven over the years as an effective technique to save system resources by calling code only on demand. As a Windows developer, you are probably familiar with a Windows dynamically linked library (DLL), and you might have used them in your projects.

Routines are called within a DLL through entry points defined during compile time. An application might implicitly load a DLL by linking to a stub library during compile time, or explicitly load a DLL by using a Windows API such as LoadLibrary followed with calls to GetProcAddress to retrieve function addresses.

How Netscape Calls Your DLL

Unfortunately, these linking methods are very specific to Windows and did not fit Netscape's criteria for cross-platform equivalence. If you look at a typical plug-in DLL's header, you'll notice only three entry points:

NP_GETENTRYPOINTS
NP_SHUTDOWN
NP_INITIALIZE

That certainly doesn't give Netscape much to work with-or does it?

NPWIN.CPP

A file is provided by Netscape for Windows developers. It's called NPWIN.CPP and can be found on this book's CD-ROM or via Netscape's plug-in developer's kit. This file contains code for Windows DLL entry points. You might want to review this file before proceeding.

Because NPWIN.CPP is intended as a layer to hide Windows platform-specific entry points from your plug-in, Netscape asks developers not to touch this file. To ensure that this code is not changed, Netscape has mentioned that it might convert NPWIN.CPP to a binary library in the future.

NP_Initialize

Immediately after the plug-in is loaded, the DLL routine NP_Initialize is called. This routine has one parameter, a pointer to an NPNetscapeFuncs structure:

NPError WINAPI NP_EXPORT NP_Initialize (NPNetscapeFuncs* pFuncs)

The NPNetscapeFuncs structure, which is located in the Netscape provided header file npupp.h, is defined in the Navigator 3.0 Plug-in SDK as follows:

typedef struct _NPNetscapeFuncs {
    uint16 size;
    uint16 version;
    NPN_GetURLUPP geturl;
    NPN_PostURLUPP posturl;
    NPN_RequestReadUPP requestread;
    NPN_NewStreamUPP newstream;
    NPN_WriteUPP write;
    NPN_DestroyStreamUPP destroystream;
    NPN_StatusUPP status;
    NPN_UserAgentUPP uagent;
    NPN_MemAllocUPP memalloc;
    NPN_MemFreeUPP memfree;
    NPN_MemFlushUPP memflush;
    NPN_ReloadPluginsUPP reloadplugins;
    NPN_GetJavaEnvUPP getJavaEnv;
    NPN_GetJavaPeerUPP getJavaPeer;
    NPN_GetURLNotifyUPP geturlnotify;
    NPN_PostURLNotifyUPP posturlnotify;
#ifdef XP_UNIX
    NPN_GetValueUPP getvalue;
#endif /* XP_UNIX */
} NPNetscapeFuncs;

The first things to notice are the structure members size and version. The size is simply a sizeof NPNetscapeFuncs. During NP_Initialize, the size is checked against your plug-in's internal NPNetscapeFuncs structure to assure compatibility:

if(pFuncs->size < sizeof NPNetscapeFuncs)
    return NPERR_INVALID_FUNCTABLE_ERROR;

The version is checked in a similar fashion:

if(HIBYTE(pFuncs->version) > NP_VERSION_MAJOR)
     return NPERR_INCOMPATIBLE_VERSION_ERROR;

Note
The version numbers indicated by NP_VERSION_MAJOR and NP_VERSION_MINOR can't be directly correlated to the version of the Navigator. These values refer to the version of the API. When the major version number of the API increases, it is a breaking change. Plug-ins written for version 0 of the API (the current major version number) won't work if the API in the Navigator progresses to major version 1. Minor version changes indicate nonbreaking changes in the API. Thus, the major version number returned by Atlas (Navigator 3.x) continues to be 0, while the minor version is incremented with each change to the API. NP_VERSION_MAJOR and NP_VERSION_MINOR are predefined in the header file, so those numbers indicate the version of the API against which the plug-in was compiled.

Further down in the structure, notice the 12 function pointer prototypes beginning with NPN_. You remember that NPN stands for a routine within the Navigator. This structure holds function pointers to all Navigator entry points that are called by your plug-in. A global pointer to this structure is maintained by your plug-in for future calls to the Navigator:

g_pNavigatorFuncs = pFuncs; // save it for future reference

The NP_Initialize routine ends with a call to your internal NPP_Initialize method, which is documented in Chapter 9, "Instance Initialization and Destruction."

Mapping Your API Calls to Netscape

As your plug-in is running, it makes calls to the Navigator. For instance, a call to allocate memory from the Navigator is NPN_MemAlloc (see Chapter 12, "Memory Management"). NPN_MemAlloc is really a routine within your plug-in. Look again in the file NPWIN.CPP and find the following routine:

void* NPN_MemAlloc(uint32 size)
{
    return g_pNavigatorFuncs->memalloc(size);
}

Notice that this routine simply maps your call to NPN_MemAlloc to the previously mentioned structure of function pointers NPNetscapeFuncs and calls the routine memalloc through the use of the saved pointer, g_pNavigatorFuncs.

NP_GetEntryPoints

After NP_Initialize is called and returns successfully, the DLL entry point routine NP_GetEntryPoints is called. Just as NP_Initialize gives you the means to call Navigator routines, NP_GetEntryPoints allows Netscape to call your plug-in's routines without using standard DLL calling conventions. Look at the prototype for this routine:

NPError WINAPI NP_EXPORT NP_GetEntryPoints (NPPluginFuncs* pFuncs)

As with NP_Initialize, a pointer to a structure is passed. In this case, it's a pointer to the structure NPPluginFuncs, which is currently defined as follows:

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;
} NPPluginFuncs;

Again, the first two members are size and version provided for compatibility checking. In this case, your plug-in only checks the structure size because the version refers to the plug-in:

if (pFuncs->size < sizeof NPPluginFuncs)
    return NPERR_INVALID_FUNCTABLE_ERROR;

Later in the structure, notice the function pointers and prototypes to such routines as NPP_NewUPP newp. The prototype for these routines begins with NPP_, identifying them as calls from the Navigator to your plug-in's methods.

The function pointers in this structure are filled by the plug-in with the appropriate internal routines during NP_GetEntryPoints:

pFuncs->version       = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
pFuncs->newp          = NPP_New;
pFuncs->destroy       = NPP_Destroy;
pFuncs->setwindow     = NPP_SetWindow;
pFuncs->newstream     = NPP_NewStream;
pFuncs->destroystream = NPP_DestroyStream;
pFuncs->asfile        = NPP_StreamAsFile;
pFuncs->writeready    = NPP_WriteReady;
pFuncs->write         = NPP_Write;
pFuncs->print         = NPP_Print;
pFuncs->event         = NULL;       /* reserved */

Versions NP_VERSION_MAJOR and NP_VERSION_MINOR are defined in NPAPI.H and indicate the plug-in API release and point version, respectively.

Netscape Calls Your Code

After NP_GetEntryPoints returns, the Navigator's structure NPPluginFuncs has been filled with valid function pointers that will be directly called as needed. If you are using a compiler other than Microsoft's, you should make sure that your plug-in APIs are prototyped correctly for your compiler. See Part IV of this book, "Plug-In Programming Resources for Windows," for more information.

Because the plug-in is running, you no longer a need to use the standard Windows DLL interface. No other DLL entry points are used until your plug-in is unloaded from memory. At this point, NP_Shutdown is called.

NP_Shutdown

The last of the Windows DLL entry points, NP_Shutdown, is called immediately before the plug-in is unloaded and simply calls your internal NPP_Shutdown routine (see Chapter 9, "Instance Initialization and Destruction"), in addition to zeroing out the global functions pointer:

NPError WINAPI NP_EXPORT NP_Shutdown()
{
    NPP_Shutdown();

    g_pNavigatorFuncs = NULL;

    return NPERR_NO_ERROR;
}

A Quick Look at the Plug-In API Methods

Throughout the next chapters, all plug-in APIs up to the Navigator 3.0 plug-in API are fully documented. Table 8.1 shows plug-in implemented APIs and Table 8.2 shows Netscape implemented APIs.

Table 8.1. The plug-in APIs, which are called from Netscape.
API Name
Description
NPP_Destroy Deletes an instance of a plug-in.
NPP_DestroyStream Called when a data stream is complete.
NPP_GetJavaClass Returns the plug-in associated Java class.
NPP_HandleEvent Macintosh-only event handler.
NPP_Initialize Global initialization.
NPP_New Creates a new instance of a plug-in.
NPP_NewStream Called when a new stream has been created.
NPP_Print Print handler.
NPP_SetWindow Called during plug-ins window activity.
NPP_Shutdown Global termination.
NPP_StreamAsFile Gives the filename for the stream.
NPP_URLNotify Notifies the completion of a URL request.
NPP_Write Called to write data to a plug-in.
NPP_WriteReady Determines whether a plug-in is ready for data.

Table 8.2. The Netscape APIs, which are called from the plug-in.
API Name
Description
NPN_DestroyStream Terminates a data stream.
NPN_GetJavaEnv Returns the Java execution environment.
NPN_GetJavaPeer Returns the plug-in associated Java object.
NPN_GetURL Requests that a new stream be created.
NPN_GetURLNotify Requests that a new stream be created with notification.
NPN_MemAlloc Allocated memory.
NPN_MemFlush Macintosh-only flush memory.
NPN_MemFree Frees memory.
NPN_NewStream Creates a new stream of data.
NPN_PostURL Posts data to a URL.
NPN_PostURLNotify Posts data to a URL and notifies of result.
NPN_RequestRead Requests bytes from a stream.
NPN_Status Displays a status message.
NPN_UserAgent Gets Navigator's user agent field.
NPN_Version Gets the Navigators plug-in version.
NPN_Write Writes to a stream.

Conclusion

In this chapter, you've learned how a plug-in code module fits into the Netscape Navigator in the Windows environment through the use of a dynamic link library. The Application Programming Interface (API) has been reviewed for calls both to and from the plug-in module.

Additionally, you should realize that your Windows DLL is not called in the traditional DLL entry point fashion, but rather through direct function pointers retrieved by the Navigator. Structures to accomplish this are found in the Netscape SDK file NPUPP.H.

Calls from your plug-in to the Navigator, although more straightforward, use the same technique with function pointers.

What's Next?

In Tables 8.1 and 8.2, APIs both to and from your plug-in are defined in alphabetical order and grouped by the types NPP and NPN. The next six chapters fully document all APIs, with each chapter covering a group of APIs based on their purpose. The next chapters cover instance initialization and destroying, stream creation and destruction, reading from and writing to the server, Netscape's memory management, status APIs, LiveConnect, and miscellaneous APIs.