Embedding Mozilla in a Java Application using JavaXPCOM

Obsolete since Gecko 4.0This feature is obsolete. Although it may still work in some browsers, its use is discouraged since it could be removed at any time. Try to avoid using it.

Warning: This technology is obsolete. No active maintainer has stepped forward, and the code broke in Firefox 4. The code has been removed from the Mozilla source tree.

XULRunner ships with the JavaXPCOM component, which allows Java code to interact with XPCOM objects. As you will see in this article, working with XPCOM objects in Java is not that much different than doing so in C++.

Prerequisites

Embedding

In order to embed Mozilla in your Java application, you will need to add the library MozillaInterfaces.jar (located in xulrunner/sdk/lib folder) to your classpath. This library provides the interfaces necessary to bootstrap Mozilla and call XPCOM methods.

To start embedding, we use the methods provided by the Mozilla singleton class. First, the Java application must find a suitable XULRunner installation:

The initEmbedding method kicks off the embedding process, allowing the Java application to work with XPCOM and Mozilla. Once the Java application is done using Mozilla, it needs to terminate the embedding process:

Working with XPCOM objects

Now that Mozilla is embedded, the Java application can work with XPCOM objects. The Mozilla class provides several methods to facilitate this, such as getServiceManager, getComponentManager, and newLocalFile. In addition to retrieving and calling methods on XPCOM objects, JavaXPCOM allows the Java application to pass Java class objects to XPCOM methods.

In this example, we have a Java class called WindowCreator, which implements the nsIWindowCreator interface, and we want to register it with Mozilla. To do so, we first get the service manager, through which we can get a reference to Mozilla's window watcher.

// Note, on linux, gtk has to be already initialized for this code to work
Mozilla moz = Mozilla.getInstance();
// Now we need to start an XUL application, so we get an instance of the XPCOM service manager
nsIServiceManager serviceManager = moz.getServiceManager();
// Now we need to get the @mozilla.org/toolkit/app-startup;1 service:
nsIAppStartup appStartup = (nsIAppStartup)serviceManager.getServiceByContractID("@mozilla.org/toolkit/app-startup;1", nsIAppStartup.NS_IAPPSTARTUP_IID);
// Get the nsIWindowWatcher interface to the above
nsIWindowCreator windowCreator = (nsIWindowCreator)appStartup.queryInterface(nsIWindowCreator.NS_IWINDOWCREATOR_IID);
// Get the window watcher service
nsIWindowWatcher windowWatcher = (nsIWindowWatcher)serviceManager.getServiceByContractID("@mozilla.org/embedcomp/window-watcher;1", nsIWindowWatcher.NS_IWINDOWWATCHER_IID);
// Set the window creator (from step 6)
windowWatcher.setWindowCreator(windowCreator);
// Create the root XUL window:
nsIDOMWindow win = windowWatcher.openWindow(null, "chrome://your-app/content/window.xul", "mywindow", "chrome,resizable,centerscreen", null);
// Set this as the active window
windowWatcher.setActiveWindow(win);
// Hand over the application to xpcom/xul, this will block:
appStartup.run();

Calling XPCOM UI from another thread

appStartup.run() enters the main event loop and will stay there until the application exits. In order to communicate with XPCOM after this point, you should use an nsIProxyObjectManager.

Following on from the above example, to create a new window, we would do the following:

// First, get the event queue service. This handles all event queues in XPCOM.
nsIEventQueueService eventQueueServive = (nsIEventQueueService)serviceManager.getServiceByContractID("@mozilla.org/event-queue-service;1",nsIEventQueueService.NS_IEVENTQUEUESERVICE_IID);
// Next, we want to get the UI thread, since we want to open a window. There is a static variable on the
// nsIEventQueueService that contains the id of the special UI event queue.
nsIEventQueue eventQueue = eventQueueServive.getSpecialEventQueue(nsIEventQueueService.UI_THREAD_EVENT_QUEUE);
// Now create a proxy for the proxy object manager.
nsIProxyObjectManager proxy = (nsIProxyObjectManager)componentManager.createInstanceByContractID("@mozilla.org/xpcomproxy;1",null,nsIProxyObjectManager.NS_IPROXYOBJECTMANAGER_IID);
// and use the proxy object manager to create a proxy for the nsIWindowWatcher instance we created above.
nsIWindowWatcher windowProxy = (nsIWindowWatcher)proxy.getProxyForObject(eventQueue,windowWatcher.NS_IWINDOWWATCHER_IID,windowWatcher,nsIProxyObjectManager.INVOKE_SYNC);
// now we use the proxy to call the method as usual.
windowProxy.openWindow(null, chromeUri, name, "centerscreen", null);