このサイトの記事更新は2019年11月に終了されました。過去記事アーカイブを公開しています。

投稿されたすべてのトピック

プラグインによるクラッシュを防ぐ Firefox ベータ版「Lorentz」が公開されました

現在開発中の Firefox 3.7 (アルファ版は Mozilla Developer Preview として公開されています) では、プラグインの実行プロセスをブラウザから分離して、プラグインがクラッシュしても Firefox が巻き添えにならないようにする取り組みが進められていますが、今日、この仕組みを Firefox 3.6.3 に取り込んだベータ版「Lorentz」が公開されました。Adobe Flash Player、Apple QuickTime Player、Microsoft Silverlight の各プラグインがクラッシュもしくはフリーズしたときに、Firefox 本体へ影響が及ばないようになっています。

テストにご協力いただける方は、Lorentz をインストールして Flash を使用しているサイトを積極的に訪れ、クラッシュが起きた場合はレポートを送信してください。ページを再読み込みすればプラグインコンテンツを再度表示してみることができます。また、他に予期せぬ問題に遭遇した場合は、いつも通り Bugzilla にバグを登録 してください。

Lorentz は Windows と Linux のみに対応しています。Mac 版も公開されていますが、ソースコードの変更が Mac 版に影響しないことを確認するためのもので、プロセス分離はまだ実装されていません。Lorentz の最終版は 5 月上旬に Firefox 3.6.4 として公開される予定です。

追記: 3.6.3plugin1 の日本語版はありません。次のベータ版か、遅くとも正式版には日本語版が追加されます。

modest の Google Group を作成しました

Mozilla Developer Street (modest) では、Mozilla 関連の開発者や利用者が集まり、みんなの知識やアイデアを共有、ディスカッションあるいは質問などが自由にできるコミュニティサイトを目指しています。

ユーザ登録するか OpenID でログインすれば誰でもページの編集トピックの投稿ができるようになっていますので、拡張機能開発テクニックのような、他の方にも役立つ情報や Tips などはいわゆる「まとめサイト」のようにページを編集していっていただいたり、イベントや勉強会などの告知や参加レポートなどをどんどん投稿していっていただければ幸いです。

一方で、サイト上のコンテンツだけでなく、アドオン開発や HTML5 などの Open Web 技術について疑問があるときなどに、気軽に質問などができる場所も欲しいというリクエストをいただくようになってきました。そこで、先日の Mozilla 勉強会@東京 2nd で確認の上、modest コミュニティの Google Group を作ることになりました。

http://groups.google.com/group/mozilla-developer-street

これからは modest サイトと合わせて modest Google Group もご利用ください。

Minefield 3.7a4preでのtabbrowser要素の仕様変更点まとめ

Mozilla 勉強会@東京 2ndで、Firefox 3.6からFirerfox 3.7a4preの間で仕様が大きく変更されたtabbrowser要素に関するトピックのまとめを発表しました。以下にプレゼン資料を公開していますのでご覧下さい。

プレゼン中では、仕様の変更によってどんな影響があるのか、アドオンを開発する際にはどこに気をつけなくてはならないのかについて、図を交えつつ解説しています。資料の内容は2010年4月3日時点での状況に基づいており、今後また仕様が変わる可能性もありますのでご注意下さい。

Firefox 3.7でのjs-ctypes

現在js-ctypesは開発中のため、今後仕様が変わる可能性があります。

去年行われたFirefox Developers Conference 2009でjs-ctypesについて説明しましたが、いくつかの制限があり、Firefox 3.6で使える状況はあまりなかったかと思います。現在開発を行っているFirefox 3.7では、js-ctypesが大幅に改良される予定で、現在のビルドでは、構造体のサポートやコールバック関数のサポートが含まれます。今回は構造体の使用について説明します。

この説明では、Windowsに含まれるカラーピッカー(色の選択をするダイアログ)を表示する例を挙げます。

Windowsでカラーピッカーを表示するAPIは、ChooseColorです。この関数は引数として以下の構造体のポインタを持ちます。

