Chapter 10

The Plug-In Architecture


CONTENTS


The team needed to build an effective Web site includes the site designers, HTML writers, and, sometimes, plug-in programmers. This chapter describes the use of plug-ins by Web site designers. As a plug-in programmer, you can use this information to improve your plug-ins and make them integrate better into Web pages.

As you read in Chapter 9, "Understanding Plug-Ins," the Web site designer has many options. He or she can use static HTML, programs on the server (such as CGI and server-side JavaScript), and programs on the client (including Java applets, client-side JavaScript, and plug-ins). With LiveConnect, the designer can integrate all of the client-side techniques to give the user a seamless experience.

This chapter shows how to select and design plug-ins for your Web site. Chapter 11, "Step-by-Step Through the NPP Methods," describes the code you, as the plug-in programmer, must write to implement your plug-in. Chapter 12, "Calling Navigator with NPN Methods," discusses the resources Netscape has provided to allow you to delegate some tasks back to Navigator. Then Chapter 13, "Analysis of a Simple Plug-In," describes a real plug-in at the code level.

As a plug-in programmer, you may also want to read Part V, "LiveConnect," to understand how Netscape integrates Java, JavaScript, and plug-ins.

Getting Started with Plug-Ins

This section introduces three ways of starting a plug-in: embedded, hidden, and full-page. It then moves into a high-level look at plug-in design. The chapter points out patterns that are associated with the plug-in architectures.

Note
When process definitions are presented with context, rationale, and examples, they are known as patterns. The most complete explanation of patterns are given by a team of authors known as the "Gang of Four."
In his 1991 doctoral theses at the University of Zurich Institute fur Informatik, Erich Gamma seized on the concept of patterns and brought them to the software engineering community. Gamma, along with Richard Help, Ralph Johnson, and John Vlissides, later authored Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley, 1995). Collectively, these authors are called the "Gang of Four."
From time to time, this chapter points out patterns that are common in plug-ins. If you're using patterns in your design work, these pointers may be useful. If you haven't started using patterns yet, feel free to ignore these references.

Three Ways of Invoking a Plug-In

Plug-ins fit into HTML in three different ways: embedded, hidden, or full-page. Although these terms are sometimes used as though they are types of plug-ins, they actually are just ways of calling the plug-in. However, there are coding differences. If you design an embedded plug-in (a plug-in that is invoked using the <EMBED> tag), have the plug-in check to see how it was invoked. Should the user incorrectly invoke the plug-in, have the plug-in put up a dialog box describing the correct usage. The HTML author will see this warning when he or she tests the page, so the warning should give the HTML writer enough information to fix the problem before the page actually goes into service with end users.

Embedded Plug-Ins  Netscape has added the <EMBED> tag to the set of extensions recognized by Navigator. The <EMBED> tag includes the SRC attribute, so an HTML writer can write the following line and the browser attempts to get the requested entity:

<EMBED SRC="http://www.some-server.com/aMovie.avi">

As described in Chapter 9, "Understanding Plug-Ins," the server uses the file extension (.avi) to select a MIME content type. When the server sends the Content-type header line back to the browser, Navigator selects the plug-in that handles this media type.

The HTML writer can also use the TYPE attribute of the <EMBED> tag to force Navigator to look for a plug-in to handle the specified type. The TYPE attribute makes sense when a plug-in doesn't need a data stream or when the data is generated dynamically and doesn't have a well-defined MIME media type.

Navigator defines a rectangle in the Navigator window to hold embedded data. The HTML writer can use the HEIGHT and WIDTH attributes of the <EMBED> tag to specify the size of the rectangle.

Hidden Plug-Ins  A plug-in may also be hidden-that is, it may be invoked in such a way that it has no window. Use the <EMBED> tag but specify a HIDDEN attribute. (You can say HIDDEN=true if you prefer-true is the default).

Full-Page Plug-Ins  Sometimes you want to allocate a whole window to the plug-in content. Rather than using the <EMBED> tag, just link to the file. For example, an HTML writer can write the following:

Examine <A HREF="http://www.some-server.com/myFile.xyz">my file</A>

