Java-to-Javascript Communication



This section includes the following topics:

Introduction

Java Plug-in offers two way to access the DOM: Through JSObject and through the Common DOM API. Each method is described below, along with security considerations.

JSObject

Java applets may need to perform Java-to-JavaScript communication to access the Document Object Model (DOM) or to call JavaScript functions on an HTML page. Browsers allow communication between Java and JavaScript through the Java wrapper class netscape.javascript.JSObject.

Because of differences in DOM implementations between browsers, Java Plug-in provides different degrees of support for JSObject in Internet Explorer and Navigator. This document specifies how JSObject support works in different browser environments.

How JSObject Works

JSObject provides an easy way to access the DOM of an HTML page. But because different browsers implement the DOM differently, using JSObject in a Java applet may yield different behaviors in Java Plug-in. For details about the DOM implementation in a particular browser, consult the developer guide for that browser.

In general, applets access JSObject as follows:

import netscape.javascript.*;
import java.applet.*;
import java.awt.*;
class MyApplet extends Applet {
     public void init() {
         JSObject win = JSObject.getWindow(this);
         JSObject doc = (JSObject) win.getMember("document");
         JSObject loc = (JSObject) doc.getMember("location");

         String s = (String) loc.getMember("href");  // document.location.href
         win.call("f", null);                      // Call f() in HTML page
     }
}

The starting point is the static method

public static JSObject getWindow(Applet a) 

which returns a JSObject representing the Window that contains the given applet. Since this method takes only java.applet.Applet as parameter, JSObject can be accessed from an applet, but not from a bean unless the bean is also an applet.

Once the Window object is obtained, the applet can navigate the DOM of the HTML page using the following methods:

We recommend using only getWindow(), call(), eval(), setMember() and getMember() in Java Plug-in. The implementations of getSlot(), setSlot(), removeMember() and toString() are browser-dependent; i.e., the result of execution may vary depending on the version and platform of the browser in which Java Plug-in is running.

To compile Java code to take advantage of JSObject, you must have the package netscape.javascript in the CLASSPATH. Currently, Java Plug-in 1.3 ships netscape.javascript in a JAR file called JAWS.JAR. To compile an applet which uses JSObject, add JAWS.JAR in the CLASSPATH before compilation.

Note that although JSObject is supported in Java Plug-in, it is not supported in AppletViewer in the Java 2 platform. As a result, applets using JSObject may not run in AppletViewer or result in exceptions.

Degree of JSObject support in Java Plug-in

Internet Explorer:

By accessing the DOM through COM, Java Plug-in provides full support of JSObject in IE.

Netscape Navigator:

By accessing the DOM through Netscape's Plug-in API, Java Plug-in provides limited support of JSObject in Navigator 4 . In Navigator 4 the following JavaScript objects can be accessed through JSObject:

No other JavaScript objects are supported with Netscape 4, and attempting to access them through JSObject will result in Java exceptions. These restrictions do not apply to Netscape 6; it provides full support of JSObject.

Note: Even though different browsers may support the same JavaScript object, support of an object's methods and properties may differ. Be sure to check the JavaScript developer guide for your browser.

Enabling JSObject Support in Java Plug-in

Due to security reasons, JSObject support is not enabled in Java Plug-in by default. To enable JSObject support in Java Plug-in, a new attribute called MAYSCRIPT needs to be present in the EMBED/OBJECT tag as follows:

Original APPLET tag: 

<APPLET code="XYZApp.class" codebase="html/" align="baseline"
     width="200" height="200" MAYSCRIPT>
<PARAM NAME="model" VALUE="models/HyaluronicAcid.xyz">
     No JDK 1.3 support for APPLET!!
</APPLET>

New OBJECT tag: 

<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
     width="200" height="200" align="baseline"
     codebase="http://java.sun.com/products/plugin/1.3/jinstall-13-win32.cab#Version=1,3,0,0">
     <PARAM NAME="code" VALUE="XYZApp.class">
     <PARAM NAME="codebase" VALUE="html/">
     <PARAM NAME="type" VALUE="application/x-java-applet;version=1.3">
     <PARAM NAME="MAYSCRIPT" VALUE="true">
     <PARAM NAME="model" VALUE="models/HyaluronicAcid.xyz">
        No JDK 1.3 support for APPLET!!