typedef struct {
 DWORD        lStructSize;
 HWND         hwndOwner;
 HWND         hInstance;
 COLORREF     rgbResult;
 COLORREF     *lpCustColors;
 DWORD        Flags;
 LPARAM       lCustData;
 LPCCHOOKPROC lpfnHook;
 LPCTSTR      lpTemplateName;
} CHOOSECOLOR, *LPCHOOSECOLOR;

これをctypes.StructTypeを利用して、js-ctypesで定義します。この例では、使わないメンバはuint32_tにしていますが、lpTemplateNameは文字列のポインタとして定義するのが正しいです。

var custColors_type = ctypes.ArrayType(ctypes.int32_t, 16);
const CHOOSECOLOR = new ctypes.StructType(
 'CHOOSECOLOR',
 [
  {'lStructSize': ctypes.uint32_t},
  {'hwndOwner' : ctypes.uint32_t},
  {'hInstance' : ctypes.uint32_t},
  {'rgbResult' : ctypes.uint32_t},
  {'lpCustColors' : custColors_type.ptr},
  {'Flags' : ctypes.uint32_t},
  {'lCustData' : ctypes.uint32_t},
  {'lpfnHook' : ctypes.uint32_t},
  {'lpTemplateName' : ctypes.uint32_t}
 ]);

構造体の定義が終わったら、関数を定義しましょう。定義方法は変わりませんが、引数でポインタ型を渡しています。

var comdlg32 = ctypes.open("comdlg32");
var ChooseColor = comdlg32.declare("ChooseColorW", ctypes.stdcall_abi, ctypes.int32_t, CHOOSECOLOR.ptr);

関数を呼び出すために、値をセットします。構造体のメンバにポインタを渡す必要があるため、addressを利用します。

var custColors = new custColors_type();
var col = new CHOOSECOLOR (CHOOSECOLOR.size, 0, 0, 0, custColors.address(), 0, 0, 0, 0);

値を作成したので、関数を呼び出しましょう。

ChooseColor(col.address());

そうすると、col.rgbResultにユーザーが選択した色の値がセットされますので、それを参照するとどの色を選択したかがわかります。

alert(col.rgbResult);

このように、構造体を引数に持つ関数の呼び出し方法が追加されています。これでjs-ctypesが利用できる範囲も広くなったと思います。次は、コールバック関数の利用について説明したいと思います。

なお、今回サンプルで作成したすべてのコードは以下になります。

Components.utils.import("resource://gre/modules/ctypes.jsm");

var custColors_type = ctypes.ArrayType(ctypes.int32_t, 16);
const CHOOSECOLOR = new ctypes.StructType(
 'CHOOSECOLOR',
 [
  {'lStructSize': ctypes.uint32_t},
  {'hwndOwner' : ctypes.uint32_t},
  {'hInstance' : ctypes.uint32_t},
  {'rgbResult' : ctypes.uint32_t},
  {'lpCustColors' : custColors_type.ptr},
  {'Flags' : ctypes.uint32_t},
  {'lCustData' : ctypes.uint32_t},
  {'lpfnHook' : ctypes.uint32_t},
  {'lpTemplateName' : ctypes.uint32_t}
 ]);

var comdlg32 = ctypes.open("comdlg32");
var ChooseColor = comdlg32.declare("ChooseColorW", ctypes.stdcall_abi, ctypes.int32_t, CHOOSECOLOR.ptr);

var custColors = new custColors_type();
var col = new CHOOSECOLOR (CHOOSECOLOR.size, 0, 0, 0, custColors.address(), 0, 0, 0, 0);

ChooseColor(col.address());
alert(col.rgbResult);

about:hacks – Mozilla’s newsletter for web developers – Issue 3

このニュースレターは現在翻訳者募集中です。部分的にでも翻訳にご協力いただける方はログインしてこのページを編集してください。

ようこそ

これは Mozilla の Web 開発者向けニュースレター about:hacks の第3号です。このニュースレターは Mozilla Developer Network サイトでニュースの受信登録をした方に email で配信しています。ニュースレターの配信停止をご希望の方は、このメールの最後の部分をご覧ください。このニュースレターに関するご要望や、トピックを取り上げて欲しいトピックなどありましたら、ご連絡ください。

目次

Mozilla Developer Previews

