Stylishがどのようにして再起動なしでCSSを適用しているか調べてみた

Firefoxの拡張であるStylishを使用すると、再起動なしでスタイルシートを適用してWebページだけでなくFirefoxのインターフェースも変更することが出来る。
この動作がわかれば、Foxdieのようなサブスキンを内蔵したテーマで、再起動なしにサブスキンを試すことが出きると考え、その動作の仕組みを探ってみた。
とりあえず、タブの高さを40pxにするスタイルをStylishに書く。

@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);
tab.tabbrowser-tab {
  height: 40px;
}

DOM Inspectorで調べると「プレビュー(W)」ボタンは「chrome://stylish/content/edit.js」の「doPreview関数」を呼び出している事がわかるので、Venkmanでここにブレークポイントを設置して、実際にタブの高さが40pxになるところまで追いかけてみた。
結局、chrome://stylish/content/common.jsの

registerStyle: function(uri, css) {
	var cssURL = stylishCommon.codePrefix + css;
	var u = this.ios.newURI(cssURL, null, null);
	this.sss.loadAndRegisterSheet(u, this.sss.USER_SHEET);

this.sss.loadAndRegisterSheet(u, this.sss.USER_SHEET);

で適用されることがわかった。
ここで、各変数を調べてみると以下のようになっていた。

var cssURL = "data:text/css,@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);\ntab.tabbrowser-tab {\n  height: 40px;\n}"

this.ios = Components.classes["@mozilla.org/network/io-service;1"]
            .getService(Components.interfaces.nsIIOService)
this.sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
            .getService(Components.interfaces.nsIStyleSheetService)

var u = this.ios.newURI(cssURL,null,null);

整理すると以下のようなコードを書けばCSSを適用できることになる。

var myIOS = Components.classes["@mozilla.org/network/io-service;1"]
            .getService(Components.interfaces.nsIIOService)
var mySSS = Components.classes["@mozilla.org/content/style-sheet-service;1"]
            .getService(Components.interfaces.nsIStyleSheetService)
var myURL = "data:text/css,@namespace  url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);tab.tabbrowser-tab {height: 20px;}"
var myU = myIOS.newURI(myURL,null,null);
mySSS.loadAndRegisterSheet(myU, mySSS.USER_SHEET);

以外に簡単だ。
しかし検索して見ると、MDCに日本語訳された文章がのっていた。
今回の収穫は、newURIメソッドの第一引数には、"chrome://hogehoge..."だけでなく、"data:text/css,..."を使えることがわかっただけか。