ブートストラップ型拡張機能

この翻訳は不完全です。英語から この記事を翻訳 してください。

なお、Add-on SDKを使って作成された拡張機能はすべて bootstrappedです!ブート処理コードは自動的に生成されるので、それについて考える必要はまったくありません。 Add-on SDKを使っていない? 読むべきです...

従来型の拡張機能はオーバーレイを含んでおり、アプリケーションが拡張機能のパッケージから XUL を読み込み、その UI 部品をアプリケーションのユーザインタフェース (UI) 上へ自動的に適用します。この仕組みを使うと、アプリケーションの UI へ部品を追加する拡張機能を比較的簡単に作成できますが、拡張機能の更新、インストール、無効化を行う際にアプリケーションの再起動が必要となります。

Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) では新たにブートストラップ型拡張機能 (bootstrapped extension) という仕組みが導入されました。これは特別な拡張機能で、オーバーレイを使って独自の UI 部品をアプリケーションへ適用する代わりに、アプリケーションへ動的に部品を挿入できるようにするものです。この処理は、拡張機能のインストール、削除、起動、終了時にブラウザが呼び出す関数を記述した、拡張機能に含まれる特別なスクリプトファイルを使って行われます。

アプリケーションが行うのはこのスクリプトファイルに書かれた関数を呼び出すことだけで、UI 部品の追加や削除、その他必要とされる起動・終了時の処理などはすべて拡張機能自身が責任を持って行う必要があります。

この記事ではブートストラップ型拡張機能の仕組みを解説します。 See this tutorial on converting from an overlay extension to restartless for a practical step by step guide to migrating.

起動・終了プロセス

ブートストラップ型拡張機能の重要な機能のひとつに、アプリケーションの指示による任意のタイミングで起動や終了が可能であることが挙げられます。拡張機能の startup() 関数が呼び出されたとき、UI 部品やその他の動作をアプリケーションへ動的に挿入する必要があります。同じように、shutdown 関数が呼び出されたときは、アプリケーションへ追加した部品やそのオブジェクトへの参照をすべて削除しなければなりません。

startup 関数が呼び出される場面はいくつかあります。例えば、

  • 拡張機能が始めてインストールされるとき (その拡張機能がアプリケーションと互換性があり、なおかつ有効化されている場合)
  • アドオンマネージャの画面上で拡張機能が有効化されるとき
  • アプリケーション起動時 (その拡張機能がアプリケーションと互換性があり、なおかつ有効化されている場合)

shutdown 関数が呼び出される場面は次のようなときです。

  • 拡張機能が削除されるとき (その拡張機能が有効化されている場合)
  • 拡張機能が無効化されるとき
  • アプリケーション終了時 (その拡張機能が有効化されている場合)

アプリケーションの UI 変更に関する注意

ブートストラップ型拡張機能内の chrome.manifest

ブートストラップ型拡張機能に chrome.manifest ファイルを含めると次のようなことが可能となります。

  1. 拡張機能に含まれるコンテンツを chrome:// URI を通じて利用可能にする (マニフェスト内の contentlocaleskin 命令文を使う)
  2. 既存の chrome:// URI を自作コンテンツで置き換える (override 命令文を使う)

ブートストラップ型拡張機能の中では使えないマニフェスト命令文もあります。例えば XUL オーバーレイ を登録することはできません。詳しくは chrome.manifest の記事を参照してください。

Firefox 10 以降では、拡張機能 XPI ファイル内のルートに (install.rdf と同列で) 置かれている chrome.manifest ファイルは自動的に読み込まれます。Firefox 8 と 9 では、nsIComponentManager.addBootstrappedManifestLocation()nsIComponentManager.removeBootstrappedManifestLocation() を使ってマニフェストを動的に読み込み、終了時に読み込み解除する必要があります。この機能は Firefox 8 未満のバージョンでは使用できません。

UI 部品の動的な追加

ここまで読んで、アプリケーションの UI を変更するブートストラップ型拡張機能を作り始めようと思ったら、最初に次のようなコードを考えましょう。

まず、関連するアプリケーションの UI 要素を、document.getElementById() を使って、その ID で参照します。次に、それらを操作して独自の UI 部品を挿入します。例えば、Firefox のメニューバーは document.getElementById("main-menubar") で参照可能です。

終了時には、追加した UI 部品を必ず削除しましょう。

ブートストラップ型拡張機能の作成

拡張機能がブートストラップ型であることを示すには、以下の要素を インストールマニフェスト へ追加する必要があります。

<em:bootstrap>true</em:bootstrap>

それから、必要な関数を記述する bootstrap.js ファイル を追加します。これは拡張機能パッケージ内の install.rdf ファイル と同列で配置します。

後方互換性