この2〜3週間で、いくつかのMozilla Developer Previewを作成しました。これらのプレビューでは、次バージョンのFirefoxを味見程度ですが体験することができます。これまでにMozilla Developer Preview 1.9.3a1(2/10リリース)、1.9.3a2(3/3リリース)、1.9.3a3(3/15にこっそりリリース)の3バージョンが公開されています。ここ数ヶ月、我々はリリース手法を変えることに取り組んでいます。たくさんのテーマを含んだαバージョンやβバージョンをリリースするのではなく、いくつかのテーマを含んだバージョンを2週間くらいの間隔でテンポ良くリリースしています。各バージョンに含まれているテーマは以下の通りです。

  • a1リリースではバージョン3.6からのブランチの最初のバージョンで、以前のabout:hacksでご紹介した新しいウェブ開発機能を追加しました。
  • a2リリースではWindowsとLinux用のOut of Processプラグインを含んでいます。すでに使うことが可能ですが、更に安定性が強化され、Firefox 3.6にも反映されています(Firefox 3.6のOut of Processプラグインは「Lorentz」という名称で個別に開発されており、そのうちお披露目されることでしょう)。
  • a3リリースは、Windows上でのD2Dサポートを向上したバージョンです。D2Dがサポートされることにより、CanvasやSVGなどの画像を扱う機能がWindows 7とVistaで非常に高速に動作します。D2Dの詳細に関しては、後述の記事を参照してください。

Developer Previewに興味がある方は、上記の各バージョンのリンクからインストールを行ってください。日常で使用しても問題ない程度の安定性を持っており、アップデートがあった場合には自動的に更新されます。ウェブ開発者であれば、これはすごく良いチャンスです。Firefoxに追加される次世代のウェブ機能を、事前にテストすることができるのですから。使用していて万が一性能の劣化を発見した場合には、我々にレポートしてください(開発ルールとしては性能向上以外ありえませんが、念のため)。

Firefox 3.6 / Firebug 1.5 フィードバック

Have you been running Firefox 3.6 and the latest release of Firebug? If so, we want to know how it’s working for you. Let us know what you think about the latest versions of Firefox and Firebug. This is the best way to get feedback to the Firebug team. We want to know if it’s awesome or buggy, crashy or runs faster or doesn’t do something you need. So be sure to fill out the survey! It only takes 3 minutes, tops.

Mozilla Developer Network (MDN) のアップデート

Thanks to everyone that provided feedback on the initial round of MDN logo concepts. Your input allowed us to go back to our partner, Studio Number One, with a clear vision of what we needed to create and after a few more iterations, we now have an official logo for the Mozilla Developer Network!

Next up is the MDN website design work with Happy Cog. For the latest on that project, be sure to keep an eye on the MDN wiki. We will continue to share progress with you and look forward to more feedback throughout the design process.

Over the next couple of months we’ll start rolling out larger designs for the new larger MDN site beyond just the logo. So stay tuned!

デモ

Parallax Scrolling with HTML5 Backgrounds

これは紹介する価値のあるおもしろいデモ (このデモページの中央に実際のデモがあります) だと私たちは思いました。他のテキストの後ろでアニメーションを行うことできます。これを実現するためににcanvas、SVGまたはFlashを使用する必要はありません。少しのJavaScriptとCSS backgroundでこれを実現しています。

Harmony

We’re including Harmony because we really like it. It’s a pretty simple-looking drawing program that you can use to build some absolutely beautiful things. In fact, there’s an Facebook group that has images that people have created. There are five pages of beautiful sketches in there. Take some time and poke around. And, of course, it’s all based on Canvas.

Behind the Scenes

D2D

Direct2D はマイクロソフトの Windows 7 と (アップデートをインストールした) Windows Vista で利用可能になったテクノロジーです。このニュースレターを受け取るMacユーザーなどの多くの人にとっては興味がないかもしれないですが、Windowsユーザーは、Web を使う割合が多くを占めており、そのユーザーたちにとっては重要です。この機能の1つにハードウェアアクセラレーションがあり、これを使うことでグラフィックの描画をより速くすることができます。一つの例として、ここにWebKitに関わるアップルのエンジニアによるスプレットシートがあります。D2DとD2Dを使わない状況での比較が一番上にありますが、項目によっては800倍近く速くなっています。これはハードウェアアクセラレーションの利用が良い結果を出すということを証明しています。

