webclient implementation guide
overview of primary classes and interfaces
The primary interfaces and classes for Webclient are:
BrowserControlFactory
BrowserControl
BrowserControlImpl
BrowserControlCanvas
WrapperFactory
WrapperFactoryImpl
WindowControl
WindowControlImpl
ImplObject
ImplObjectNative
Understanding the primary classes and interfaces is essential to knowing how Webclient works.
BrowserControlFactory
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()
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
"sun.awt.windows.WDrawingSurfaceIno".
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()
newBrowserControl() sets newCanvas to a new instance
of browserControlCanvasClass. It then does the following:
- passes
newCanvasto the constructor ofBrowserControlImplto get a new instance ofBrowserControlImplcalledresult; - checks both
newCanvasandresultto see if they arenull; - if neither is
null, then initializesnewCanvas, passingresultto theinitialize()method as follows:
newCanvas.initialize(result);
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.
Summary
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
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
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().
constructor
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()
appInitialize() is a
static method that sets
wrapperFactory = createWrapperFactory(), if the
static wrapperFactory variable
is null, and then invokes
initialize() on wrapperFactory.
Notes
wrapperFactoryis set as typeWrapperFactory, which is an abstract class.createWrapperFactory()is aprivate staticmethod ofBrowserControlImplthat returns an object of typeWrapperFactory.
createWrapperFactory()
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()
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
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 sun.awt.windows package.
initialize()
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()
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,
this);
}
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
WindowControl is an interface that includes methods to create
a window, control it, and get the native webshell.
WindowControlImpl
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
eventThread.run() invokes nativeInitialize(), which is
a native method for initializing Mozilla. Following nativeInitialize()
in NativeEventThread.run(), windowControl.notify()
tells the main thread that it can run again.
Note that WindowControlImpl extends ImplObjectNative
and implements WindowControl.
ImplObject
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
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