Now browsing the archives for the 'Extension Dev.' category.
Thanks, and goodbye XUL!
先日 Tokyo WebExtensions Meetup #1 に参加したことをきっかけに、ここ1~2年終息状態だったアドオン開発を再開しようという気になった。「お前のアドオンをとっとと Firefox Quantum に移行しろ!」というメールも最近はあまり来なくなってしまったが、遅ればせながら自作XULアドオン(旧式の拡張機能)の今後について、方向性を整理しておこうと思う。
FireGestures
ユーザー数:199,320 ユーザー
個人的使用度:★★★★★
キーボードよりマウス派。とはいえ戻りたいときにいちいち戻るボタンをクリックしたり、タブを切り替えるためにタブバーから選択してクリックすることにはストレスを感じるので、マウスの右クリックをしながら小さな動きで様々なアクションができるマウスジェスチャーは便利だ。
XULとしてはタブブラウザ全体(xul:tabbrowser 要素)に対する mousedown, mousemove, mouseup などのDOMイベントを検知してマウスジェスチャーを実現可能だが、これを WebExtensions 流にやるなら content scripts で各ブラウザ内のWebページに対して同じことをすれば良さそう。すでにいくつかの新しい拡張機能が順調に開発を進めているようであり、十分な代替があるため FireGestures は開発打ち切り。
なお、自分が試したのは Gesturefy のみであるが、完成度が高く、FireGesuturesを少しだけ意識してくれつつもモダンなUIへと昇華されており、もはや自分自身手放せない状態である。
ScrapBook
ユーザー数:78,593 ユーザー
個人的使用度:★
Firefox黎明期から存在し、知名度的には高い。しかし、現在は自分自身がほぼ使用していないため、開発は打ち切り。かといって今まで保存したWebページが見られなくなってしまうのは困るかもしれないので、ツリー構造をHTML出力する機能を使ってからFirefox Quantumへアップデートしてください。なお、代替としては ScrapbookQ や Web ScrapBook といったものがあるもよう。
Tab Scope
ユーザー数:55,836 ユーザー
個人的使用度:★★
昔Operaにあった機能を参考とし、タブにマウスポインタを当てることでプレビューしてくれる。怪しい画像を開くときに役立つ機能。技術的には CSS transition を使いまくってヌルヌル動くのが気持ちよく、結構好きなアドオンだが、無くても別に困らない。ブラウザUI改造系は WebExtensions としては実現可能性が低いため、開発打ち切り。
Vertical Toolbar
ユーザー数:4,577 ユーザー
個人的使用度:★★★
これもOperaにあった機能で、ブラウザのツールバーをサイドバーの左側に縦型表示してくれる。横長ディスプレイ主流の時代では理にかなっていると思う。むしろ標準機能として取り入れてほしい。 WebExtensions としては今のところ実現不可だが、新しいツールバーを追加する、ツールバーを縦に表示する、といったAPIが追加されれば是非とも開発したい。
Flat Bookmarks
ユーザー数:1,767 ユーザー
個人的使用度:★★
ブックマークツリーで階層が深くなるとインデントが増す問題への対処として、スタック型UIにしてくれる。食べログで行きたい店を見つけて最寄り駅別にフォルダに分けてブックマークしたり、ブックマークを一番活用していた時代には役立った機能。しかし、最近はブックマークが面倒な生活になってしまった。たまにPocketするくらい。技術的には XUL overlay や eval 駆使による魔改造系アドオンであり、開発打ち切り。
FoxAge2ch
ユーザー数:1,516 ユーザー
個人的使用度:★★★★
2ちゃんねる(現5ちゃんねる)およびいくつかの互換掲示板の更新チェッカー。自分自身も常用しており、現在はこれだけのために Firefox ESR を別プロファイルで起動する不便さを強いられている。
サイドバーの独自UI、HTTPリクエストやJSONデータ管理などを中心としたバックグラウンドのサービスだけで完結しているので、WebExtensions への移行は比較的容易い。現在移行作業中で、必要最小限の機能は利用できるレベルまで達している。
というわけで、奇しくも一番ユーザー数が少ない FoxAge2ch だけが今のところ開発継続という結果となってしまった。
最後に
XULに出会ったのはおよそ14年前、研究室の先輩からの提案であり、それ以来長らく関わってきた中で得たプログラミング知識、仲間達との出会い、イベントや旅行、書籍執筆など、さまざまな思い出が詰まっている。XULの名前空間 http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul をそらで言えるようになったり、 Components.classes[“@mozilla.org/ …と呪文のごとくXPCOMを呼び出すことに妙な興奮を覚えたり、深い思い入れがある。
しかし、Mozilla(Firefox)としては FUEL、Jetpack、Rebootlessアドオンなど長い長い試行錯誤を経てようやく辿り着いた真打 WebExtensions であり、実際に触れてみるとその敷居の低さ、デバッグ環境の充実ぶり、モダンなプログラミングスタイルなど、ブラウザアドオン界の新たな幕開けを確信させるものであった。
というわけで、Thanks, and goodbye XUL!
Firefox 4 対応アドオンのプレビュー用スクリーンショット作成手順
Firefox 4 ベータ版の完成度もだいぶ高くなってきて見た目も最終仕様に近づいてきたと思われるので、addons.mozilla.org で公開している Firefox 4 対応済み自作アドオンのプレビュー用スクリーンショットを順次 Firefox 4 ベースに差し替えていこうと思う。以下はプレビュー用スクリーンショットの作成手順メモ。
OS
以前は Windows XP (Royale Theme) + Firefox 3.6 でプレビュー用スクリーンショットを作成していたが、 Firefox 4 になってデザインが Windows 7 と相性が良くなったのと、自分の開発環境が Windows 7 ということもあり、今後は Windows 7 + Firefox 4 とする。
OSのテーマ
Windows 7 デフォルトの Aero テーマで、透明感を有効(Glass効果あり)にし、壁紙を白一色にする。透けたタイトルバーにデスクトップのアイコンが写り込むのを防ぐため、デスクトップ上で右クリック→「表示」→「デスクトップアイコンを表示」をオフにする。
次に、「デザインの詳細設定」でUIに使用するすべてのフォントを、メイリオから Segoe UI に変更する。メイリオも綺麗だが、 Segoe UI は大変美しく、小さいサイズでも可視性に優れている。さらに、アクティブタイトルバーのサイズを18から20に変更する。
次回以降の作業時のために、変更した状態となっている「未保存のテーマ」を右クリックして名前を付けて保存しておく。
Firefox のバージョン
Firefox 4.0b8pre(トランクビルド)だと、タイトルバーのアプリケーションボタンなどが「Firefox」ではなく「Minefield」になってしまうため、現時点で最新のベータ版である、 Firefox 4.0b7 をインストールする。自分はインストーラ版の Firefox 3.6 をインストールしており、追加でインストーラから Firefox 4.0b7 をインストールすると関連付けが変わったり若干面倒なことになりそうな予感がしたので、ZIPパッケージの Firefox 4.0b7 を探したが、見つからなかった。そこで、イレギュラーな方法であるが、Firefox ベータ版 – 各国語版のダウンロードから英語版の Firefox 4.0b7 インストーラをダウンロードし、インストーラの exe ファイルを 7-Zip で展開し、中にある「core」フォルダを取り出して「Mozilla Firefox 4.0b7」にリネームし、「C:Program Files」内に移動することでインストールした。なお、プレビュー画像の国際化対応のためUIを英語にしたいので、英語版の Firefox 4.0b7 をダウンロードする。
Firefox の設定
「”C:Program FilesMozilla Firefox 4.0b7firefox.exe” -p -no-remote」で Firefox を起動し、プロファイルマネージャにて常用プロファイルとは別のプレビュー画像作成用のクリーンなプロファイルを作って起動する。
各種ツールバーの表示は基本的にはデフォルト状態のまま変更しないようにする。つまり、メニューバーは非表示(代わりにアプリケーションボタン表示)、ナビゲーションツールバー表示、タブバーは上部に表示となる。ただし、ナビゲーションツールバー右端の「Feedback」ボタンはベータ版特有のものなので、ツールバーのカスタマイズで取り除いておく。アドオンバーは必要に応じて表示する。
また、GPU固有の問題かもしれないが、自分の環境ではハードウェアアクセラレーションを有効にするとなぜかテキストの描画が劣化するので、オプションの「Use hardware acceleration when available」をオフにする。
Firefox のウィンドウ
Firefox のウィンドウのサイズを addons.mozilla.org で許可されている最大のサイズである 700 x 525 にする。
やり方は、以下のコードをローケーションバーに貼り付けて移動するだけで良い。ただし、 JavaScript の詳細設定で「Move or resize existing windows」がオフになっていると効かないので注意。
javascript:window.resizeTo(700,525);
サイドバー系の拡張機能では以下のコードをエラーコンソールで実行し、サイドバーの幅を一意にする。
var win = Components.classes["@mozilla.org/appshell/window-mediator;1"]. getService(Components.interfaces.nsIWindowMediator). getMostRecentWindow("navigator:browser"); win.document.getElementById("sidebar-box").width = 200;
スクリーンショットのキャプチャ
ここまでの手順で準備は完了で、あとはひたすらアドオンの色々な場面のスクリーンショットをキャプチャしていく。
スクリーンショットのキャプチャには WinShot を使用し、基本的にはアプリケーションのウィンドウ全体をキャプチャする。 Windows Aero 有効時はウィンドウの外側に影が付くが、画像サイズを700 x 525で統一するため、この影は省いてキャプチャすることとなる。ただ、ウィンドウ枠の四隅の角丸の外側が汚れたような見た目になってしまう問題点がある。
実際の例
以上の手順に従って作成した Firefox のスクリーンショットはこちらです。
Babelzilla の WTS で全ローカライズの進捗が100%と誤認識される問題
事象
Bazelzilla の Web Translation System (WTS) では、通常各ローカライズの DTD ファイルおよび propertiesファイル中の未翻訳部分は、その行自体が無い状態でXPIにパッケージングしてアップロードする必要がある。しかし、誤って全ローカライズの未翻訳部分を英語に置き換えた内容の XPI ファイルをアップロードしたところ、全ローカライズの翻訳進捗率が100%と誤認識されてしまった。もう一度正しい XPI ファイルをアップロードしなおしてもサーバー側のデータベースに以前翻訳された内容が保持されているようで、翻訳進捗率は100%のまま。こうなってしまうと、翻訳者はどのファイルのどの部分が未翻訳であるかを把握できなくなってしまう。
復旧方法
XPI ファイルからすべてのローカライズ( jar ファイル中の locale フォルダと chrome.manifest の locale 宣言)を取り除いた偽バージョンを作成し、アップロードする。その後、改めて正しい XPI ファイルをアップロードする。この手順で翻訳進捗率の表示が正しい値に戻った。
Firefox 3ではじめる拡張機能開発|gihyo.jp … 技術評論社
McCoy を使ったアドオンの安全な更新方法の提供
Firefox 3 では、安全な更新方法が提供されていないアドオン、つまりインストールマニフェスト中の em:updateURL の値が https ではなく http プロトコルであるようなアドオンは、デフォルトでインストール不可となる。
どうしても em:updateURL の値を http プロトコルにしたければ、インストールマニフェストとアップデートマニフェストの両者へ以下のような細工を施す必要がある。
作業 | ファイル | 内容 |
---|---|---|
#1 | インストールマニフェスト (install.rdf) |
公開鍵を em:updateKey エントリとして追加する。 |
#2 | アップデートマニフェスト (update.rdf) |
em:updateLink で示された XPI ファイルのハッシュ値を em:updateHash エントリとして追加する。 |
#3 | マニフェストファイルに対する電子署名を em:signature エントリとして追加する。 |
このような細工を施すことで、以下のような仕組みにより安全な更新が可能となる。
- アドオンマネージャで「更新の確認」を行った際、インストールマニフェスト中の公開鍵と、安全ではない経路からダウンロードしたアップデートマニフェスト中の電子署名を照合し、そのアップデートマニフェストの正当性を検証する。
- アップデートマニフェストで示された新しいバージョンをインストールする際、アップデートマニフェスト中のハッシュ値と実際にダウンロードした XPI ファイルから算出したハッシュ値とを比較し、その XPI ファイルの正当性を検証する。
事前準備
上記作業#1~#3を実施するにあたり、事前に McCoy というアプリをインストールしておく。
作業#1の手順
- McCoy で「Create」ボタンを押して公開鍵(と秘密鍵)を生成する。
- 右クリックメニューの「Copy Public Key」から公開鍵をクリップボードにコピーする。
- 既に作成済みのインストールマニフェストへ <em:updateKey>{公開鍵の値}</em:updateKey> という行を追加する。
こうしてできあがったインストールマニフェストを含めて XPI ファイルを生成すれば、とりあえずはそのアドオンは Firefox 3 にインストール可能となる。なお、手順1で作成した公開鍵(と秘密鍵)は今後も同じものを使い続けるので、作業#1は一度実施すれば今後のバージョンアップ時はそのままで良い。
なお、手順1で作成した公開鍵(と秘密鍵)は、他のアドオンに対して使いまわしても構わない。
作業#2の手順
- XPI ファイルの SHA1 ハッシュ値を求める。
SHA1 ハッシュの求め方は、 Win 用アプリ bkhashes, Firefox 拡張機能 MDHashTool, Cygwin の sha1sum コマンド、PHP の sha1_file 関数などがある。 - 既に作成済みのアップデートマニフェストへ <em:updateHash>sha1:{ハッシュの値}</em:updateHash> という行を追加する。
ただし、 XML 構造によっては em:updateHash=”sha1:{ハッシュの値}” という記述となる場合もある。
SHA1 ハッシュ値は、 XPI ファイルが1バイトでも違えばまったく異なる値となるので、 XPI ファイルをパッケージングするたびに作業#2を実施する必要がある。
作業#3の手順
- McCoy にて作業#1で作成した公開鍵を選択し、「Sign」ボタンを押して作業#2で作成したアップデートマニフェストのファイルを選択する。
- アップデートマニフェストへ自動的に em:signature エントリが追加される。
McCoy によって自動生成されたアップデートマニフェストは、XML の構造が少し複雑である。だが、このファイルを手動で編集してはならない。ちょっとでも編集すると、アドオンマネージャにて更新情報を検知できなくなってしまう。
自分は XML 構造が変わるのが嫌なので、手動で編集するためのアップデートマニフェストと、 McCoy で電子署名を付加したアップデートマニフェストとを別々に管理している。
なお、当然ながら作業#2で em:updateHash の値を書き換えたら、その都度作業#3を実施する必要がある。
動作確認手順
実際にアドオンマネージャにて更新確認と新しいバージョンのインストールの動作確認を行うための手順を示す。
- インストールマニフェストに対して作業#1を実施する。
- 1. のインストールマニフェストを含めた XPI インストーラを作成し、 Firefox へインストールする。
- 1. のインストールマニフェストの em:version の値を上げる。
- 3. のインストールマニフェストを含めた XPI インストーラを作成する。
- 4. の XPI インストーラから SHA1ハッシュを生成し、アップデートマニフェストに対して作業#2を実施する。
- 5. のアップデートマニフェストに対して作業#3を実施する。
- 4. と 6. の2ファイルを Webサーバへデプロイする。
- アドオンマネージャにて「更新を確認」する。
参考
Latest topics > XML署名とハッシュを使って安全な方法でアドオンを更新できるようにする – outsider reflex
くでんな日々や公開どう? ◆ [Mozilla] さぁ、McCoyをはじめよう!!
Install Manifests – MDC
Extension Versioning, Update and Compatibility – MDC
McCoy – MDC
[Exception… “‘Component is not available’ when calling method: [nsIHandlerService::getTypeFromExtension]
2008/5/3 追記
この問題は解決済みです。
Firefox 3にて、XULから <script type="application/x-javascript" src="chrome://myext/content/test.js" />
のようにして JavaScript を読み込む際、その JavaScript ファイルがjar形式アーカイブの中身ではなくて純粋なローカルファイルである場合(つまり chrome.manifest にて content myext content/myext/
のようにしている場合)、以下の例外がエラーコンソールに出力される。
エラー: [Exception… “‘Component is not available’ when calling method: [nsIHandlerService::getTypeFromExtension]” nsresult: “0x80040111 (NS_ERROR_NOT_AVAILABLE)” location: “
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9pre) Gecko/2008042606 Minefield/3.0pre
BabelZilla を使ったローカライズ管理
先のエントリでもちょこっと触れたように、BabelZilla を使うことで拡張機能のローカライズ関連のメンテナンスが楽になる。
BabelZilla へ拡張機能を登録すると、その拡張機能専用のフォーラムが作成されるので、翻訳者とのやりとりを一極化できる。また、 WTS (Web Translation System) と呼ばれるシステムによって、ローカライズファイルのアップロードやダウンロード、さらには編集までも Webベースで行うことが可能になる。
自分も2年前から少しずつ BabelZilla を使い始め、今では完全に BabelZilla へ移行した。たとえ翻訳者がEメールで直接 locale パッケージをよこしても、 BabelZilla 経由しか受け付けておりませんとお断りし、 BabelZilla へのユーザ登録を促すようにしている。
WTS を使う大きなメリットとして、「Download all locale files (missing string: replaced)」というリンクから未翻訳のエンティティ・プロパティをすべて英語に置換した形ですべての locale パッケージを圧縮してダウンロードできることが挙げられる。正式リリース版の XPI ファイルを作成する際に、この置換済み locale パッケージをダウンロードして自分の拡張機能のソースコードに含めてやればよいわけだ。
しかし、後日拡張機能のバージョンアップを実施し、新たに翻訳可能なエンティティ・プロパティを追加し、 XPI を作って BabelZilla へアップロードすると、英語に置換された部分についてはすでに翻訳済みであると認識されてしまう。これは BabelZilla の仕様であり、未翻訳なエンティティ・プロパティについてはその行自体を無い状態にして XPI を作成してアップロードしなければならない。 <!ENTITY hello "">
のように値を空欄にした場合も翻訳済みと認識される。
この問題を解決するために、自分はどうやっているかというと、翻訳が完全に済んだ locale パッケージのみを自分のソースコードへ取り込んでバージョン管理するようにし、正式リリース版 XPI を作成するときだけ一時的に locale フォルダ以下全てを BabelZilla からダウンロードした英語に置換済みのファイルへと置き換えるようにしている。
翻訳者全員の仕事が速くて、正式リリース版 XPI を作る際にすべてのロケールの翻訳が100%完了している、という前提であれば、上記のように開発版の locale フォルダと正式リリース用の locale フォルダを別にする必要は無いが、現実はそうもいかない。仕方ないけど、もう少しうまく管理できる方法はないものか、とも思っている。
ひとつ思いついたのは、 WTS が英語に置換した未翻訳なエンティティの行にコメントで目印をつけることで、次回アップロード時に WTS が未翻訳だと認識してくれるような仕組みである。
<!ENTITY hello "Hello."><!-- untranslated -->
でも、同じように properties ファイルの各プロパティの行へコメント入れるのは無理っぽいな。
HELLO=Hello # untranslated
なんてやってもコメントと認識されるわけないし、せいぜい
HELLO=Hello.
#untranslated HELLO
みたいに別の行コメントで未翻訳キーを示すしかないか。
拡張機能バージョンアップ時の不完全ローカライズの取り扱い
翻訳者ではなく、拡張機能開発者としての疑問。
ある言語の翻訳者がローカライズ (xx-XX の locale パッケージ) を提供してくれたはいいが、その後、拡張機能がバージョンアップして翻訳すべき箇所が追加されても、継続的にローカライズをメンテしてくれないことが多々ある。
そういう場合、どうするか?
案1 不完全なローカライズは含めない
バージョンアップで翻訳可能な箇所を追加するたびに locale パッケージを en-US と ja-JP だけに削減してリリースし、完全なローカライズが提供され次第、それを含めて再リリースする。
ついてこれるやつだけついて来い、という感じの冷たいやり方。
確か Firefox 1.0 の頃はバージョンアップに伴い locale パッケージを減らすと変なエラーが出て、この方法は無理だったような気がする。
案2 未翻訳の部分は英語で置き換えておく
拡張機能のバージョンアップに伴い、DTDファイルに新しいエンティティを追加したとすると、その拡張機能に含まれる日本語以外の全 locale パッケージに対して英語のエンティティを追加する。
おそらくこれが一般的ではないだろうか。 Piro さんもやはりこの方式であるそうだ。
しかし、手作業でやると面倒であり、ミスも発生しやすい。英語のエンティティを追加し忘れると、ブラウザウィンドウ下部に黄色いエラーメッセージが表示されたりして被害が大きい。
BabelZilla を使っていると、この面倒くささを解消できる。ただ…
また、正式リリース前に英語で置き換えられたバージョンを翻訳者に送付し、ローカライズをお願いするというのもいいかもしれない。
案3 案1+案2の折衷案
とりあえず未翻訳の部分は英語で置き換えてリリースし、その後あまりにも未翻訳な部分(英語で置き換えられた部分)が多くなりすぎたら、その locale パッケージを削除する。
ユーザによっては少しでも自分の国の言語に翻訳されている方がありがたいと思うかもしれないので、どの程度未翻訳な部分が増えたら locale パッケージを捨てるか、難しいところ。
開発中のアドオンのソースファイルへの上書きインストール問題
以下のような手順で開発中のアドオンのソースファイルを配備したとする。
1. ファイル「myapp@example.com」を作成
2. ファイルの内容を「c:xulmyapp」とする
3. ファイルをプロファイルフォルダextensions下へ配置
4. c:xulmypp に各種ソースファイルを配置して開発
ここで、誤って同一のem:idを有するアドオンをXPIファイルからインストールすると、「c:xulmyapp」内部が一度全削除され、myapp フォルダ下にXPIが展開して配備されてしまうということが Firefox 1.5 時代にあったように思う。
しかし、この問題は Firefox 2.0 へアップグレードする過程でいつの間にか治ったようだ。今では誤って同一のem:idを有するアドオンをXPIファイルからインストールしても「c:xulmyapp」内部は削除されず、普通に extensions フォルダ下にXPIファイルが展開され、通常の手順でアドオンをインストールした状態となる。
Chrome Providers (content, locale, skin)
Chrome Providers (という言い方は今まで知らなかったが)には、 content, locale, skin の3種があることは XULチュートリアルの最初の方にも書いてあるように基本的な事柄である。 content には XUL や JavaScript といったメインソースコードが格納され、 locale には DTD や properties の言語リソースが格納され、 skin にはスタイルシートや画像が格納される。
バカ正直に拡張子 xul か js のファイルは content, dtd か properties なら locale, css か png か gif とかなら skin、と決め付ければいいのかと思いきや、必ずしもそうではない。ポイントは、 locale は Firefox 自体の general.useragent.locale の設定値によって内容が可変であり、 skin は Firefox 自体のテーマによって内容が可変である、ということである。
- ヘルプとして参照されるHTML形式のファイルがある。ヘルプの内容をローカライズ可能にしたいなら、 locale 配下に置けばよい。
- バインディングするための CSS がテーマによって改変されては困る。そういった CSS は当然 content 配下に置くべきである。
- 拡張機能のために作成したアイコンのデザインが気に入っているので、サードパーティーのテーマ作者が勝手に独自のアイコンに改変することを禁じたい。それなら skin に置くべきアイコン画像をすべて content に置けばよい。
- 「保存」ボタンに割り当てるアクセスキーを言語ごとに変えたい。英語なら Save なので S にしたいけど、ドイツ語なら Außer なので A にしたい。それなら XUL は <button accesskey=”&savebutton.accesskey;”> として、savebutton.accesskey を locale 中の DTD ファイルで定義してやればよい。こういったDTDの使い方は頻繁に見かける。
- 言語ごとにダイアログのサイズがフィットするようにしたい。それなら XUL を <window width=”&window.width;”> として、window.width を locale 中の DTD ファイルで定義してやればよい。こういうやり方は実際に chrome://browser/content/safeMode.xul などで見かけることができる。