800といってもそれは数字にすぎません。私たちがいろいろと見た比較例の中の一つにHans Schmuckerによる、グラフィックをスムーズに操作することを行うだけの本当に狂ってるデモがあります。デモ (もしこれを表示した時、あなたのコンピュータを悲しませることになるかもしれません) はただ単にFirefox ロゴをアニメーションするだけです。 What he did, though, was to put that same animation in a bunch of browsers and turn it into a movie so you can really see the difference.

We’ll be talking more about this as we get closer to release and it’s been more widely tested. もしあなたが、アルファ3ビルドをWindows上で利用することが可能であれば、Bas がポストしたブログにこの機能を有効にする方法が書かれていますので、試すことが可能です。

Are We Fast Yet? – A JägerMonkey Update

This is the coder’s badge of glory, That he protect and tend his monkey, Code with honor, as is due, And through the bits to God is true. –damons, IRC

Want to know if we’re fast yet? The page says “NO” but we’re making a huge amount of progress. Those graphs can be confusing, so here’s some background:

  • Lower is better.
  • The two lines along the bottom are the V8 engine and the Nitro engine from Apple.
  • The top brownish line is the interpreter without any kind of acceleration or tracing.
  • The purple line is the one that matters. That’s the new engine that takes the well-known techniques from V8 and the engine in Safari and bolts our tracing from Firefox 3.5 and 3.6 onto its back. After only a few weeks it’s on par with our relatively mature tracing code and that’s without big chunks of the JägerMonkey code base online yet.

So basically we’re making a huge amount of progress on making our JS engine super-fast. We’ll learn a lot more about how the hybrid approach works over the next couple of months and then we’ll be able to figure out when we can get it into a working release.

For more background on JagerMonkey, have a look at the hacks post on it and the follow-up.

New on MDC

Work on the Mozilla Developer Center is progressing on multiple fronts: documentation for future Firefox features is ongoing, and we’re working toward deploying a significant update to the MindTouch software that powers the site — an update that should improve performance and reliability. See http://bit.ly/bsFavy for details. In other news, we’re looking to hire another writer! If you love the open web and grok HTML, C++, JavaScript, and the other things that make the web awesome, check out our opening: http://bit.ly/bZbpYX

ご意見をお待ちしています

about:hacks で扱う問題にはみなさまからの質問の答えも含ませていきたいと考えています。このニュースレターで思ったこと、次回のニュースレターでカバーしてもらいたいことなど、ぜひご意見を下さい

はじめての Jetpack SDK 0.2

先日 Mozilla Labs のサイトにて Jetpack SDK の新バージョンである SDK 0.2 が公開されました。SDK 0.2 では、 SDK 0.1 で見つかった Windows 上での不具合などが修正されています。 SDK 0.2 は依然として API は充実しておらず、実用的な機能を手軽に作ることはできませんが、 SDK を用いた開発の雰囲気を一通り味わうことができます。

この記事では SDK 0.2 による開発環境のセットアップから始め、 SDK 0.2 を使用して実際に簡単な機能を開発するための手順を解説します。なお、 OS は Windows を前提としますが、おおよその手順は他の OS でも大差無いと思います。

Python インストール

Jetpack SDK を動作させるには Python のインストールが必要となります。インストール方法は OS によって異なると思いますが、 Windows の場合、 Python Japan User’s Group のサイトから Windows 用インストーラの「python-2.6.2.msi」をダウンロードし、ウィザードに従ってインストールを実施します。ここでは、インストール先を「C:\Python26\」とします。

インストール完了後、コマンドラインにて「python」コマンドを有効にするため、 Windows のユーザー環境変数の変数「Path」へ値「C:\Python26」を追加(すでに別の値が存在する場合は「;」で区切って追加)し、 Python インストール先フォルダへのパスを通します。スタートメニューの「ファイル名を指定して実行」で「cmd」と入力してコマンドプロンプトを起動し、「python -V」と入力して「Python 2.6.2」と出力されることを確認します。

C:\>python -V
Python 2.6.2