When the site user follows this link, the server looks up the MIME media type based on the .xyz file extension and begins streaming the data to the browser. Navigator looks up the media type from among its registered plug-ins; if it finds a match, it loads the plug-in and starts an instance of the plug-in. Plug-ins started in this way are called "full-page" plug-ins.

Introduction to Plug-In Architecture

As described in Chapter 9, Navigator plug-ins are implemented as code resources that execute in the same address space as Navigator. They are distinguished from other applications by the fact that they call and are called by Netscape Navigator. Figure 10.1 shows the context of a Netscape Navigator plug-in.

Figure 10.1 : A Navigator plug-in resides in the space between Navigator and the native operating system.

When Navigator starts, it registers the MIME media types used by the plug-ins and waits until it's called on to process one of those types.

When Navigator reads a content-type that it doesn't handle internally, it looks at the list of registered plug-ins to see if the type can be handled by one of the plug-ins. If so, it loads the plug-in code, instantiates two classes (one in the plug-in and one in Navigator), and makes a series of calls to the plug-in object.

Figure 10.2 illustrates these two objects. All calls from Navigator to the plug-in start with the characters NPP_. Calls from the plug-in to Navigator start with NPN_.

Figure 10.2 : Within its context, a Navigator plug-in is defined by two objects.

All of the methods that are part of the plug-in Application Program Interface (API) are defined in the npapi.h file.

Tip
You can use C++ exceptions to signal conditions within your plug-in. Error conditions to and from Navigator are passed through result codes from the methods. Npapi.h has definitions of the result codes in NPError type.

Figure 10.3 illustrates the calls Navigator makes to the plug-in. When the plug-in is loaded (and before it is instantiated), Navigator calls NPP_Initialize(). As soon as a copy of the plug-in is instantiated, Navigator calls NPP_New(). If more copies of the plug-in are opened while the plug-in is loaded, NPP_New() is called for each new instance.

Figure 10.3 : During its life, Navigator makes a series of calls to a plug-in.

When NPP_New() is called, Navigator sets its pluginType parameter to either NP_EMBED or NP_FULL to reflect the way in which the plug-in was invoked.

Note
The original plug-in documentation from Netscape described three types of plug-ins: embedded, full-page, and hidden plug-ins. In the current implementation, Netscape supports embedded plug-ins and full-page plug-ins as pluginType types in NPP_New(). If the HTML writer uses an <EMBED> tag with the HIDDEN attribute to make a hidden plug-in, Netscape sets pluginType to NP_EMBED but does not call NPP_SetWindow() to tell the plug-in to draw into the window.

When the instance window is closed, Netscape calls NPP_Destroy() on that instance anddeletes the instance. When the last instance of a plug-in is destroyed, Netscape calls NPP_Shutdown() and unloads the plug-in. Figure 10.3 shows this and other calls made by Navigator to the plug-in.

As the plug-in programmer, you are free to take any appropriate action when Netscape calls your plug-in. Generally, NPP_New() is used to do all initialization not done by the constructor. NPP_Destroy() can delete any objects instantiated during initialization.

You also may want to use NPP_Destroy() to save information related to an instance. When possible, Navigator restores that information to a new plug-in instance that is instantiated on the same content.

Suppose that a user opens the myMovie.avi file. Navigator starts an AVI-reading plug-in that begins playing the movie. Before the movie is finished, the user closes the plug-in window. If the user later opens myMovie.avi again, the plug-in could use stored information to return the user to the exact frame where he or she left off.

The Plug-In Object  Most plug-ins interact with windows in the native environment. A plug-in that draws into a rectangular space in the Navigator window is known as an embedded plug-in. A plug-in that opens its own window is referred to as a full-page plug-in.

At one time, Netscape envisioned a third type of plug-in, which would run in the background and have no open window. Their latest thinking is that functionality should be provided with the existing types of plug-ins, but that the HTML writer should pass the HIDDEN attribute to the plug-in through the <EMBED> tag.

After it is instantiated, Netscape calls the plug-in's NPP_SetWindow() method. As a parameter for this method, Netscape passes the handle for the native window provided for the plug-in's use.