</OBJECT>

New EMBED tag:

<EMBED type="application/x-java-applet;version=1.3" width="200"
   height="200" align="baseline" code="XYZApp.class"
   codebase="html/" model="models/HyaluronicAcid.xyz" MAYSCRIPT=true
   pluginspage="http://java.sun.com/products/plugin/1.3/plugin-install.html">
<NOEMBED>
   No JDK 1.3 support for APPLET!!
</NOEMBED>
</EMBED>

If MAYSCRIPT is specified as false, or if MAYSCRIPT is absent, JSObject is disabled. For more information about the MAYSCRIPT attribute in the EMBED/OBJECT tag, see Using OBJECT, EMBED and APPLET Tags in Java Plug-in.
          

Common DOM API

Overview

This section discusses the Common DOM API in Java Plug-in for 1.4. It provides a standard API for accessing the DOM in the browser for browsers from different browser vendors running on various platforms.

Note

Full support is provided with Internet Explorer 6 and Netscape 6; support is limited with other browsers.

This API is built upon the Document Object Model (DOM) Level 2 recommendation. (See http://www.w3.org/DOM/ for various w3c recommendations.) The Document Object Model (DOM) is a set of interfaces defined using Interface Definition Language (IDL) and including Java Language bindings.

The Common DOM API includes the following w3c-defined interface packages:

DOMService

The Common DOM classes allow an application to access the underlying DOM of the browser through the APIs in the org.w3c.dom and org.w3c.dom.html packages.

Each DOM represents the underlying representation of a single XML/HTML document within the browser, and each browser may display more than one XML/HTML document in multiple browser frames/windows. Thus, when an application requests to access the DOM through the Common DOM classes, it is important to return the DOM associated with the application. In order to obtain the proper DOM associated with the application, a Java object will be passed to DOMService.getService(). DOMService will return the proper DOMService implementations associated with the object, or an exception will be thrown. Ordinarily the Java object is an applet or JavaBeans component. However, this specification doesn't preclude other Java object types from being used, if the DOMServiceProvider can handle it.

To perform an action on the DOM, an object that implements DOMAction will need to be passed to DOMService.invokeAndWait() or DOMService.invokeLater(). DOMAction.run() will then be executed on the DOM access dispatch thread. 

Here is a simple example of obtaining the title of the Document object:

DOMService service = null;

try
{
    service = DOMService.getService(MyApplet);
    String title = (String) service.invokeAndWait(new DOMAction()
                            {
                                public Object run(DOMAccessor accessor)
                                {
                                     HTMLDocument doc = (HTMLDocument) accessor.getDocument(MyApplet);
                                     return doc.getTitle();
                                }
                            });
}
catch (DOMUnsupportedException e1)
{
}
catch (DOMAccessException e2)
{
}

DOMService Plugability

Since there may be more than one DOMServiceProvider, it is important to allow third parties to plug their DOMServiceProvider implementations into the Common DOM classes. To achieve that, a new Java property, com.sun.browser.dom.DOMServiceProvider, is defined.

If this property is defined, it should contain a list of class names of the DOMServiceProvider implementations, each separated by a character "|".

When DOMService.getService() is called, DOMServiceProvider implementations specified by the com.sun.browser.dom.DOMServiceProvider will be called one-by-one to determine if the provide can determine the DOM association of the object, according to the order that is specified in the property. In case two DOMServiceProvider implementations may be able to handle the same object, the provider that is specified first in the property will be used.

Thread Safety

Because the DOM of each browser is implemented differently, DOM access is not expected to be thread safe. Accessing implementation of DOM objects in this specification must be restricted on the DOM access dispatch thread only, so thread safely can be ensured. To accomplish that, code accessing the DOM objects must be scoped within the DOMAction.run() block. To invoke the action, either DOMService.invokeAndWait() or DOMService.invokeLater() should be used, so that DOMAction.run() will be executed in the DOM access dispatch thread.

Although implementations of DOM objects should not be called outside the DOMAction.run() block, the application may cache these DOM objects around as instance member of a class, or pass these DOM objects between threads. However, caching the DOM objects as static members of any object is prohibited, since static members tend to stay around much longer than the lifecycle of the underlying DOM object.

The only object in the Common DOM classes that can be called from any thread is DOMService. Access to other objects in the Common DOM classes is restricted within the DOMAction.run() block; otherwise, an exception will be thrown.

Security

The browser DOM provides access to every service in the browser, so it is important to ensure that security is checked properly during each call into the DOM. When DOMService.invokeAndWait() or DOMService.invokeLater() is called, the security context of the caller will be captured. Later, when the corresponding DOMAction.run() is executed on the DOM access dispatch thread, the caller's security context will be passed to the browser DOM when implementations of the DOM objects are called. DOMAccessException will be thrown if the original caller doesn't have the required privileges to access the DOM.

Security policy of DOM access in each browser is different. As a result, even if a Java application is signed and fully trusted, accessing the DOM objects in the browser may still result in DOMAccessException.

DOM Object Lifetime

Implementation of the DOM objects represents the real underlying objects in the browser DOM. As the XML/HTML document is changed on-the-fly, DOM objects in Java may no longer be valid. Accessing an invalid DOM object will result in org.w3c.dom.DOMException, according to the W3C DOM Level 2 Specification. Developers who write code to access DOM objects in DOMAction.run() should not assume the validity of the DOM objects at any given moment. 

Conformance Requirements

Third parties implementing this specification must provide implementations of the Common DOM classes in the com.sun.browser.dom package. Implementations of the W3C DOM Level 2 APIs must also conformance to the W3C DOM Level 2 Specification. However, because each browser may implement a different subset of the W3C DOM APIs, third parties are not required to provide implementations of all org.w3c.dom and org.w3c.dom.html classes.

Package com.sun.browser.dom

This section defines the API of the com.sun.browser.dom package.

public abstract class DOMService       

The DOMService defines a service API that enables applications to access a document object representing the underlying DOM of the browser window that embeds the applications.

public abstract class DOMService 
{
        /**
         * Returns new instance of a DOMService. The implementation
         * of the DOMService returns depending on the setting of the
         * javax.browser.dom.DOMServiceProvider property or, if the
         * property is not set, a platform-specific default.
         * 
         * Throws DOMUnsupportedException if the DOMService is not 
         * available to the obj.
         *
         * @param obj Object to leverage the DOMService
         */
        public static DOMService getService(Object obj) throws DOMUnsupportedException;

        /**
         * An empty constructor is provided. Implementations of this
         * abstract class must provide a protected no-argument constructor
         * in order for the static getService() method to work correctly.        
         * Application programmers should not be able to directly
         * construct implementation subclasses of this abstract subclass.
         */
        protected DOMService();

        /**
         * Causes action.run() to be executed synchronously on the 
         * DOM action dispatching thread. This call will block until all 
         * pending DOM actions have been processed and (then) 
         * action.run()
returns. This method should be used when an 
         * application thread needs to access the browser's DOM. 
         * It should not be called from the DOMActionDispatchThread
         * 
         * Note that if the DOMAction.run() method throws an uncaught 
         * exception (on the DOM action dispatching thread), it's caught 
         * and re-thrown as an DOMAccessException on the caller's thread.
         * 
         * @param action DOMAction.
         */    
        public abstract Object invokeAndWait(DOMAction action) throws DOMAccessException;

        /**
         * Causes action.run() to be executed asynchronously on the 
         * DOM action dispatching thread. This method should be used 
         * when an application thread needs to access the browser's 
         * DOM. It should not be called from the DOMActionDispatchThread
         *
         * Note that if the DOMAction.run() method throws an uncaught 
         * exception (on the DOM action dispatching thread),  it will not be
         * caught and re-thrown on the caller's thread.
         * 
         * @param action DOMAction.
         */    
        public abstract void invokeLater(DOMAction action);
}

Note that Object obj in the getService(Object obj) method above is the applet or the bean.

public abstract class DOMServiceProvider

Implementation instances of the public abstract class DOMServiceProvider enable access to the underlying browser DOM for a given Java object. Instances of DOMServiceProvider should not be obtained by the application directly.

public abstract class DOMServiceProvider
{
        /**
         * An empty constructor is provided. Implementations should 
         * provide a protected constructor so that the DOMService
         * can instantiate instances of the implementation class. 
         * Application programmers should not be able to directly
         * construct implementation subclasses of this abstract subclass.
         * The only way an application should be able to obtain a 
         * reference to a DOMServiceProvider implementation
         * instance is by using the appropriate methods of the
         * DOMService.
         */
        protected DOMServiceProvider();

        /**
         * Returns true if the DOMService can determine the association
         * between the obj and the underlying DOM in the browser.
         */
        public abstract boolean canHandle(Object obj);

        /**
         * Returns the Document object of the DOM.
         */
        public abstract org.w3c.dom.Document getDocument(Object obj) throws DOMUnsupportedException;

        /**
         * Returns the DOMImplemenation object of the DOM.
         */
        public abstract org.w3c.dom.DOMImplementation getDOMImplementation();
}

Note that Object obj in the canHandle(Object obj) and getDocument(Object obj) methods above is the applet or the bean.

public interface DOMAccessor

DOMAccessor represents the interface that can be used within DOMAction.run() to access the entry point of the browser DOM.

public interface DOMAccessor
{
        /**
         * Returns the Document object of the DOM.
         */
        public org.w3c.dom.Document getDocument(Object obj) throws org.w3c.dom.DOMException;

        /**
         * Returns a DOMImplementation object.
         */
        public org.w3c.dom.DOMImplementation getDOMImplementation();

Note that Object obj in the getDocument(Object obj) method above is the applet or the bean.

public interface DOMAction

DOMAction encapsulates all the actions of the applications that will be performed on the browser's DOM.

public interface DOMAction
{
        /**
         * When an object implementing interface DOMAction is passed
         * to DOMService.invokeAndWait() or DOMService.invokeLater(),
         * the run method is called in the DOM access dispatch thread.
         *
         * accessor is used for the DOMAction to access the entry point of 
         * the browser's DOM, if necessary.
         *
         * @param accessor DOMAccessor
         */
        public Object run(DOMAccessor accessor);
}

public class DOMUnsupportedException

This exception is thrown from DOMService.getService() and DOMServiceProvider.getDocument() if the association between the Java object and the DOM cannot be found.

public class DOMUnsupportedException extends Exception
{    
        /**
         * Constructs a new DOMUnsupportedException with no detail message.
         */               
        public DOMUnsupportedException();

        /**
         * Constructs a new DOMUnsupportedException with the given detail message.
         *
         * @param msg Detail message.
         */               
        public DOMUnsupportedException(String msg);

        /**
         * Constructs a new DOMUnsupportedException with the given exception as a root clause.
         *
         * @param e Exception.
         */               
        public DOMUnsupportedException(Exception e);

        /**
         * Constructs a new DOMUnsupportedException with the given exception as a root clause and the given          * detail message.
         *
         * @param e Exception.
         * @param msg Detail message.
         */               
        public DOMUnsupportedException(Exception e, String msg);

        /**
         * Returns the detail message of the error or null if there is no detail message.
         */               
        public String getMessage();

        /**
         * Returns the root cause of the error or null if there is none.
         */               
        public Exception getException();   
}           

public class DOMAccessException

This exception is thrown from DOMService.accessAndWait() if any DOM objects throws any exception when it is accessed within DOMAction.run().

public class DOMAccessException  extends Exception
{    
        /**
         * Constructs a new DOMAccessException with no detail message.
         */               
        public DOMAccessException();

        /**
         * Constructs a new DOMAccessException with the given detail message.
         *
         * @param msg Detail message.
         */               
        public DOMAccessException(String msg);

        /**
         * Constructs a new DOMAccessException with the given exception as a root clause.
         *
         * @param e Exception.
         */               
        public DOMAccessException(Exception e);

        /**
         * Constructs a new DOMAccessException with the given exception as a root clause and the given          * detail message.
         *
         * @param e Exception.
         * @param msg Detail message.
         */               
        public DOMAccessException(Exception e, String msg);

        /**
         * Returns the detail message of the error or null if there is no detail message.
         */               
        public String getMessage();

        /**
         * Returns the root cause of the error or null if there is none.
         */               
        public Exception getException();   
}