なお、 Jetpack SDK Docs には Python 2.5 以上のバージョンが必要と記載されていますが、現在のところ Python 3.0.1 には対応していないようです。また、 Windows の場合は「Windows 用拡張モジュール」が必要と記載されていますが、実際はインストールしなくても問題ないようです。

Jetpack SDK セットアップ

次に、 Jetpack SDK のセットアップを行います。 Mozilla Labs のサイトから Jetpack SDK 0.2 のパッケージをダウンロードし、お好みの位置へ展開します。ここでは、「C:\jetpack-sdk-0.2」へ展開するものとします。

Jetpack SDK を使用する際は、毎回最初に「活性化」させる必要があります。コマンドプロンプトを起動し、 Jetpack SDK パッケージ展開先フォルダへ移動し、「bin\activate」と入力します。

C:\jetpack-sdk-0.2>bin\activate
Welcome to the Jetpack SDK. Run 'cfx docs' for assistance.
(C:\jetpack-sdk-0.2) C:\jetpack-sdk-0.2>

引き続き、「cfx docs」コマンドを入力して SDK ドキュメントをブラウザで表示します。SDK ドキュメントはポート8888を待ち受けポートとしたローカルのWebサーバ上で表示されます。

(C:\jetpack-sdk-0.2) C:\jetpack-sdk-0.2>cfx docs
One moment.
Opening web browser to http://127.0.0.1:8888.

パッケージのフォルダ構成

Jetpack SDK で開発する機能の単位をパッケージと呼びます。ここからは、単純な hello-world パッケージを作成する手順へと移りますが、その前に hello-world パッケージが最終的にどのようなフォルダ構成となるかを、下表に示します。

フォルダ/ファイル 概要
フォルダjetpack-sdk-0.2 Jetpack SDK 展開先フォルダ
フォルダpackages パッケージ格納フォルダ
フォルダhello-world パッケージのルートフォルダ
ファイルpackage.json マニフェストファイル
ファイルREADME.md ドキュメントファイル
フォルダlib プログラム格納フォルダ
ファイルmain.js メインプログラム
ファイルsimple-dialog.js 自作ライブラリ

Jetpack SDK を展開したフォルダの下の「packages」フォルダ内に個々のパッケージのルートフォルダがあり、その下には「package.json」という名前のマニフェストファイルがあります。「README.md」はパッケージの詳細を記述するためのドキュメントファイルで、必要に応じて配置します。「lib」フォルダ内には、パッケージのメインプログラムや自作ライブラリのプログラムを格納します。

パッケージの作成

それでは、「C:\jetpack-sdk-0.2\packages」フォルダ下に hello-world パッケージ用の「hello-world」フォルダを作成します。次に、パッケージのルートフォルダ内にマニフェストファイル「package.json」を作成します。マニフェストファイルにはパッケージに関するメタ情報を JSON 形式で記述します。拡張機能を作成したことのある方であれば、インストールマニフェスト「install.rdf」に近いものと考えてください。ここでは、以下のような内容を記述します。

{
    "id": "helloworld@xuldev.org",
    "version": "0.1",
    "description": "This is my first package.",
    "author": "Gomita <gomita@xuldev.org>"
}

"id" プロパティはすべての拡張機能および Jetpack パッケージを一意に識別するための文字列で、一般的にはメールアドレスのような形式にします。拡張機能のインストールマニフェストの <em:id> タグに相当します。

次に、さきほどブラウザで開いた SDK ドキュメントのページを更新し、「Package Reference」に「hello-world」が追加されたことを確認してください。

プログラムの作成

引き続き、 hello-world パッケージへメインプログラムを追加して、動作できるようにします。パッケージのルートフォルダの下に「lib」フォルダを作成します。「lib」フォルダ内にメインプログラムである「main.js」ファイルを作成し、以下のような内容を記述してください。

exports.main = function(options, callbacks) {
    console.log("Hello, World!");
};

メインプログラムは「main」という名前のひとつのモジュールとなっており、 CommonJS 形式の exports.main = ... という記法によって main プロパティのみをモジュール外部からアクセス可能にします。また、 console.log は Jetpack 標準のグローバル関数のひとつで、 Jetpack SDK のコマンドプロンプトへデバッグ用文字列を出力します。

