Embedding Mozilla in a Java Application using JavaXPCOM

XULRunnerにはJavaXPCOMが標準搭載されており、これは、JavaのコードとXPCOMの相互利用を可能にするものです。この記事で示すとおり、JavaでのXPCOMオブジェクトの操作は、C++の場合とそれほど大きな差はありません。

必要な環境

組み込み

Mozilla を Java アプリケーションに埋め込むためには、<tt>xulrunner/sdk/lib</tt>フォルダーにある<tt>MozillaInterfaces.jar</tt>というライブラリをclasspathに追加する必要があります。このライブラリは Mozilla をブートストラップし、XPCOM メソッドを呼び出すために必要なインターフェースを提供します。

組み込みを開始するために、Mozilla共有クラスの提供するメソッドを使用します。はじめに、Java アプリケーションは適切な 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) {
   // この例外は greGREPathWithProperties が GRE を見つけられなかったときに送出されます
 } catch (XPCOMException e) {
   // この例外は initEmbedding が失敗したときに送出されます
 }

LocationProviderはJavaアプリケーションによって提供されるクラスです。これはインターフェースIAppFileLocProviderを実装しているもので、 and tells XPCOM where to find certain files and directories.

initEmbeddingメソッドは embedding process を開始するもので、Java アプリケーションと XPCOM や Mozilla の連携を可能にするものです。ひとたび Java アプリケーションが Mozilla を使う作業を終えたとき、それは embedding process を terminate する必要があります。

 try {
   mozilla.termEmbedding();
 } catch (XPCOMException e) {
   // この例外は termEmbedding が失敗したときに送出されます
 }

XPCOMオブジェクトを利用する

Mozilla が組み込まれると、Java アプリケーションは XPCOM オブジェクトを利用することができるようになります。Mozilla クラスはこれの手助けをするメソッドを提供しており、たとえば、getServiceManagergetComponentManagernewLocalFileがあります。JavaXPCOM により、 Java アプリケーションがXPCOM オブジェクトを取得し、メソッドを呼び出すのに加え、Java クラスオブジェクトを XPCOM メソッドに渡すことも可能になります。

例えば:

 Mozilla mozilla = Mozilla.getInstance();
 WindowCreator creator = new WindowCreator();  // nsIWindowCreator を実装
 
 nsIServiceManager serviceManager = mozilla.getServiceManager();
 
 nsIWindowWatcher windowWatcher = (nsIWindowWatcher) serviceManager
   .getServiceManagerByContractID(NS_WINDOWWATCHER_CONTRACTID,
     nsIWindowWatcher.NS_IWINDOWWATCHER_IID);
 windowWatcher.setWindowCreator(creator);

この例では、nsIWindowCreatorインターフェースを実装した Java のクラスであるWindowCreatorが存在し、それを Mozilla に登録しようとしています。そのために、まず service manager を取得するのですが、それは Mozilla のwindow watcherのリファレンスにある方法によります。

別の例: (rayh.co.ukにあるもの)

     // linux 上ではこのコードが実行されるより前に gtk が初期化されている必要があることに注意
     Mozilla moz = Mozilla.getInstance();
 
     // 次に XUL アプリケーションを実行するために、XPCOMのservice managerのインスタンスを取得する必要がある
     nsIServiceManager serviceManager = moz.getServiceManager();
 
     // 次に @mozilla.org/toolkit/app-startup;1 サービスを取得する必要がある
     nsIAppStartup appStartup = (nsIAppStartup)serviceManager.getServiceByContractID("@mozilla.org/toolkit/app-startup;1", nsIAppStartup.NS_IAPPSTARTUP_IID);
 
     // 上のものへの nsIWindowWatcher インターフェースを取得する
     nsIWindowCreator windowCreator = (nsIWindowCreator)appStartup.queryInterface(nsIWindowCreator.NS_IWINDOWCREATOR_IID);
 
     // window watcher サービスを取得する
     nsIWindowWatcher windowWatcher = (nsIWindowWatcher)serviceManager.getServiceByContractID("@mozilla.org/embedcomp/window-watcher;1", nsIWindowWatcher.NS_IWINDOWWATCHER_IID);
 
     // window creator をsetする (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);
 
     // これを active window にする
     windowWatcher.setActiveWindow(win);
 
     // application を xpcom/xul に手渡し、ここでブロックする:
     appStartup.run();

これは動作する LocationProvider の例です :

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


XPCOM の UI を別のスレッドから呼び出す

appStartup.run() はメインのイベントループを始動し、アプリケーションが終了するまでそこに留まります。これ以降の場所で XPCOM とcommunicateするためには、nsIProxyObjectManager を使用する必要があります。

上の例に引き続き新しいウインドウを作成するためには、このようにします :

 // まず、event queue service を取得します。これは、XPCOM の全てのイベントキューを処理するものです。
 nsIEventQueueService eventQueueServive = (nsIEventQueueService)serviceManager.getServiceByContractID("@mozilla.org/event-queue-service;1",nsIEventQueueService.NS_IEVENTQUEUESERVICE_IID);
 
 // 次に、ウインドウを開くために、UI スレッドを取得します。
 // nsIEventQueueService が所有するstatic変数がUIイベント用の特別なキューを所有しています。
 nsIEventQueue eventQueue = eventQueueServive.getSpecialEventQueue(nsIEventQueueService.UI_THREAD_EVENT_QUEUE);
 
 // 次に、proxy object manager 用の proxy を作成します。
 nsIProxyObjectManager proxy = (nsIProxyObjectManager)componentManager.createInstanceByContractID("@mozilla.org/xpcomproxy;1",null,nsIProxyObjectManager.NS_IPROXYOBJECTMANAGER_IID);
 
 // そして、proxy object manager を使って、さきほど作成した nsIWindowWatcher のインスタンスへの proxy を作成します。
 nsIWindowWatcher windowProxy = (nsIWindowWatcher)proxy.getProxyForObject(eventQueue,windowWatcher.NS_IWINDOWWATCHER_IID,windowWatcher,nsIProxyObjectManager.INVOKE_SYNC);
 
 // そうすれば、proxy を使ってメソッドを普通に呼び出すことができます。
 windowProxy.openWindow(null, chromeUri, name, "centerscreen", null);

さらに詳しい情報は、XulPlanet's documentation of nsIProxyObjectManagerを参照してください。

これは、Injecting Events onto XPCOM’s UI Threadからとられたものです。

ドキュメントのタグと貢献者

 このページの貢献者: Luna8bit
 最終更新者: Luna8bit,