JavaXPCOM:Embedding Mozilla in a Java Application using JavaXPCOM

Obsolete since Gecko 4.0
This 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

  • Java 1.4.2 or newer
  • XULRunner 1.8.0.1 or newer

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:

 Mozilla mozilla = Mozilla.getInstance();
 GREVersionRange[] range = new GREVersionRange[1];
 range[0] = new GREVersionRange("1.8.0", true, "1.9", false);
   // work with trunk nightly version 1.9a1  ^^
 
 try {
   File grePath = Mozilla.getGREPathWithProperties(range, null);
   LocationProvider locProvider = new LocationProvider(grePath);
   mozilla.initEmbedding(grePath, grePath, locProvider);
 } catch (FileNotFoundException e) {
   // this exception is thrown if greGREPathWithProperties cannot find a GRE
 } catch (XPCOMException e) {
   // this exception is thrown if initEmbedding failed
 }

LocationProvider is a class provided by the Java application. It implements the IAppFileLocProvider interface, and tells XPCOM where to find certain files and directories.

If your code cannot find the GRE and keeps throwing FileNotFoundExceptions during the getGREPathWithProperties(...) call, check whether you already registered the GRE on your system: GRE Registration

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:

 try {
   mozilla.termEmbedding();
 } catch (XPCOMException e) {
   // this exception is thrown if termEmbedding failed
 }

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.

For example:

 Mozilla mozilla = Mozilla.getInstance();
 WindowCreator creator = new WindowCreator();  // implements nsIWindowCreator
 
 nsIServiceManager serviceManager = mozilla.getServiceManager();
 
 nsIWindowWatcher windowWatcher = (nsIWindowWatcher) serviceManager
   .getServiceByContractID(NS_WINDOWWATCHER_CONTRACTID,
     nsIWindowWatcher.NS_IWINDOWWATCHER_IID);
 windowWatcher.setWindowCreator(creator);

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.

Another example: (taken from rayh.co.uk)

     // 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();

Here is an example of a LocationProvider that works :

       public class LocationProvider implements IAppFileLocProvider {

       private final File libXULPath;
       int counter = 0;
        
       public LocationProvider(File grePath) {
       this.libXULPath = grePath;
       }

       public File getFile(String aProp, boolean[] aPersistent) {
       File file = null;
       if (aProp.equals("GreD") || aProp.equals("GreComsD")) {
           file = libXULPath;
           if (aProp.equals("GreComsD")) {
               file = new File(file, "components");
           }
       }
       else if (aProp.equals("MozBinD") ||
                aProp.equals("CurProcD") ||
                aProp.equals("ComsD") ||
                aProp.equals("ProfD"))
           {
               file = libXULPath;
               if (aProp.equals("ComsD")) {
                   file = new File(file, "components");
               }
           }
       return file;
   }

   public File[] getFiles(String aProp) {
       File[] files = null;
       if (aProp.equals("APluginsDL")) {
           files = new File[1];
           files[0] = new File(libXULPath, "plugins");
       }
       return files;
   } 

}

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);

For more information, please see XulPlanet's documentation of nsIProxyObjectManager

This was taken from Injecting Events onto XPCOM’s UI Thread

Document Tags and Contributors

 Contributors to this page: Anonymous
 Last updated by: Anonymous,