なお、現時点では console.log("こんにちは"); のように日本語を記述しても、正常に動作しません。将来的に提供されるはずのローカライズ用APIを利用することになるはずです。

テスト実行

メインプログラムを作成したら、さっそくテスト実行してみます。テスト実行するには SDK のコマンドプロンプトへ「cfx run -a firefox」コマンドを入力します。「cfx run」コマンドへ「-a firefox」オプションを付加することで、新規の Firefox プロファイルへ先ほど作成したパッケージのみがインストールされた状態で Firefox が起動します。

(C:\jetpack-sdk-0.2) C:\jetpack-sdk-0.2>cd packages\hello-world

(C:\jetpack-sdk-0.2) C:\jetpack-sdk-0.2\packages\hello-world>cfx run -a firefox
info: Hello, World!
OK
Total time: 1.531000 seconds
Program terminated unsuccessfully.

Firefox 起動後、コマンドプロンプトに「info: Hello, World!」と表示されることを確認してください。Firefox のウィンドウをすべて閉じると、テスト実行も終了します。

標準ライブラリの使用

ここからは、 Jetpack 標準ライブラリのひとつである timer ライブラリを使用して、さきほどのプログラムを少し変更してみます。 timer ライブラリはタイマー関連の処理をひとまとめにしたモジュールで、 DOM の window.setTimeout, window.clearTimeout などとほぼ同等の機能を提供します。ライブラリの詳細を調べるには、 SDK ドキュメントを参照してください。なお、 SDK ドキュメントには記載されていませんが、 timer.setInterval, timer.clearInterval も利用可能です。

メインプログラム内でライブラリをインポートして利用可能にするには、 CommonJS 形式の require 関数を使用します。メインプログラム「main.js」を下記のように修正してください。

var timer = require("timer");

exports.main = function(options, callbacks) {
    timer.setInterval(function() {
        console.log(new Date().toLocaleTimeString());
    }, 1000);
};

修正後、「cfx run -a firefox」コマンドでテスト実行し、以下のように SDK のコマンドプロンプトへ1秒おきに現在時刻が出力されることを確認してください。

(C:\jetpack-sdk-0.2) C:\jetpack-sdk-0.2\packages\hello-world>cfx run -a firefox
info: 10:37:21
info: 10:37:22
info: 10:37:23
info: 10:37:24
info: 10:37:25

自作ライブラリの作成

ここからは、 Jetpack 標準ライブラリには無い機能を、自作ライブラリとして作成する手順に移ります。拡張機能や Jetpack パッケージ内でファイル読み書きなどの高度な処理を行う場合、 XPCOM と呼ばれるコンポーネントを呼び出す必要があります。 Jetpack には、 XPCOM を使用する高度な処理はモジュール化してメインプログラムから切り離すという設計思想があります。今のところ、ライブラリだけでなくメインプログラム内でも制限なく XPCOM を利用可能ですが、もしかすると将来的にはメインプログラム内では XPCOM 使用不可となる可能性があります。したがって、 XPCOM を使用する処理は極力ライブラリとして実装した方がいいと思われます。

ここでは、 DOM の window.alert のような単純なモーダルダイアログを表示する simple-dialog ライブラリを実装してみます。 Jetpack のプログラムのコンテクストには DOM でおなじみの windowdocument といったオブジェクトが無いため、 window.alert 関数も使用できません。このようなコンテクストでダイアログを表示するためには、 nsIPromptService という XPCOM を使用します(参考)。まず、パッケージのルートフォルダ下の「lib」フォルダ内に「simple-dialog.js」ファイルを作成します。メインプログラム同様にライブラリは exports.メソッド名 = function(...) { ... }; のような CommonJS 形式で実装していきます。

ここでは、 simple-dialog ライブラリに下表の2つのメソッドを実装します。

メソッド 概要
alert(text) 引数 text のラベルとOKボタンを有する警告ダイアログを表示する。
DOM の window.alert と同等。
confirmYesNo(text) 引数 text のラベルと「はい」「いいえ」ボタンを有する確認ダイアログを表示する。
メソッドの戻り値は真偽値で、ユーザが「はい」ボタン押下時は true を返す。

「simple-dialog.js」には、以下のように記述します。

var promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"].
                getService(Ci.nsIPromptService);

exports.alert = function(text) {
    promptSvc.alert(null, "[Jetpack]", text);
};

exports.confirmYesNo = function(text) {
    var pos = promptSvc.confirmEx(
        null, "[Jetpack]", text, promptSvc.STD_YES_NO_BUTTONS,
        null, null, null, null, {}
    );
    return pos == 0;
};

1~2行目は、 nsIPromptService を呼び出す処理です。なお、 Cc, Ci はそれぞれ Components.classes, Components.interfaces への参照であり、 Jetpack 標準のグローバル変数として定義済みです。4~6行目は simple-dialog ライブラリの alert メソッドの実装で、 nsIPromptService の alert メソッドを使って警告ダイアログを表示します。8~14行目は simple-dialog ライブラリの confirmYesNo メソッドの実装で、 nsIPromptService の confirmEx メソッドを使って「はい」「いいえ」ボタン付きの確認ダイアログを表示します。 nsIPromptService の confirmEx メソッドはユーザが押したボタンの番号(「はい」は 0、「いいえ」は 1)を返す仕様ですので、 confirmEx メソッドの戻り値が 0 なら confirmYesNo メソッドは true を返すようにします。

自作ライブラリの使用

先ほど作成した simple-dialog ライブラリをメインプログラムで呼び出し、正常に動作するかを確認します。「main.js」を下記のように修正してください。

var simpleDialog = require("simple-dialog");

exports.main = function(options, callbacks) {
    var adult = simpleDialog.confirmYesNo("Are you over 18 years old?");
    if (adult) {
        simpleDialog.alert("Welcome!");
    }
    else {
        simpleDialog.alert("Good bye!");
    }
};

「cfx run -a firefox」コマンドでテスト実行し、以下のように「はい」「いいえ」ボタン付き確認ダイアログが表示されることを確認してください。また、「はい」「いいえ」それぞれのボタン押下時に適切な警告ダイアログが表示されることを確認してください。

オフライン状態監視機能の実装

ここからは、 hello-world パッケージを修正して、もう少し実用的な機能を実装してみます。 Jetpack 標準ライブラリのひとつである observer-service ライブラリを使い、 Firefox のオンライン/オフライン状態の変化を監視する機能を実装します。

Firefox の内部ではアプリケーションに関する色々なイベントを nsIObserverService という XPCOM によってオブザーバへ通知しています。 Firefox がオフライン状態になったとき、トピック名「network:offline-status-changed」の通知が送信されます。この通知を受けて何らかの処理を実行するには、 observer-service ライブラリの add メソッドを使用します。add メソッドの第1引数には監視する通知のトピック名、第2引数には通知を受けた際に実行するコールバック関数を設定します。コールバック関数には、2つの引数が渡されますが、オフライン状態が変化した際には、第2引数に「online」または「offline」の文字列が渡されます。ここでは、この文字列の値を調べて、状況に応じた内容のダイアログを simple-dialog ライブラリを使って表示させます。

var simpleDialog = require("simple-dialog");
var observer = require("observer-service");

exports.main = function(options, callbacks) {
    observer.add("network:offline-status-changed", function(sbj, data) {
        if (data == "online") {
            simpleDialog.alert("Firefox is now online.");
        }
        else if (data == "offline") {
            simpleDialog.alert("Firefox is now offline.");
        }
    });
};

「cfx run -a firefox」コマンドでテスト実行し、 Firefox 起動後に [ファイル] → [オフライン作業] のチェックボックスをオフにし、以下のようなダイアログが表示されることを確認してください。

ドキュメントの作成

各パッケージについての詳細なドキュメントを追加することで、 SDK ドキュメントの各パッケージのリンクをクリックしたときに表示されるようになります。ドキュメントを追加するには、パッケージのルートフォルダの下に「README.md」ファイルを作成してください。「README.md」は以下のように markdown という記法にて記述します。

This is my *first* package.

* foo
* bar
* baz

「cfx docs」コマンドで SDK ドキュメントをブラウザで表示し、「hello-world」のリンクをクリックするとパッケージのメタ情報とともにドキュメントの内容が整形表示されることを確認してください。

