You are currently viewing a snapshot of taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to, please file a bug.

webclient implementation guide

overview of primary classes and interfaces

directories & packages | object hierarchies | sequence description

The primary interfaces and classes for Webclient are:


Understanding the primary classes and interfaces is essential to knowing how Webclient works.


BrowserControlFactory is the starting point for building an application with Webclient. It is a class that provides two essential methods, both static:

  • setAppData()
  • newBrowserControl()


setAppData() checks to see that (1) the String specifying the absolute path to the native browser binary directory (absolutePathToNativeBrowserBinDir) is not null and that (2) the path actually exists on the machine. It then attempts to determine the correct canvas class for the platform, Win32 or Motif.

It sets platformCanvasClassName by first attempting to load "".

If it loads, then it sets platformCanvasClassName for Win32. If it fails, then it tries the same thing for Motif.

If one loads, then it sets:

BrowserControlCanvasClass = Class.forName(platformCanvasClassName);

This class is then used when BrowserControlFactory.newBrowserControl() is invoked.

In our example application, it is invoked in the very next line of code:

browsercontrol = BrowserControlFactory.newBrowserControl();

The result is as follows:


newBrowserControl() sets newCanvas to a new instance of browserControlCanvasClass. It then does the following:

  1. passes newCanvas to the constructor of BrowserControlImpl to get a new instance of BrowserControlImpl called result;
  2. checks both newCanvas and result to see if they are null;
  3. if neither is null, then initializes newCanvas, passing result to the initialize() method as follows:


The effect of this initialization is as follows:

Examining BrowserControlCanvas.initialize(BrowserControl controlImpl), it can be see that it sets the variable private BrowserControl webShell equal to result, the argument passed to initialize(), first checking that the argument is not null (we already now that it isn't).

This says that result is the BrowserControlImpl instance for newCanvas, which is a BrowserControlCanvas implementation instance.


In summary, setAppData() checks the path to the binary directory for Mozilla and finds the correct canvas class, while newBrowserControl() creates an instance of the canvas, creates a browser control from it, and associates that browser control with the canvas. (Note: setAppData() also invokes BrowserControlImpl.appInitialize(), the effects of which are discussed in BrowserControlImpl.)


BrowserControl is an interface that sets a number of static variables used by implementations (BOOKMARKS_NAME, BROWSER_CONTROL_CANVAS_NAME, CURRENT_PAGE_NAME ...), and it defines an abstract method called queryInterface(String interfaceName).

The variables represent various browser functions, and queryInterface() returns an instance of the implementation of the browser function named by the variable. For instance, the navigation function of the browser is represented by the variable

NAVIGATION_NAME = "webclient.Navigation";

By passing this variable to queryInterface(), an instance of the implementation of the navigation function (i.e., instance of NavigationImpl) is returned.

Thus the developer can use just those functions desired for the application.


BrowserControlImpl implements BrowserControl. Thus it it inherits the static variables of BrowserControl and implements queryInterface(). It also adds methods of its own, including a constructor, appInitialize() and createWrapperFactory().


The constructor takes a BrowserControlCanvas object as an argument and sets a private BrowserControlCanvas variable called myCanvas equal to it. Thus there is a particular canvas object associated with the BrowserControlImpl object.


appInitialize() is a static method that sets wrapperFactory = createWrapperFactory(), if the static wrapperFactory variable is null, and then invokes initialize() on wrapperFactory.


  1. wrapperFactory is set as type WrapperFactory, which is an abstract class.
  2. createWrapperFactory() is a private static method of BrowserControlImpl that returns an object of type WrapperFactory.


To accommodate different type of wrappers ("native" and "non-native"), some generality is introduced via the createWrapperFactory() method:
First, a String called wrapperFactoryClassName is temporarily set to the package name for BrowserControlImpl. Then String PARAMETERIZED_VALUE is set to the wrapper type (currently, "native", since this code is being used for a native wrapper). Then we have:

wrapperFactoryClassName = wrapperFactoryClassName + "wrapper_" + 
        PARAMETERIZED_VALUE + "." + WrapperFactory.IMPL_NAME;

wrapperFactoryClass = Class.forName(wrapperFactoryClassName);

The first statement sets wrapperFactoryclassName to the fully- qualified name for WrapperFactory.IMPL_Name. The second statement sets wrapperFactoryClass to the actual class.

Note that WrapperFactory.IMPL_NAME is determined by the abstract class WrapperFactory. public static String IMPL_NAME is currently set to "WrapperFactoryImpl" in that class. Thus WrapperFactory.IMPL_NAME is simply the String "WrapperFactoryImpl". This again give us generality, since we have the opportunity to set the directory for the WrapperFactory implementation according to the type of wrapper, and we also have the opportunity to name the implementation class as we like.

createWrapperFactory() finally creates a new instance of wrapperFactoryClass and returns it.

When the flow of control returns to appInitialize() , it sets the instance to wrapperFactory and invokes the initialize() method on it. WrapperFactoryImpl.initialize()is explained under WrapperFactory, WrapperFactoryImpl .


queryInterface() is used to create instances of a desired browser functions, such as navigation, bookmarks, history, as mentioned previously. All instances of a desired function are created similarly. Let us take the case of creating an instance of the history function. We could pass "webclient.History" to queryInterface(), which would set:

history = (History) wrapperFactory.newImpl(HISTORY_NAME, this);

this would be a reference to the BrowserControlImpl instance that is invoking newImpl(). The effect would be to cause wrapperFactory.newImpl() to set:

result = new HistoryImpl(this, browserControl);

this is a reference to the invoking WrapperFactoryImpl instance, wrapperFactory, while browserControl is a reference to the BrowserControlImpl instance that invokes wrapperFactory.newImpl().


BrowserControlCanvas is an abstract class that extends Canvas and is extended by a platform-specific class. BrowserControlCanvas has only one abstract method, getWindow(), which is implemented by the platform-specific class. For example, in the case of the Win32 platform, a class called Win32BrowserControlCanvas implements getWindow() by returning an int for the Window Handle (a unique 32-bit value that identifies the Window). It does this via the getHWnd() method of the WDrawingSurfaceInfo class in the package.


In the initialize() method of BrowserControlCanvas an argument of type BrowserControl is passed to it and a private variable of the same type, webShell, is set equal to it.


addNotify() is worth examining. It is at the heart of this class.

Note that when the BrowserControlCanvas implementation instance (such as browserCanvas in our example) is added to the Frame of an application, the addNotify() method of < code>BrowserControlCanvas is called and addNotify() generates wc, an instance of WindowControlImpl cast as type WindowControl. Let us take a closer look at how this is done and what is happening in the addNotify() method:

First, it gets the peer of the BrowserControlCanvas implementation instance and casts it as type DrawingSurface (sun.awt.DrawingSurface). Then it uses the < code>getDrawingSurfaceInfo() method of DrawingSurface to get the DrawingSurfaceInfo object dsi.

Next, windowRelativeBounds is set to new Rectangle(). windowRelativeBounds is a Rectangle at point (0,0) with width and height = 0.

Then, dsi is locked so that the information is not changed elsewhere, then dsi is passed to getWindow() to get an int called nativeWindow. getWindow(DrawingSurfaceInfo dsi) is an abstract method of BrowserControlCanvas that is implemented in the concrete class of which we have an instance. (Note: It is assumed that an instance of the implementation of BrowserControlCanvas would be created in a custom applications following the invocation of the setAppdata() method of BrowserControlFactory.)

Next, in the try block a new Rectangle is created by passing getBoundsRelativeToWindow() as an argument to the constructor for Rectangle.  getBoundsRelativeToWindow() returns a Rectangle object that has been translated so that its x and y data fields reference the Window of our custom application and not the particular container that it may be in within that Window.

Finally, WindowControl wc is created and its createWindow(int nativeWindow, Rectangle bounds) method is used to create the Window. createWindow() is discussed in detail under WindowControlImpl .

WrapperFactory, Wrapper FactoryImpl

WrapperFactory is an abstract class that allows for different types of browsers that might be embedded, native or non-native, and it has an important abstract method called newImpl() that is implemented by WrapperFactoryImpl. newImpl() is what is called by BrowserControlImpl.queryInterface() to actually get an instance of some browser function such as navigation, bookmarks, history, etc.

For example, if the navigation function is desired, that is, an instance of NavigationImpl, "webclient.Navigation" would be passed to BrowserControlImpl.queryInterface() and control would be passed to the following statement within that method:

if (NAVIGATION_NAME.equals(interfaceName)) {
        if (null == navigation) {
            navigation = (Navigation) wrapperFactory.newImpl(NAVIGATION_NAME,
        return navigation;

wrapperFactory in the test example is in fact an instance of WrapperFactoryImpl for the type of browser being embedded, and the WrapperFactoryImpl class is located in its own directory for that type; i.e., for Windows, it is located in wrapper_native.

wrapperFactory.newImpl() with NAVIGATION_NAME as the argument passes control to the following statement in WrapperFactoryImpl.newImpl():

if (BrowserControl.NAVIGATION_NAME == interfaceName) {
            result = new NavigationImpl(this, browserControl);
            return result;

Thus it creates the new instances of NavigationImp for the type of browser being embedded.

WrapperFactoryImpl.initialize() synchronizes on the instance of WrapperFactoryImpl and then invokes the native method nativeAppInitialize(). nativeAppInitialize() is called at the beginning of program execution to allow for one-time initialization of tasks. The native method initializes XPCOM and so on.


WindowControl is an interface that includes methods to create a window, control it, and get the native webshell.


An instance of WindowControlImpl is created via the addNotify() method of BrowserControlCanvas. addNotify() is called when an instance of an implementation of BrowserControlCanvas (such as an instance of win32BrowserControlCanvas) is added to the custom application.

BrowserControlCanvas.addNotify() uses the queryInterface() method of BrowserControlImpl via an instance of the latter called webShell, which is passed to the BrowserControlCanvas object via its initialize() method.

The createWindow() method is worth some attention. Following some preliminary checking, it locks myBrowserControl (the BrowserControlImpl object) and this (the WindowControlImpl object), then passes nativeWindow to nativeCreateInitContext(), along with other arguments, to obtain nativeWebShell. nativeWindow was created in BrowserControlCanvas.addNotify() via getWindow(), which gets, in the case of Win32, the Window Handle for the native Window. nativeCreateInitContext() is the native method for initialization.

Next, createWindow() creates eventThread, an instance of NativeEventThread. NativeEventThread extends java.lang.Thread and adds native methods. createWindow() starts the thread by invoking eventThread.start(), then invokes wait() on the main thread in a try block. eventThread.start() causes the thread to begin and invokes nativeInitialize(), which is a native method for initializing Mozilla. Following nativeInitialize() in, windowControl.notify() tells the main thread that it can run again.

Note that WindowControlImpl extends ImplObjectNative and implements WindowControl.


ImplObject defines two attributes for a number of the implementations of the Webclient interfaces. The two attributes are:

  • public WrapperFactory myFactory;
  • public BrowserControl myBrowserControl;

In the case of a native embedded browser, the implementations of the interfaces extend the subclass of ImplObject called ImplObjectNative. Two interfaces that do not extend the subclass are WrapperFactoryImpl and BrowserControlImpl.


ImplObjectNative, which is used for native embedded browsers, extends ImplObject. All implementations, other than WrapperFactoryImpl and BrowserControlImpl, extend it so as to provide easy access to the WrapperFactory and BrowserControl attributes.

ImplObjectNative provides a constructor that invokes getNativeWebShell().

Blackwood Release 0.9/Netscape PR3 - Last Modified 10/13/2000