Netscape Navigator's plug-in architecture is based on dynamically loaded code modules. These modules reside in a subfolder or directory called PLUGINS that the Navigator reads during its initialization. Each module has a resource that determines which MIME type it can handle. When the Navigator finds this MIME type embedded in a Web page through HTML or as a single file, it loads the appropriate code module.
For embedded plug-ins, the HTML EMBED tag tells Navigator the size of the plug-in's window in a given Web page. This window is created by Navigator on behalf of the plug-in. The plug-in is given a handle to this newly created window for drawing and event processing.
When a plug-in is loaded, an instance of the plug-in is created with a call to the NPP_New API. The plug-in can be loaded multiple times, creating multiple instances. It is very common for a Web page to have more than one instance of a plug-in. Therefore, if your plug-in uses a restricted resource such as an audio card, you must allow for sharing of this resource across multiple plug-in instances.
Data streams are a big part of Netscape's plug-in architecture. Most plug-ins have data pushed from the server for processing, but others might choose to pull it down, perhaps in a random-access fashion. Just as a plug-in can have multiple instances, it can also have multiple streams per instance. The plug-in API also provides for stream instance data.
With the introduction of Netscape Navigator 3.0 comes LiveConnect. LiveConnect extends the plug-in architecture by adding communication between plug-ins, Java applets, and JavaScript. The Java Runtime Interface (JRI) plays an important part in this interface.
As you can see in Figure 6.1, the Navigator 3.x plug-in architecture consists of a plug-in code module, Navigator, Java Applet and Java Runtime Interface (JRI), JavaScript, and HTML. A bare minimum plug-in could go without Java, JavaScript, and HTML. For example, many of this book's examples don't use Java or JavaScript and, if opened directly by the plug-in supported media file, would not use HTML either.
Figure 6.1 : Netscape's Navigator 3.x plug-in architecture.
The core of the plug-in interface is the plug-in Application Programming Interface (API). These APIs are prefixed by NPN_ for methods located within the Navigator and NPP_ for methods in the plug-in. All APIs up to Navigator 3.x are well-documented in upcoming chapters of this book. Using the APIs, the plug-in becomes part of Navigator's code. With the introduction of Netscape Navigator 3.0 came new APIs and LiveConnect. LiveConnect joins plug-ins with Java and JavaScript.
Netscape's LiveConnect enables you to integrate Java, JavaScript, and plug-ins. New plug-in methods for LiveConnect are NPP_GetJavaClass, NPN_GetJavaEnv, and NPN_GetJavaPeer. Chapter 14, "LiveConnect," documents these Java-specific APIs for plug-ins and gives more details on the LiveConnect interface. Also, a LiveConnect example written by Netscape is presented in Chapter 23, "Netscape's LiveConnect Sample."
For the purposes of this chapter, you should understand what LiveConnect does. With LiveConnect you can perform the following tasks:
As you can see, LiveConnect is for extending JavaScript and Java as much as it is for extending plug-ins. If you refer back to Figure 6.1, you can see that there is no direct connection between plug-ins and JavaScript. Any plug-in to JavaScript communication must go through Java.
To learn more about LiveConnect, refer to this book's LiveConnect Plug-in API reference and sample chapters. Also, make sure to get the latest Software Development Kit (SDK) from Netscape and read the documentation. The Netscape SDK has the most up-to-date LiveConnect information.
When the Navigator initializes itself, it checks for installed plug-ins in the PLUGINS subdirectory or folder. Navigator does not load any plug-ins at this time; it just parses out the resource information containing the plug-in's supported MIME types, file extensions, and the name for the file open dialog. At the time of this writing, Macintosh plug-ins allow a user to configure plug-in/MIME type association, while Windows does not. Navigator release 4.0 for Windows is slated to have this feature, according to Netscape sources.
The release of Navigator Beta 4 for Windows contains an updated version of the Help|About Plug-ins menu item. The About Plug-ins feature tells you what plug-in you have installed. Also provided is the full path of each plug-in and its MIME type, its description, its suffixes, and whether it is enabled. Only after Navigator finds a MIME type to which a plug-in is registered is the plug-in loaded into memory and executed. Figure 6.2 shows the Windows Navigator Beta 4 About Plug-ins screen.
Figure 6.2 : Windows Navigator Beta 4 About Plug-ins screen.
It is important to realize that your plug-in can be loaded multiple times, depending on a given Web page. For example, a Web page might contain three audio files of the same type. Navigator then creates three instances of the audio plug-in using the NPP_New API. Each of these instances has its own instance data that is allocated by the plug-in and attached to a Navigator-maintained instance data pointer. Each time Navigator calls one of your plug-in methods, you must dereference the Navigator-provided instance pointer and get access to your instance data. All of the examples in this book show how to do this.
In many cases, your plug-in code can be oblivious to other instances. However, in some cases, a plug-in needs to communicate among its instances. The RealAudio plug-in does this by allowing a Web author to load a console instance to control other instances associated with audio files. You can read more about the RealAudio plug-in in Chapter 5, "Using a Plug-In."
It is important to understand that Navigator creates a window for your plug-in's use. You are provided a handle to this window during a call to the NPP_SetWindow method. The size of this window is determined by the HTML EMBED tag attributes WIDTH and HEIGHT. Relative window position is also determined by the HTML code. Window and event processing differ between UNIX, Windows, and Macintosh.
In Windows and UNIX, a child window is created in the window hierarchy. This child window automatically sees all window events. In the Windows programming environment, you can subclass the Navigator-created window to process any given window event.
The Macintosh environment is a little different. A Macintosh window is shared between the plug-in and the Navigator, which means that your plug-in must only draw in the specified area of this shared window. You must save, set up, and restore the shared drawing environment around any drawing operations. Events are provided to the Macintosh plug-in with the NPP_HandleEvent API.
The big advantage of a Navigator plug-in over a Navigator helper application is its capability to embed itself directly in the Navigator displayed Web page. This feature is similar to how a Java applet provides seamless Web page integration. A plug-in differs from Java in that the plug-in's code is native to the local machine and is installed. A Java applet is downloaded before each use and is platform independent.
A plug-in can run in either embedded, full page, or hidden modes. Of these modes, embedded is used most often because it provides seamless Web page integration. Full page mode allows a plug-in to run by itself, taking the whole Navigator display area. Hidden mode, as the name implies, is for plug-ins that have no visible attributes. An example of a hidden plug-in is the Background MIDI Player found in this book's sample code.
Netscape Navigator plug-ins are built around the concept of client/server data streaming. A stream is a constant flow of data. One of the first implementations of streams was for the UNIX I/O subsystem, which provided a full-duplex, modular connection to a given device driver. As multimedia becomes more prevalent on the home computer, streaming becomes very important to handle data flow for audio and video.
A simple stream can be implemented with a pool of fixed-length buffers. The producer of data continuously fills empty buffers, buffer order is maintained, and data is delivered to the consumer. Such problems as overruns (no more empty buffers) or underruns (no more full buffers) make the life of the stream more complicated.
The Navigator plug-in API provides many methods for managing data
streams both to and from a plug-in. For a stream that sends data
from the Navigator to a plug-in (the most common type of stream),
you can create it with NPP_NewStream,
get data from it with NPP_Write,
and destroy it with NPP_DestroyStream.
A stream that sends data from a plug-in to the Navigator (new
with the Navigator 3.0 plug-in API) uses NPN_NewStream
for creation, NPN_Write to
write data to the stream, and NPN_DestroyStream
to destroy it. Additionally, your plug-in can have multiple incoming
and outgoing streams running concurrently. Read about the streaming
methods in Chapter 10, "Stream Creation
and Destruction," and Chapter 11,
"Reading From and Writing To Streams." Be sure to check
out the code samples in Chapter 17, "A
Streaming Audio Sample," and Chapter 18,
"The Buffer Classes," to see how your plug-in can handle
a real-time data stream from the Navigator.
| Note |
All of the streaming samples in this book operate on single streams. If you are writing a plug-in that handles multiple streams, be sure to add code for multiple stream management. This book's samples relate a single stream to the whole plug-in instance object. A multiple stream plug-in should use a separate stream object to manage each stream. Some of the API code examples in Chapter 10 show this technique, but sample code in Chapters 17 through 23 does not. |
After a plug-in is loaded, for all intents and purposes it is part of the Navigator client. A plug-in is compiled machine code and requires no interpretation, as is required by platform-independent languages such as Java. Being this tightly coupled allows a very high-speed bond to the Navigator client and, in turn, the Web server. Data flows between the plug-in and Navigator in either sequential or seekable streams.
As you'll see in Chapter 10, a plug-in can change the stream type to seekable by setting *stype to NP_SEEK. Setting this mode allows a plug-in to pull data from a server with calls to the NPN_RequestRead method. This technique puts the onus on a plug-in to continuously call Navigator for data buffers and is not considered a true continuously flowing stream. A seekable stream is generally slower than a sequential stream, which is driven by Navigator with calls to the plug-in implemented method NPP_Write. Your plug-in should only use seekable streams when the random access benefits outweigh the performance penalty. Seekable streams also have many other usage problems that you'll find out about in Chapter 10.
When Navigator creates a stream for your plug-in, it is in sequential
mode. In most cases, a sequential type stream is created for each
plug-in instance. Your plug-in is automatically notified by the
NPP_Write API as chunks of
data come across the network. This data flow can come from the
Internet via TCP/IP, a Local Area Network (LAN), a local client
file, or Navigator's file cache. A sequential stream, as the name
implies, is a continuous sequential stream of data true to the
streaming definition. In most cases, this is the preferred stream
type for a plug-in to use.
| Note |
Navigator's cache plays an important role in your plug-in's performance. Netscape Navigator 2.0 has both a memory-based and a disk-based caching system. The caching scheme is based on whole files. If you abort a file download, it is not saved to cache. Both cache sizes are user configurable. Navigator 3.0 introduced LiveCache. LiveCache provides progressive caching, which enables you to continue where you left off if a file download is aborted. LiveCache also enables you to preload content from slow devices such as CD-ROM for fast access and viewing. |
A common problem with plug-ins is that users don't know where to find them. To view a Web page that needs a specific plug-in, the user must have that plug-in installed on his or her local machine. To make it easy for users to install new plug-ins, Navigator provides an assisted installation feature. This is automatically activated when a user displays an HTML page that requires a plug-in that is not currently installed.
When a user hits a Web page that requires a plug-in not found in that user's current plug-in installation, a dialog is automatically opened, allowing the user to select either Plug-in Info or Cancel. If the Plug-in Info button is clicked, Navigator loads a new URL to get the given plug-in. This URL can be specified in the PLUGINSPACE attribute of the EMBED tag (see the next chapter for further documentation). If no PLUGINSPACE attribute is used, Navigator goes to a current plug-in list.
You should download Netscape's Plug-in SDK to use in conjunction with this book. The SDK contains the authoritative and most up-to-date plug-in documentation. This SDK is currently located at the following FTP site:
ftp://ftpXX.netscape.com/pub/navigator/sdk
In this address, ftpXX is any one of Netscape's 20 or so FTP servers.
The Plug-in SDK provides the following benefits:
This chapter discussed Netscape Navigator's plug-in architecture. The block diagram in Figure 6.1 showed Navigator's current plug-in architecture up to Navigator 3.x.
Navigator 3.x introduced a major plug-in enhancement called LiveConnect. LiveConnect allows direct communication between Java, JavaScript, and plug-ins. You should get the current Netscape Navigator Plug-in SDK for the best information on LiveConnect.
Remember that plug-ins are dynamically loaded code modules. A plug-in that is loaded more than once is considered to have multiple instances. Navigator creates a child window in UNIX and MS Windows, but it shares the main window with a Macintosh plug-in.
Try to process your data in a streaming fashion by allowing the Web server to push data to your plug-in with a sequential mode stream.
The next chapter focuses on design issues for your plug-in. Network bandwidth, MIME considerations, HTML attributes, and plug-in types are discussed.