インストーラの作成

これまで作成してきたような Jetpack のパッケージから、一般的な Firefox 拡張機能と同等の XPI インストーラ形式を作成することができます。 XPI インストーラを作成するには、 SDK のコマンドプロンプトでパッケージのルートフォルダへ移動し、「cfx xpi」コマンドを入力します。

(C:\jetpack-sdk-0.2) C:\jetpack-sdk-0.2\packages\hello-world>cfx xpi
Exporting extension to hello-world.xpi.

すると、「hello-world.xpi」というファイル名の XPI インストーラが生成されます。これを適当な Firefox のウィンドウへドラッグ&ドロップして、通常の拡張機能としてインストールされることを確認してください。

XMLHttpRequest サンプルコード

XMLHttpRequest を処理する簡易 Wrapper サンプルコード。

var myextension = {
	// get html contents and do something
	httpGet: function(url, callback) {
		var req = new XMLHttpRequest();
		req.onreadystatechange = this.bindFunction(this, function(e) {
			if (req.readyState == 4) {
				if (req.status == 200) {
					if (typeof callback == "function") {
						callback(req.responseText, req.status, req);
					}
				}
				else {
					var message = "HTTP Request Failed! - url: " + url;
					if (this.debug && typeof this.debug.warn == "function") {
						this.debug.warn(message);
					}
					else if (Firebug && Firebug.Console && typeof Firebug.Console.log == "function") {
						Firebug.Console.log(message);
					}
					else {
						window.alert(message);
					}
				}
			}
		});
		req.open("GET", url, true);
		req.send(null);
		return req;
	},
	// workaround until we can use ECMA 5th bind method
	// we can this function to specify 'this' for callback functions
	bindFunction: function(thisobj, func) {
		return function() func.apply(thisobj, arguments);
	}
}
myextension.httpGet("", function(data, status, req) {
	alert(data);
});

このコードは 拡張機能デバッグイ ンターフェイスや Firebug などと組み合わせて使えるようにしたり、コールバック関数で this が維持されない問題についての対応を含めたサンプルですが、拡張機能固有の話ではないので必要な機能に応じて適当に Web サイト用のコードを好きなように使えば OK です。

ユーザ設定インターフェイス

ユーザ設定操作用のインターフェイスのサンプルコードです

var myextension = {
	// preference interface
	prefs: {
		_service: Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService),
		setBranch: function(branch) {
			this._service = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch(branch);
		},
		getPref: function(name) {
			switch(this._service.getPrefType(name)) {
				case this._service.PREF_INVALID:
					return null;
				case this._service.PREF_STRING:
					return decodeURIComponent(escape(this._service.getCharPref(name)));
				case this._service.PREF_INT:
					return this._service.getIntPref(name);
				case this._service.PREF_BOOL:
					return this._service.getBoolPref(name);
				default:
					return null;
			}
		},
		setPref: function(name, val) {
			switch(typeof val) {
				case "string":
					this._service.setCharPref(name, unescape(encodeURIComponent(val)));
					break;
				case "number":
					this._service.setIntPref(name, parseInt(val));
					break;
				case "boolean":
					this._service.setBoolPref(name, val);
					break;
				default:
					this.log("cannot set pref - val: " + val);
					return null
			}
			return true;
		},
		get datasource()    this.getPref("datasource"),
		set datasource(val) this.setPref("datasource", val),
	}
	onLoad: function() {
		var mypref = this.prefs.getPref("extensions.myextension.mypref");
		this.prefs.setBranch("extensions.myextension.");
		var anotherpref = this.prefs.getPref("anotherpref");
	}
}
window.addEventListener("load", function() { myextension.onLoad() }, false);

prefs オブジェクトを自分の拡張機能専用オブジェクトのプロパティとして定義し、prefs.getPref() と prefs.setPref() メソッドを使います。設定の型は設定時の引数に応じて自動判別されるので、引数の型には注意してください。

また、prefs.setBranch() メソッドを使えば共通する接頭辞部分を省略できるようになります。Firefox 本体や他の拡張機能の設定を操作する予定がない場合、誤って自分の拡張機能以外の設定を書き換えてしまわないようにするためにも、ブランチを設定しておくことをオススメします。