Note
On Windows and UNIX, window->window is a handle to a subwindow of the Netscape window hierarchy. On the Macintosh, this field points to an NP_Port structure. N

Note
If the plug-in is running on Windows or UNIX, Netscape filters messages and only sends the plug-in messages destined for the plug-in's window. On the Macintosh, the operating system and the plug-in share the event stream. The Macintosh programmer should write a method NPP_HandleEvent() that picks off the events the plug-in can handle and refers the rest back to the operating system.

Unless you make other arrangements, the plug-in's methods are part of Navigator's main thread of control, which means that if a plug-in seizes control for a long time, Navigator looks to the user as though it has stopped responding. (Methods of handling substantial asynchronous work are described under "Control Issues in Asynchronous Plug-Ins," later in this chapter.)

After the plug-in instance is instantiated and has a handle to its window, Navigator can pass data to it. Navigator signals the plug-in that a stream of data is available by calling the plug-in's NPP_NewStream() method.

Note
Navigator can pass data as the data is received, in a stream, or after all the data has been received, in a file. If the stream has the ability to be positioned at a particular spot for purposes of reading or writing, it is said to be seekable. Local files are inherently seekable. Remote streams may be seekable if the server supports byte-range requests. Details on how to access seekable streams from a plug-in are given later in the chapter, in the section entitled "The Netscape Peer."

When the stream is no longer available, Navigator calls NPP_DestroyStream(). Netscape recommends that plug-ins wait while Navigator buffers data and then calls NPP_WriteReady() and NPP_Write() to "write" the data into the plug-in.

When Navigator calls NPP_NewStream(), the plug-in sets up a buffer to receive incoming data. Before actually writing the data to the plug-in, Navigator calls NPP_WriteReady(). That method reports back to Navigator the space remaining in the buffer and clears the way for Navigator to write that number of bytes.

After Navigator puts data into the buffer, the plug-in is free to process this data asynchronously. Before Navigator writes to the plug-in again, it calls NPP_WriteReady() to see how much space is available in the buffer. NPP_WriteReady() is an example of an Observer pattern, providing synchronization and coordination between two objects.

Caution
The terms read and write as used in plug-in methods are written from the point of view of whichever object is making the call. This convention may lead to some confusion. Data flows to the plug-in because Navigator writes it. The plug-in can also issue a read request that solicits data on a seekable stream. In both cases, the direction of data flow is to the plug-in.
The plug-in also can be written so that Navigator saves the stream to the hard drive (in its cache), and then calls NPP_StreamAsFile() to process the entire stream at once. Netscape strongly discourages using this method.

In addition to the NPP_New(), NPP_NewStream(), and the other methods already described, Netscape can call the following methods on the plug-in object:

Note
Netscape Navigator 3.0 and later allow methods related to LiveConnect. These methods are described in Part V, "LiveConnect."

The plug-in printing mechanism is an example of a Mediator pattern. The printing mechanism is decoupled from Navigator by the plug-in object. If the plug-in is using a full window, Navigator even offers the plug-in control of the print dialog boxes.

NPP_Print() is used when Navigator wants the plug-in to print itself. If the instance is full-page, NPP_Print() is first called with platformPrint->mode set to NP_FULL before Netscape displays any print dialog boxes. This technique gives the plug-in an opportunity to show its own dialog boxes and control the printing process. If it does this, it should set pluginPrinted to true before returning.

If you are willing to allow Navigator to set up the printing process, set pluginPrinted to false and return. Navigator calls NPP_Print() again, this time with platformPrint->mode set to NP_EMBED. The plug-in that sees platformPrint->mode set to NP_EMBED knows that it is responsible for drawing only its representation into the native window. Navigator sends a pointer to this native window in the data member platformPrint->embedPrint.window.

Note
If the plug-in is running on the Macintosh and platformPrint->mode is set to NP_FULL, platformPrint contains a handle to the standard Macintosh print record.
The handle is referred to as a THPrint in Mac-speak; the print-record itself is named TPrint.

