A script from "http://localhost:8080" was denied UniversalXPConnect privileges.

Log4Jsを使用していた際の話。

次のようなエラーがでた。ブラウザはfirefox*1
[[A script from "http://localhost:8080" was denied UniversalXPConnect privileges.]]

エラーの原因は、次の一行があるためだった。

var appender = new Log4js.MozillaJSConsoleAppender();

Log4JsのMozillaJSConsoleAppender()が原因のようだ。
というわけで、この関数のコードを確認したら、次のような実装になっていた。

Log4js.MozillaJSConsoleAppender = function() {
	this.layout = new Log4js.SimpleLayout();
	try {
		netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
		this.jsConsole = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
		this.scriptError = Components.classes["@mozilla.org/scripterror;1"].createInstance(Components.interfaces.nsIScriptError);
	} catch (e) {
		log4jsLogger.error(e);
	}
};

XPConnectを使っている*2。。。

ここで落ちているのかと思った。しかし、XPConnectを使用する前に、

netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");

を実行してUniversalXPConnect特権を得ている。特権を得ようとした時点で、特権を得るための許可をブラウザのユーザに求めるダイアルログがでるはずだが、でていない。原因がわからない。

方針を変える。FirefoxのURLバーに、about:configと打ち込む。
変数signed.applets.codebase_principal_supportの値がデフォルトではfalseだが、それをtrueに変更した。
すると、UniversalXPConnect特権特権を得るためのダイアログが表示され、そこで許可を出すとエラーはでなかった。

ググって調べたら、次の記事が見つかった。

署名されていないスクリプトで各種の特権を取得する方法

この記事には次のようにあった(一部書き方を変えました)。

  • netscape.security.PrivilegeManager.enablePrivilege()は、http://〜といったURIでアクセスするリソースでは使えない。
  • 署名されたスクリプトと特権についてのmozilla.orgの技術文書(2006.6.27現在では英語版のみ)によれば、先のような特権の取得を求めるコードは、現在は電子署名済みのスクリプトでしか利用できなくなったそうな。しかし、Codebase Principal(s)といういくらか弱いセキュリティ機構を使うことによって、署名されていないリモートのスクリプトでも特権を取得できるようになるらしい。

結局、about:configの設定は元に戻し、Log4jsのMozillaJSConsoleAppenderの使用はやめることにしようと思いました。

*1:ちなみに、IEだと「TypeError: 'netscape' は宣言されていません。」となる。MozillaJSConsoleAppenderはMozilla系ブラウザ用だから当然。

*2:XPConnectとは、JavaScriptからXPCOMを利用する技術。