Firefox の旧バージョンは bootstrap プロパティや bootstrap.js ファイルを認識できないため、ブートストラップ型と従来型を兼ねた拡張機能の開発は非常に難しいと言えます。まずはブートストラップ型拡張機能として作成し、次に従来のオーバーレイも追加することになります。そうすることで、Firefox の新バージョンは bootstrap.js スクリプトを使い、コンポーネントやオーバーレイを無視しますが、旧バージョンにはオーバーレイを使わせられます。

ブート処理が呼び出されるタイミング (エントリーポイント)

bootstrap.js スクリプトにはいくつかの特定の関数を含める必要があります。それらは拡張機能を管理するブラウザによって呼び出されます。このスクリプトは特権付きサンドボックス内で実行され、拡張機能の終了時までキャッシュされます。

startup

拡張機能がそれ自身を起動する必要があるときに呼び出されます。アプリケーションの起動時や、無効化されている拡張機能が有効化されるとき、更新をインストールするときにも呼び出されます。そのため、アプリケーションの起動中に何度も呼び出される可能性があります。

このタイミングで、独自の UI 部品を挿入したり、必要な処理を開始したりします。

void startup(
  data,
  reason
); 
引数
data
ブートストラップデータ構造
reason
理由定数 のひとつで、拡張機能が起動されようとしている理由を示します。APP_STARTUPADDON_ENABLEADDON_INSTALLADDON_UPGRADEADDON_DOWNGRADE のいずれかになります。

shutdown

拡張機能がそれ自身を終了する必要があるときに呼び出されます。アプリケーションの終了時や、拡張機能が更新あるいは無効化されるときなどです。このタイミングで、挿入した UI 部品をすべて削除し、処理を停止し、オブジェクトを破棄する必要があります。

void shutdown(
  data,
  reason
);
引数
data
ブートストラップデータ構造
reason
理由定数 のひとつで、拡張機能が終了されようとしている理由を示します。APP_SHUTDOWNADDON_DISABLEADDON_UNINSTALLADDON_UPGRADEADDON_DOWNGRADE のいずれかになります。

Optional

install

ブートストラップスクリプトにはオプションで install 関数を含めることができます。これは、拡張機能がインストール、更新、あるいはダウングレードされた後、startup 関数の初回呼び出し前に、アプリケーションによって呼び出されます。

注: この関数は、拡張機能が一度も起動されていない場合は呼び出されません。例えば、拡張機能がインストールされたもののアプリケーションの現在のバージョンと互換性がなく、互換性が確保される前に削除された場合、install 関数は一度も呼び出されません。しかし、拡張機能がそのアプリケーションと互換性のあるバージョンへ更新された場合、install 関数はその時点で、startup 関数の初回呼び出し前に呼び出されます。
void install(
  data,
  reason
); 
引数
data
ブートストラップデータ構造
reason
理由定数 のひとつで、拡張機能がインストールされようとしている理由を示します。ADDON_INSTALLADDON_UPGRADEADDON_DOWNGRADE のいずれかになります。

Optional

uninstall

このオプション関数は、拡張機能の特定のバージョンが削除された後、shutdown 関数の最終呼び出し後に呼び出されます。これは、install 関数が一度も呼び出されていない場合は呼び出されません。

注: uninstall 関数は、拡張機能が無効化されている場合や、アプリケーションの現在のバージョンと互換性がない場合でも呼び出される場合があることに注意してください。このため、この関数を実装する場合は、使用している API がアプリケーションに実装されていない可能性も考慮し、適切に処理することが重要です。なお、この関数は Firefox が起動していないときに外部アプリケーションによって拡張機能が削除された場合には呼び出されません。
Note: Simply having function install() {} IS NOT ENOUGH because if you have code in uninstall it will not run. You MUST run some code in the install function; at the least you must set parameters for the install function, such as: function install(aData, aReason) {}; then uninstall WILL WORK.
Note: If you open the add-on manager and then click "Remove" on an add-on, it will not call uninstall function right away. This is a soft uninstall because of the available "Undo" option. If the add-on manager is closed or another event takes place such that the "Undo" option becomes unavailable, then the hard uninstall takes place and the uninstall function is called.
Note: The uninstall function fires on downgrade and upgrade as well so you should make sure it is an uninstall by doing this:
function uninstall(aData, aReason) {
     if (aReason == ADDON_UNINSTALL) {
          console.log('really uninstalling');
     } else {
          console.log('not a permanent uninstall, likely an upgrade or downgrade');
     }
}
void uninstall(
  data,
  reason
); 
引数
data
ブートストラップデータ構造
reason
理由定数 のひとつで、拡張機能が削除されようとしている理由を示します。ADDON_UNINSTALLADDON_UPGRADEADDON_DOWNGRADE のいずれかになります。

理由定数

ブートストラップ関数は reason 引数を取ることができます。拡張機能は、その関数が呼び出された理由をこの引数で確かめられます。理由定数は以下の通りです。