Tip
If you opt to control your own full-screen printing, save the user's choices from the Print and Page Setup dialog boxes with the instance data. If the user prints this instance again, restore this data as the new defaults.

Windows programmers should note that the coordinates of the window rectangle are in TWIPs, which is a Microsoft term that means "twentieth of a point." Make sure that you use the DPtoLP() method of the CClientDC object to convert the coordinates from device coordinates to logical coordinates before drawing text into the window.

NPP_URLNotify() is used in connection with methods on the Netscape peer to tell the plug-in that an URL-related request to Netscape has completed. This method is described in greater detail in the following section.

The Netscape Peer  Recall that when Navigator instantiates a plug-in object, it also instantiates a peer object of its own. You can make calls to the peer with methods that begin with NPN_. These methods represent services that Navigator performs for the plug-in.

Some of these services are rather mundane. NPN_UserAgent(), for example, returns the browser's ID string. NPN_Version() returns the version numbers of the browser and the plug-in SDK. There is platform-specific code (in npmac.h and npwin.h) to compare the browser's major version number with the plug-in's version; if the user tries to load a version 3.x plug-in with a version 2.x browser, the plug-in exits.

Caution
Netscape only increments the major version number of the SDK when it releases a version that is incompatible with older browsers. Netscape has promised to increment the minor version number when the browser offers new plug-in features. Your plug-in should compare the browser minor version number with its own minor version number to ensure that all new features it uses are available.

A principal use of the Netscape peer object is to reach out through Navigator back to the Internet. You can ask Netscape to open a new stream by calling NPN_GetURL(). To open a new stream and be notified when the request is completed, call NPN_GetURLNotify(). When Navigator completes the request, it calls NPP_URLNotify() and tells the plug-in the result of the request. These methods can be used to implement links.

Tip
If your plug-in includes buttons or hot spots, put the destination in the status line, as Navigator does, using NPN_Status(). This technique keeps your plug-in consistent with Navigator's look and feel.

The NPN_PostURL() is the reverse of NPN_GetURL(). It allows the plug-in to package and send data to a Web server, where a CGI script or server-side JavaScript program can process it. The plug-in API also offers an NPN_PostURLNotify() that provides notification through NPP_URLNotify().

Tip
You can use NPN_PostURL() to send data to non-Web servers (specifically FTP, mail, and news). If you are sending a file, however, and the plug-in is running on a Windows or Macintosh machine, the file must be a text file with UNIX-style line breaks (newlines, also known as linefeeds).

Caution
Each protocol has its own needs for headers. Some protocols, such as HTTP, need a blank line between the headers and the body. If you don't need headers for a particular file, but the protocol requires that headers be separated from the body by a blank line, start the transmission with a blank line.
You cannot use NPN_PostURL() to send separate headers (even a blank line) from a memory buffer-only from a file. To send a memory buffer with separate headers, use NPN_PostURLNotify().

When a plug-in handles NPP_NewStream(), it tells Navigator how to handle the stream. It can specify that the data be delivered as a stream (the recommended technique) or as a file. If the stream is seekable, the plug-in can tell Navigator that it doesn't want data sent; the plug-in asks for data as needed. If the stream is set up in this way, the application calls NPN_RequestRead() to get the data.

Caution
Only two kinds of streams are inherently seekable-files on the local hard drive and streams from Web servers that allow byte-range requests. If you use NPP_NewStream() to set a stream to NP_SEEK mode, even though it isn't inherently seekable, Navigator must download the entire file to the cache so it can fulfill NPN_RequestRead().
Trying to seek on a stream that isn't inherently seekable forces the user to wait while the whole file downloads. If this download takes a long time (remember that a 28.8Kbps modem can only fetch about 40K in 15 seconds), warn the user before starting the download.

Not only can the plug-in open a new stream for reading, it also can open an URL for writing. Use the NPN_NewStream() to open the stream and write to it with NPN_Write(). The call to NPN_NewStream() allows you to specify the target. These targets are the same ones Netscape uses with their <FRAMESET> tags.

After the plug-in is done with the stream, it should call NPN_DestroyStream().

