Netscape Client Plug-ins
By S. Narayanan
Send comments
and questions about this article to View Source.
Click here for printer-friendly version
Netscape's plug-in architecture allows developers to extend the capabilities
of Navigator, Netscape's Web browser. Using Netscape's LiveConnect technology,
you can deliver high-performance applications, integrating client plug-ins
with Java and JavaScript.
This article presents an overview of how to develop a plug-in that supports
LiveConnect and take advantage of the resulting communication capabilities
among Java, JavaScript, and C.
ABOUT PLUG-INS, MIME TYPES,
AND LIVECONNECT
Plug-ins are like helper applications that run within Navigator. Although
they behave as though they're part of Navigator, plug-ins are separate
code modules that extend Navigator's capabilities by allowing it to support
additional MIME types, play audio and video, display animations, and so
on.
MIME (Multipurpose Internet Mail Extensions) media types specify most
data types on the Internet, and consist of a major type (such as application,
image, or text) followed by a minor type. If you create a new MIME type,
you should register it with the Internet Engineering Task Force (IETF).
Until the MIME type is registered, you should prefix it with x-.
(For more information on MIME types, see RFC
1521.)
LiveConnect is a Netscape technology that enables communication between
Java, JavaScript, and C. With LiveConnect:
- Java can use the power of JavaScript to access browser-related information.
- JavaScript can use Java methods, variables, classes, and packages directly.
- Java can call native methods to export low-level functionality.
- JavaScript can call native methods through Java.
LiveConnect is enabled by default in Navigator 3.x and later; users
can manually enable it or disable it through a preference panel. LiveConnect
communication is made possible in Navigator through netscape packages present
in java_30 in Navigator 3.x or java40.jar in Communicator.
Because LiveConnect allows you to integrate plug-ins with Java and JavaScript,
you can create LiveConnect-enabled plug-ins that are controlled by Java
and JavaScript. These plug-ins can even make use of the built-in Java and
JavaScript methods directly. Although no direct communication can occur
between JavaScript and native methods, JavaScript can communicate with
native methods through Java. (The section LiveConnect
Technology presents more details on these communication capabilities.)
HOW PLUG-INS WORK
When the browser starts up, it checks for plug-in modules in the plug-ins
directory and registers them. (You can find the installed plug-ins by selecting
About Plug-ins from the Help menu.) When an
unknown MIME type comes over the stream, Navigator checks for that type
in the header. If a plug-in is available to handle the new stream with
the specified MIME type, then Navigator loads the appropriate plug-in into
memory, creates a new instance of it, initializes it, and hands the new
stream over to the plug-in. Navigator also gives the window handle to the
plug-in so that it can draw in the Navigator window.
Plug-ins can also be loaded as part of a Web page by means of the EMBED
tag. If you use the SRC parameter
in your EMBED tag, Navigator looks at the type of document to
decide which plug-in to use (which is why you need to register for MIME
types and file extensions in the plug-in's resource file).
When downloading a file from a Web server, Navigator receives a
MIME type, which it will use to choose the plug-in. When SRC refers
to a local file, there is no MIME type information, so Navigator has to
fall back on the extensions that plug-ins have registered for.
DEVELOPING A 32-BIT PLUG-IN
USING MICROSOFT VISUAL
C++ 4.0
The following steps give a general description of how to develop a 32-bit
Navigator plug-in using Microsoft Visual C++ 4.0. (These steps are for
Windows development only.)
Note: These steps are intended specifically for developing a
plug-in with Microsoft Visual C++. However, you can use the Plug-in SDK
in any C++ development environment.
- Open a new project workspace.
- Select MFC AppWizard dll.
- Name the project. Make sure that the name starts with NP.
- Click Create.
- Click Finish to generate project files.
- Unzip the source files and copy them to
your current project directory.
- Insert WinTemp.c and npwin.cpp into your project.
- Open the VS_VERSION_INFO resource file in the Visual C++ resource
editor.
- Double-click Block Header. In the dialog box that appears, specify
Code Page as Windows, Multilingual. (If you don't do this, Navigator won't
recognize your plug-in.)
- Save and open your resource (.rc) file in Notepad to add MIME
and file extension information.
- Add the following in your .rc file below VALUE "CompanyName",
"\0":
VALUE "FileExtents", "wpt\0"
VALUE "FileOpenName", "Windows Plugin Template (*.wpt)\0"
VALUE "MIMEType", "application/x-Netscape-Windows-Plugin-Template\0"
- Save the file and close Notepad. Open VS_VERSION_INFO in Visual
C++. You should see the new values. You can change the MIME types and file
extensions according to your needs; for the purpose of this example, however,
leave them unchanged.
- >From the Build menu, choose Settings to display the Open Project
Settings dialog box.
- Under General, select "Use MFC in a Static Library." This
is necessary to avoid shipping additional libraries with your plug-in.
- Open the C/C++ folder.
- Select Precompiled Headers from the Category list.
- Select Automatic Use Of Precompiled Headers, and click OK.
- Open the module definition (.def) file in Visual C++.
- Delete EXPORTS and any explicit exports
that follow.
- Add the following code:
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
NP_GetEntryPoints @1
NP_Initialize @2
NP_Shutdown @3
- Build your plug-in DLL (dynamic linked library).
- Copy the plug-in DLL into your plug-ins directory. Then, if Navigator
is running, restart it.
- Unzip the test files. Open TemplateExample.html
in Navigator.
Once you've completed these steps, you'll have a basic plug-in module.
The rest of this article describes LiveConnect technology in general and
shows how to extend the plug-in you just built to support LiveConnect.
LIVECONNECT
TECHNOLOGY
This section describes how Netscape's LiveConnect can be used to connect
Java, JavaScript, and plug-ins.
JavaScript-to-Java Communication
JavaScript can call Java built-in functions directly. To access Java
in JavaScript, use the following syntax:
[Packages.]packageName.className.methodName
- Packages is optional; it can refer to Java, Netscape, or Sun.
- packageName refers to the package name.
- className refers to a particular class in the package.
- methodName refers to a method in the class.
Here's how JavaScript uses the println() method of Java's System
class to print to the Java Console (a Navigator window that displays
Java messages printed to stdout()).
java.lang.System.out.println("Greetings from JavaScript");
Example 1
demonstrates how to access the Java built-in classes directly. It uses
Java's built-in Math class to calculate the power of two numbers.
Similarly, JavaScript can control Java applets. JavaScript can reference
applets present in the document using the applets array or the
applet's name. Using this reference, JavaScript is able to access an applet's
public members and methods.
Example 2 demonstrates how JavaScript
can access an applet's public members and public methods.
Java-to-JavaScript Communication
The Netscape JavaScript package contains JSObject and JSException
classes. To access JavaScript functions and properties in Java, import
the JavaScript package into your Java code. To allow your applet to use
JavaScript, you must specify the MAYSCRIPT attribute in the APPLET
tag. This prevents an applet from accessing JavaScript without the
knowledge of the page's author. If MAYSCRIPT is not specified,
an exception is thrown for applets using JSObject. (MAYSCRIPT
is only needed for Java to access JavaScript -- not for JavaScript
to access Java.)
Before accessing JavaScript properties or functions, you must get the
browser window handle. You can do this by using the JSObject class's
getWindow() method.
JSObject winHandle = (JSObject) JSObject.getWindow(this);
In the above code, this represents the Applet object.
Once you obtain the browser window handle, you can use the JSObject.getMember()
method to access JavaScript properties. Example
3 shows how to use JSObject.getMember().
Applets can also execute JavaScript functions using the JSObject.eval()
and JSObject.call() methods. Example
4 demonstrates how a Java applet uses these methods to call JavaScript
built-in functions.
Java-to-C Communication
Writing native methods primarily allows you to export low-level functionality
that Java may not provide. You can also use native methods to provide better
performance.
The following steps present a generic way of defining and using native
code in Java. (Details on calling a plug-in's native methods from Java
are given later in this article.)
- Create a Java class that declares a native method.
- Compile your Java code using javac.
- Create .h and .c files using the javah utility.
- The .h file you created will have the C syntax for your native
function. Implement native methods using this function declaration.
- Create a DLL.
- Load the DLL into your Java code to access the native method.
For more information, check Sun's example in the article Integrating
Native Code and Java Programs.
Note: Although Java applications can load DLLs to call native
methods, security restrictions prevent applets from doing so.
With LiveConnect, however, it is possible
for an applet to execute a plug-in's native methods as long as the plug-in
and applet are loaded.
JavaScript-to-C Communication
For security reasons, JavaScript cannot call the native code directly.
But since JavaScript can call Java directly, it can call the native code
through Java.
ENABLING NETSCAPE CLIENT
PLUG-INS TO SUPPORT LIVECONNECT
This section begins by giving an overview of Netscape's Plugin class
and javah utility, which allow you to support LiveConnect and call native
methods from Java. At the end of the section, you'll find steps for
implementing LiveConnect support in the plug-in you built earlier.
The Netscape Plugin Class
For security reasons, applets cannot load DLL modules to call native
functions. But with Netscape's LiveConnect, you can call plug-in native
code through the Plugin peer class. (After reading this article, you may
want to refer to the PluginAppletComm
example to see how applets can communicate with LiveConnect
plug-ins; this example was tested on Netscape Navigator 3.x with the Simple
plug-in.)
The Plugin class, provided by Netscape, extends the Object
class of Java. The Plugin class represents the Java reflection
of the plug-in. If you develop LiveConnect plug-ins, you'll have to design
a Java class derived from Plugin to
add new methods; these methods can be native methods that will be defined
in plug-in code, or they can be any normal Java methods that can use other
Java classes. This allows Java applets and JavaScript to manipulate or
call plug-in functions.
For more information, see the description
of the Plugin class in the JavaScript Guide.
Netscape's Javah Utility
LiveConnect is built on the Java Runtime Interface (JRI). But the JRI
implementation is hidden when you use Netscape's javah utility,
a modified version of Sun's javah. (For complete documentation
on JRI, check the Additional
Resources section of the LiveConnecting Plug-ins with Java.)
Netscape's javah, provided along with the plug-in developer's kit, allows
you to write native methods that are independent of the structure and implementation
of Java objects. You can use the javah
utility to generate a corresponding .c file and .h file
for a given Java class file. These files have native method declarations
that are to be used for defining native methods in the plug-in; they also
have declarations for calling Java methods or for accessing Java fields.
You must include these files with your plug-in code for compiling and linking.
The Java Runtime Interface document contains details on
javah-generated
header files and stub files.
Netscape LiveConnect Communication
Netscape LiveConnect technology is restricted to plug-ins, Java, and
JavaScript communication. As mentioned earlier, security considerations
prevent Java applets from loading native code modules to execute native
methods. Instead, Java and JavaScript can use the native code of the loaded
plug-in module. With Netscape LiveConnect:
- Java and JavaScript can call a plug-in's native code.
- Plug-ins can call Java and JavaScript.
Communication between JavaScript and plug-ins can only occur through
Java.
Calling Java Methods from Plug-ins
To use a built-in Java method or access its properties in your plug-in,
follow these steps:
- Run Netscape's javah on the Java class you want to use. For
example, if you want to use the String class, javah -jri java.lang.String
would generate java_lang_String.h, and javah -jri -stubs java.lang.String
would generate java_lang_String.c.
- Include these javah-generated files in your plug-in code for
compiling and linking.
- Use the function definition in *.h (java_lang_String.h)
to call the class methods directly from the plug-in.
- Call the use_ method to create an instance of the String
class during run time.
For more details, see the document Calling
Java Methods from Plug-ins.
Calling Plug-in Methods from Java
Some Java methods can be written in native code. This article discusses
plug-in native code executed from Java applets. You can read more about
Sun's implementation in the article
Integrating Native Code and Java Programs.
To allow Java to access a plug-in's native methods, you need to supply
a Java class that is a subclass of Netscape's Plugin class. Here
are the steps involved:
- Derive a Java class from Plugin. This class must be a public
class; otherwise, you'll get a run-time error.
- Declare native methods in the Java class.
- Compile the Java file to generate the byte file.
- Run Netscape's javah on the byte file to create the .h
and the .c files corresponding to
the class name.
- Include these files in your plug-in files.
- Define the native method.
- Call the use_ method to create an instance of the Java class
during run time.
- Call native methods directly from your Java class.
Now when Java calls the native Java method, your plug-in's native code
is executed. (You'll also develop a live example later, in the section
Changes to Make in Your Plug-in Files.)
Calling Plug-in Methods from JavaScript
Because Netscape's LiveConnect technology permits JavaScript to call
a Java method, JavaScript can execute native code through Java.
All LiveConnect plug-ins will have a Plugin peer class, so
JavaScript can directly call into the public methods of this peer class
using the following syntax:
document.pluginName.methodName
This will directly execute your Java method or your plug-in native code,
depending on which method you call.
Changes to Make in Your Plug-in Files
To implement LiveConnect in the plug-in files you built in Visual C++,
you must supply a plug-in class that you derive from Netscape's Plugin
class. In the following steps, MyClass represents the class
you're supplying.
- Define a plug-in class that will support LiveConnect functionality,
as shown here. Copy the following code and save it as MyClass.java:
import netscape.plugin.Plugin;
public class MyClass extends Plugin{
public native void popWindowsMessageBox();
}
- Obtain the MyClass.class file by running
javac, and obtain the corresponding MyClass.h
and MyClass.c files by running Netscape's javah. Copy
MyClass.c and MyClass.h into your project directory.
(For the javah syntax, see the next step.)
- You will also need to generate java_lang_Object.h, netscape_plugin_Plugin.h,
and netscape_plugin_Plugin.c under your project directory, because
they are dependent files. Use the following commands:
javah -jri java.lang.Object
javah -jri netscape.plugin.Plugin
javah -jri -stubs netscape.plugin.Plugin
- Make sure CLASSPATH points to java_30 or java40.jar.
If you get a -jri illegal argument message, then you are not using
Netscape's javah -- you're using Sun's javah.
- In Visual C++, create a new file by copying the following code and
saving it as stubs.c. (Note: Although it's not usual practice,
the .c files are included here to avoid some fancy "make"
rules.)
#include "netscape_plugin_Plugin.c"
#include "MyClass.c"
- Insert stubs.c into the project that you have already built.
- Open WinTemp.c. This is the file in which you will define
your native method. Under the line #include <windows.h>,
type the following code:
#define IMPLEMENT_MyClass
#include "MyClass.h"
#include "netscape_plugin_Plugin.h"
- Call use_ in NPP_GetJavaClass() for all the
Java classes that you want to use in your plug-in code. This associates
your Java class with your plug-in. In NPP_GetJavaClass(), return
the class you derived from the Plugin class.
If you don't intend to associate any Java classes in your plug-in, return
NULL in NPP_GetJavaClass(). Here's the code you'll
add to your NPP_GetJavaClass():
struct java_lang_Class* myClass;
JRIEnv* env = NPN_GetJavaEnv();
if (env == NULL)
return NULL; /* Java disabled */
myClass = use_MyClass(env);
use_netscape_plugin_Plugin( env );
return myClass;
- When you finish, call the corresponding unuse_ routine to
unload your classes in NPP_Shutdown(void). Here's what you have
to add to this example:
JRIEnv* env = NPN_GetJavaEnv();
if (env) {
unuse_MyClass(env);
unuse_netscape_plugin_Plugin( env );
}
- If you don't intend to associate any Java classes in your plug-in,
return NULL in NPP_GetJavaClass().
- Now define your native method in WinTemp.c. Here's a sample
snippet:
extern JRI_PUBLIC_API(void)
native_MyClass_popWindowsMessageBox(JRIEnv* env, struct MyClass* self){
NPP npp = (NPP)netscape_plugin_Plugin_getPeer(env, self);
PluginInstance *pinst = (PluginInstance*)npp->pdata;
NPWindow *window = pinst->fWindow;
MessageBox((HWND)window->window, "Test", "Native", MB_OK);
}
- Compile your plug-in. Copy the plug-in DLL and MyClass.class
into your plug-ins directory. Modify your test file (TemplateExample.html).
You may want to include some test code like this:
<form>
<input type=button Value=click onClick="document.embeds[0].popWindowsMessageBox();">
</form>
Technical reviewers for this article were Sharon Williams, Marc Byrd,
Steve Thomas, and Eric Byunn of Netscape Communications. The article was
edited by Anne Szabla.
FURTHER READING
View Source wants your feedback!
Write to us and let us know
what you think of this article.
S. Narayanan is a software engineer at India-based
Wipro Systems and works as a developer
support engineer for Netscape. Narayanan specializes in Netscape's client
technologies. He has also contributed sample code and FAQ documents to
Netscape's developer site.
(7.97)
- Related Readings:
-
Any sample code included above is provided for your use on an "AS IS" basis, under the Netscape License Agreement - Terms of Use