# Java-to-Javascript Communication

This section includes the following topics:

- Introduction
- `JSObject`
  - How `JSObject` Works
  - Enabling `JSObject` support in Java Plug-in
- Common DOM API

## Introduction

Java Plug-in offers two ways 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`. For more information, see Java Packages for LiveConnect.

Because the JavaScript rendering engine is implemented differently 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

`JSObjec`t 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:

- `public Object call(String methodName, Object args[])`
- `public Object eval(String s)`
- `public Object getMember(String name)`
- `public Object getSlot(int index)`
- `public void removeMember(String name)`
- `public void setMember(String name, Object value)`
- `public void setSlot(int index, Object value)`
- `public String toString()`
- `public boolean equals(Object obj)`

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.

For more information about using `JSObject`, please read the section called "Java to JavaScript Communication" on the LiveConnect page.

To compile Java code to take advantage of `JSObject`, you must have the package `netscape.javascript` in the `CLASSPATH`. Since 1.4.2 Java Plug-In ships `netscape.javascript` in a JAR file called `plugin.jar`. To compile an applet which uses `JSObject`, add `plugin.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 SE platform. As a result, applets using `JSObject` may not run in AppletViewer or result in exceptions.

### 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.

JavaScript and LiveConnect are technologies from Netscape Communications Corporation. Due to the differences in the Javascript engine implemented by Mozilla and Microsoft, data marshalling between Java and JavaScript via LiveConnect may result in different datatypes for different browsers. The main differences in JavaScript implementations from vendors are in JavaScript datatype support, mapping of datatypes between Java and JavaScript, and DOM element implementation.

## Note The original JavaScript specification is available at http://devedge-temp.mozilla.org/library/manuals/2000/javascript/1.3/guide/index.html. The original LiveConnect specification is available at http://devedge-temp.mozilla.org/library/manuals/2000/javascript/1.3/guide/lc.html#1037078.

## Common DOM API

### Overview

This section discusses the Common DOM API in Java Plug-in 6. 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 supported Mozilla browsers. 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:

- `org.w3c.dom.*`
- `org.w3c.dom.css.*`
- `org.w3c.dom.events.*`
- `org.w3c.dom.html.*`
- `org.w3c.dom.stylesheets.*`
- `org.w3c.dom.views.*`

### 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(); }`