Tip
A plug-in can make a new instance of itself by opening a new stream with one of the MIME media types that it handles. If the target is the same window or frame in use by the current instance (such as _current), the old instance is destroyed as soon as it completes NPN_Write().

Recall that when NPP_Destroy() is called by Navigator, you can set an NPSavedData parameter and store data for use by future instances that are called on the same URL. The memory for this parameter must be owned by Navigator because the plug-in is gone after NPP_Destroy() completes. Allocate a chunk of memory in Navigator with NPN_MemAlloc().

Tip
The Macintosh version of Navigator uses a memory cache that can fill memory. If your Macintosh plug-in tries to allocate memory with NewPtr() (part of the Macintosh's Memory Manager) and NewPtr() returns a memFullErr, request the memory through NPN_MemAlloc().
For easier implementation and greater portability, just call NPN_MemAlloc() in the first place. NPN_MemAlloc() forces Navigator to purge enough of its memory cache to satisfy the request, so it is more likely to succeed than NewPtr().

Note
The Macintosh API also offers NPN_MemFlush(), which asks Navigator to free a block of memory. In general, use NPN_MemAlloc() to get memory. NPN_MemFlush() is useful only if you need to make a call that allocates memory indirectly. If you need as much memory as possible, write a loop to repeatedly call NPN_MemFlush() until it returns 0 (indicating that no more memory can be freed).

When you are done with a block of memory allocated with NPN_MemAlloc(), release it with NPN_MemFree().

Additional methods are available on the Netscape peer object that is used with LiveConnect. These methods are described in Part V, "LiveConnect."

What Can You Do with a Plug-In?

A visit to

http://home.netscape.com/comprod/products/navigator/version_2.0/plugins/index.html

reveals dozens of plug-ins, which fall into three groups: multimedia, document viewers, and applications.

Multimedia

One major use of plug-ins is to extend Navigator to handle new media types as though they were native. By using the <EMBED> tag as though it were, say, an <IMG> tag, the HTML programmer can place advanced graphics and movies on the page. The plug-in is responsible for reading the incoming data stream and drawing a representation of the data directly to the window.

If the <EMBED> tag is called with the HIDDEN attribute set to true, no window appears. The plug-in that is designed to play a sound may be used in this way.

Document Viewers

Sometimes the non-native media type is best thought of as a document rather than as a component to an HTML page. The Adobe Acrobat PDF viewer is an example of this type. When a user follows a link to a PDF document, Navigator starts the Acrobat plug-in in a full window and displays the document.

It still is possible to observe the Netscape look and feel in a full-page plug-in. When the user moves the cursor over a link, call NPN_Status() to show the link. When the user selects a link, call either NPN_GetURL() to open a new window or NPN_NewStream() with _current in the target. Then call NPN_Write() to overwrite the old contents of the current window.

Tip
Use NPN_GetURL() when the link takes the user to an existing entity on the Web. Use NPN_NewStream() and NPN_Write() when the plug-in generates the new content. In either case, cue the user about what will happen by marking the link with NPN_Status().

A Plug-In-Based Application

Although most plug-ins are multimedia-type viewers or document viewers, plug-ins give the programmer the potential of building a full network-centric application.

To lay out the end user's overall experience, many application designers follow a series of defined steps. In recent years, the industry has come to capture such processes at all levels, from analysis and design to coding. When these process definitions are presented with context, rationale, and examples, they are known as patterns.

Tip
The use of patterns in developing plug-ins is described in more detail in Chapter 3, "Integrating Plug-Ins into Web Site Design," of Netscape Plug-Ins Developer's Kit (Que, 1996).

This section shows an example of such an application, using the "Early Development" design patterns from the Portland Pattern Repository at http://c2.com/ppr/early.html.

The Story Pattern  The Story pattern is triggered when someone decides to computerize something. The key element of Story is to encourage the customer to talk about ways the end user will use the application.

For this example, your customer is a manufacturer of lawn tools. The Vice President of Sales tells you stories about the sales staff. The company distributes its products through distributors such as hardware stores, garden supply stores, and department stores. Here is one of their stories.

The sales staff are expected to review their accounts, looking for customers who haven't bought for a while or whose purchase volume has declined. The staff members are also encouraged to keep in touch with their accounts; they try to call every customer at least three times a year, even if their volume is high.

Sales are highly seasonal. The summer months are the best, but sales of rakes, leaf blowers, and work gloves are good in the fall. Snow blowers make up the bulk of the winter sales.

Every day, each account rep makes a list of which customers to call. In larger firms, customers usually speak to someone in purchasing. At smaller firms, they try to speak to the owner. Most of the accounts are smaller firms.

When account reps have the customer on the phone, they talk about the customer's recent purchases. They are often called on to answer simple technical support questions about the products or to describe features. They also like to have on hand a complete record of the customer's buying history.

The account reps have several problems with the current manual system. The product catalog is often out of date; by the time the summer catalog is out, the fall selling season has begun.

Technical support notes are packaged separately from the catalog. Often, account reps can find the product in the catalog (they can describe the features) but cannot find the tech support notes (so they cannot answer questions about the use of the product).

Calls from account reps often come as an interruption to their customers, so time is of the essence. Sometimes they are asked to call back. More often the owner can give them a few minutes and may even place an order if the account rep has the necessary information on hand.

Another problem the account reps have is that orders are sometimes put on hold by the credit department. This practice has led to some hard feelings and lost accounts: The account rep takes the order and is often unaware that the order has been held up for days, waiting for the credit manager to approve it.

The User Decision Pattern  After you have a set of stories, you can begin to map them to the elements of a user interface. Figure 10.4 shows a graphical representation of this mapping. The best user interfaces show consistency.

Figure 10.4 : Mapping stories to user interface elements requires a transformation from chronological order to spatial organization.

For example, users can imagine that they are in a "virtual world" such as a desktop. They may access applications like timers and word processors, but they perceive these tools as scheduling calendars and notepads.

The User Decision pattern calls for the designer to make a list of every decision the user must make during the stories. For each decision, the designer writes down the information the user needs to make a good decision.

Using the User Decision process, make a list of every decision the user makes during the stories and identify the information they need to make a good decision. Table 10.1 shows some of the decisions and information associated with the story of the lawn tools manufacturer.

Table 10.1  The User Decision Process

DecisionInformation
Which customers to callCustomer's purchase history Record of previous calls
Which products to recommendCatalog of products with feature lists
What information to give customerCatalog, tech support notes
When to tell customer order will shipComplete order
Credit approval
Whether to approve creditCustomer's payment history
Size of order

The Task Pattern  With the list of decisions in hand, the designer turns to the Task pattern. The hallmark of the Task pattern is that different account reps can work in the order that best suits their needs. Some reps may prefer to concentrate on accounts with declining sales. Other reps may want to concentrate on calling their best customers frequently.

Management, however, may want to make sure that all customers are called and not just the best accounts. Some companies go so far as to write a script for their account reps. A good interface design helps account reps structure their work, without requiring that every account rep work in exactly the same way as every other.

When using the Task pattern, the designer writes each task on an index card and clusters cards by the information they need. Figure 10.5 shows what some of these clusters look like in the case of the lawn tool manufacturer. Each cluster becomes a candidate task and gets a name.

Figure 10.5 : When using the Task pattern, the designer clusters user decisions by the kind of information needed.

The Task Window Pattern  The purpose of the Task Window pattern is to find an acceptable design point somewhere between the extremes of "everything in one window" and "a window for every element."

When using the Task Window pattern, the designer reviews the list of tasks with the users. After there is some agreement about which tasks the users perform (and which users perform which tasks), the designer develops one window for each task.

The available actions in each window are the visible functions of each task. Sometimes, it makes sense to divide the window into related panes.

The Early Program Pattern  Soon after the stories are complete and the user interface is defined, it's time to build a prototype. For Web-based applications with sophisticated user interfaces, a prototype of the user interface is key to ensuring that the end user's needs are met.

For a technically literate client, you may choose to build an architecture prototype. Patterns for all of these early programs are available in the Portland Pattern Repository at http:// c2.com/ppr/.

Figures 10.6 and 10.7 show how portions of the lawn tools manufacturer's application may look if implemented by using an intranet with Windows 95 clients.

Figure 10.6 : The account rep uses a customer list pane, a customer information pane, and a phone pane to do the Call Customertask.

Figure 10.7 : While talking to the customer, the account rep can access an integrated electronic catalog and set of technical support notes.

An application such as the one described in this section can be implemented as a combination of static HTML, client-side and server-side JavaScript, Java, and plug-ins. Plug-ins are particularly attractive when the application will be fielded over an intranet because the solution may be needed only on a single platform, and the organization may be able to draw on existing applications and code.

The following components of the solution are candidates for implementation as plug-ins for these reasons:

Control Issues in Asynchronous Plug-Ins

Some plug-in methods are inherently asynchronous. For example, when your plug-in calls the URL methods of the Netscape peer object, control is returned to the plug-in immediately, and the plug-in is notified of the results later by NPP_URLNotify() (if you used the Notify version of the URL call).

At other times, the plug-in may need to proceed asynchronously and allow Navigator to resume processing while the plug-in does its work. There are two methods for doing asynchronous work: threads and processes. Threads and processes are similar; one name for a thread is a "lightweight process." The principal difference between the two is that a thread runs in the same address space as its parent (so it can access data structures allocated by the parent) while a process runs in a separate address space and communicates with its parent by using InterProcess Communications (IPC) mechanisms.

Threads

Until the mid-90s, most high-end operating systems (such as UNIX and Windows NT) gave the programmer only one way to put the processor to work on more than one task: process forking (also known as spawning). Forking a new process is a CPU-intensive step because the process has its own set of kernel entries and its own address space.

Separate processes also presented complexities for the programmer because direct communication between different address spaces needs signals, pipes, or other forms of interprocess communication (IPC) rather than simple function calls.

Many programmers felt a need for a "lightweight process" that could run asynchronously in the same address space as its parent. Both UNIX and Windows NT now offer threads, which is a mechanism of starting a separate processing sequence without the overhead of a separate process.

Note
Macintosh programmers can expect similar facilities in the next generation of the Macintosh, System 8. See the latest information on Apple's site (http://www.macos.apple.com/macos8/) for details.

When the programmer needs to start asynchronous work during an NPP_ call, he or she should start a new thread and return control to Navigator.

Processes

Sometimes the programmer has an existing application or a package of easy-to-assemble modules that do the asynchronous work. (These easy-to-assemble packages are particularly common in UNIX, where shell, awk, and Perl programs are common and pipes make it easy to put together tools.)

In these cases, the programmer should consider calling system(), which transfers control to a new process and allows it do the work. Various IPC mechanisms, ranging from simple pipes to sophisticated TCP and UDP solutions, allow communications between the plug-in and the separate process.

Reentrant Code

In general, Navigator instantiates a new plug-in object from the plug-in code when it needs one to deal with a stream or an <EMBED> tag. One important exception exists to this rule: Netscape warns that if the plug-in calls Navigator through NPN_ calls, Navigator may make reentrant calls to the plug-in.

Most of the STL classes are reentrant. If you use a commercial version, the vendor can show you which classes are not reentrant. If you use one of the off-the-Internet versions, examine the classes you use for static variables. Either use a different class or devise your own version of the class, which moves the class variables into instance variables or singleton objects.

In the SDK…

Plug-ins are based on a pair of collaborating objects-one, the plug-in, representing the native operating system. The other, the Netscape peer object, representing Netscape and the Internet itself.

Plug-ins are only one part of the design of a complete network-centric application. A Web-based application, such as the example with the lawn tools manufacturer, may include static HTML, client- and server-side JavaScript, Java, as well as plug-ins. Using LiveConnect, you can integrate all of the client-side techniques.

ON THE WEB
http://home.netscape.com/comprod/development_partners/plugin_api/index.html This page contains information on LiveConnect and Navigator Plug-ins. From this page, you can download the plug-in developer's kits for Windows, OS/2 Warp, UNIX, and the Macintosh. If you download one of the developer's kits, you don't need the Developer's Guide (listed at the bottom of the page). The Developer's Guide is included in each kit.