定数 意味
APP_STARTUP 1 アプリケーションが起動されようとしている
APP_SHUTDOWN 2 アプリケーションが終了されようとしている
ADDON_ENABLE 3 拡張機能が有効化されようとしている
ADDON_DISABLE 4 拡張機能が無効化されようとしている (削除時にも送信されます)
ADDON_INSTALL 5 拡張機能がインストールされようとしている
ADDON_UNINSTALL 6 拡張機能が削除されようとしている
ADDON_UPGRADE 7 拡張機能が更新されようとしている
ADDON_DOWNGRADE 8 拡張機能がダウングレードされようとしている

ブートストラップデータ

上記の各関数 (エントリーポイント) には、その拡張機能に関する有用な情報が含まれるシンプルなデータ構造が渡されます。拡張機能に関するより詳しい情報は AddonManager.getAddonByID() を呼び出すことで取得できます。このデータは単純な JavaScript オブジェクトで、以下のプロパティが含まれます。

プロパティ 意味
id string ブート処理される拡張機能の ID
version string ブート処理される拡張機能のバージョン
installPath nsIFile ブート処理される拡張機能がインストールされている場所。これは、拡張機能がインストール時に展開されているかどうかによって、ディレクトリもしくは XPI ファイルとなります
resourceURI nsIURI

拡張機能ファイルのルートを示す URI。これは、拡張機能がインストール時に展開されているかどうかによって、jar: もしくは file: URI となります

oldVersion string The previously installed version, if the reason is ADDON_UPGRADE or ADDON_DOWNGRADE, and the method is install or startup.
newVersion string The version to be installed, if the reason is ADDON_UPGRADE or ADDON_DOWNGRADE, and the method is shutdown or uninstall.

Note: An add-on may be upgraded/downgraded at application startup, in this case the startup method reason is APP_STARTUP, and the oldVersion property is not set. Also be aware that in some circumstances an add-on upgrade/downgrade may occur without the uninstall method being called.

Add-on debugger

From Firefox 31 onwards, you can use the Add-on Debugger to debug bootstrapped add-ons.

Localization (L10n)

Localizing bootstrapped add-ons is very much the same since Firefox 7, as that is when chrome.manifest compatibility landed.

JS and JSM Files - Using Property Files

To localize your .js and .jsm files you have to use property files.

The absolute minimum needed here is:

  1. File: install.rdf
  2. File: chrome.manifest
  3. File: bootstrap.js
  4. Folder: locale
    1. Folder: VALID_LOCALE_HERE
      1. File: ANYTHING.properties

In the locale folder you must have folders for each of the languages you want to provide; each folder must be named a valid locale (ex: en-US). Inside this folder must be a property file. Inside the chrome.manifest file these locale must be defined. For example if you had a subfolder of en-US in locale folder your chrome.manifest file will have to contain: locale NAME_OF_YOUR_ADDON en-US locale/en-US/

Here is an example: GitHub :: l10n-properties - on startup of this add-on it will show a prompt saying USA or Great Britain, which ever it deems closest to your locale. You can test different locale by going to about:config and changing preference of general.useragent.locale to en-US and then to en-GB and disabling then re-enabling the add-on.

XUL and HTML Files - Using Entities from DTD Files

Many times HTML pages are used, however they cannot be localized with DTD files. There are three changes you must make:

  1. You have to change the HTML file's extension to be .xhtml
  2. The doctype must be defined point to a DTD file in your locale folder such as: <!DOCTYPE html SYSTEM "chrome://l10n/locale/mozilla.dtd">
  3. Must add xmlns attribute to html tag for example: <html xmlns="http://www.w3.org/1999/xhtml">
  4. If you have multiple DTD files read on here: Using multiple DTDs

The bare minimum needed is:

  1. File: install.rdf
  2. File: chrome.manifest
  3. File: bootstrap.js
  4. Folder: locale
    1. Folder: VALID_LOCALE_HERE
      1. File: ANYTHING.dtd

The chrome.manifest file must include a definition for content for example: content NAME_OF_YOUR_ADDON ./

The chrome.manifest file must also include a line pointing to the locale, just like in the above property section, if you had a folder named en-US in locale, the chrome.manifest file should contain: locale NAME_OF_YOUR_ADDON en-US locale/en-US/

Here is an example add-on that opens an HTML page and a XUL page on install: GitHub :: l10n-xhtml-xul. Here is an example showing how to use a localized HTML page as an options page: GitHub :: l10n-html-options. You can go to about:config and change the value of the preference general.useragent.locale to en-US and then to en-GB and then reload the open pages to see the localization change.

参考資料

日本語の参考資料

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

 このページの貢献者: lv7777, kohei.yoshino
 最終更新者: lv7777,