JavaXPCOM:Embedding Mozilla in a Java Application using JavaXPCOM
出典: MDC
XULRunnerにはJavaXPCOMが標準搭載されており、これは、JavaのコードとXPCOMの相互利用を可能にするものです。この記事で示すとおり、JavaでのXPCOMオブジェクトの操作は、C++の場合とそれほど大きな差はありません。
目次 |
[編集] 必要な環境
- Java 1.4.2 以降
- XULRunner 1.8.0.1 以降
[編集] 組み込み
Mozilla を Java アプリケーションに埋め込むためには、xulrunner/sdk/libフォルダーにあるMozillaInterfaces.jarというライブラリを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 クラスはこれの手助けをするメソッドを提供しており、たとえば、getServiceManager、getComponentManager、newLocalFileがあります。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からとられたものです。