2013年8月12日月曜日

Firefox addon 開発記:艦これ遠征 Timer と Trusted Content と port

 記録的な猛暑の中コミケが開催されていましたね。自分も暑さに負けてられない!ということで艦これ遠征 Timer アドオンの,前から欲しいと思っていた機能の実装に取り組んでみました。


 その機能とは,遠征終了通知機能。ただし alert やら notification で実装すると少々鬱陶しい気がしたので,規定の遠征時間が経過したら,ひっそりとアドオンのアイコンの色を変えたいと思います。 

 これまで行なってきた実装は,アドオンの panel 内に読み込んだ HTML(panel.html) と,その HTML に付随する JavaScript(countdown.js) での情報のやり取りを扱って来ました。一方,今回行うアドオンのアイコン変更は,HTML に付随する JavaScript と panel を生成している main.js との間の情報交換を行う必要があります。
 図示すると下記のような構造です。











 調べてみたところ,panel と panel 内のコンテンツとの情報のやり取りは,contentScript を介して行うのが一般的なようです。contentScript とは,panel にてコンテンツと共に読みこむように指定するスクリプトで,main.js とは port.on もしくは port.emit で,コンテンツの HTML とはgetElementByID などでやり取りを行うことができます。
 このアドオンに適用すると下図のようになります。
















 「contentScript.js に panel.html を見張らせて,遠征終了の文字が countdown.js により記述されたら main.js に伝えさせよう」と設計してみました。が,よく考えると「見張らせる」ためには,contentScript.js を常になんらかのイベントで呼び出す必要があります。しかもカウントダウンは panel.html が表示されていない状態でも進行するため,onClick や onChange といった HTML が表示されていることを前提としたイベントは使えません。
 では setTimeout を使う? しかしそんなことをしたら,countdown.js のカウントダウン処理と 2 重でタイマーが動く冗長な構造になってしまいます。それならいっそカウントダウン処理を contentScript.js に組み込もうかとも思いましたが,やはり HTML に組み込んだ JavaScript の方が HTML とのやり取りが楽な気がします。


 ここでひとしきり悩みつつ,色々なページのサンプルプログラムを読んでいた所,なんと本家 Add-on SDK Documentation に探していた情報がありました!このページの Scripting Trusted Widget Content の部分です。
 Widget や panel 内のコンテンツとして,外部の HTML を読み込んだり,本プログラムのようにアドオンと同梱のHTML を読み込んだりできます。後者の内部の HTML をコンテンツとしてロードする場合,そのコンテンツを Trusted Content と呼ぶようです。このページによると...


Trusted Content とやり取りを行う場合,content script を使用する必要はない。通常通り script タグを用いて,HTML にスクリプトをインクルードすればよい。そして self.port.emit でなく,addon.port.emit を用いることで,スクリプトとアドオン間のやり取りができる。

 こんな方法があったんですね! それにしても self オブジェクトは分かりますが,addon オブジェクトって何だろう? ひとしきり調べましたが,詳しくは分かりませんでした。検索結果の少なさから,この用途のためだけにある Firefox 専用のオブジェクトっぽい気がします。
 この方法で構築すると,下図の様になります。










 一番最初に貼った図とほぼ同じ,とてもシンプルな構成です。contdown.js からメッセージさえ出せれば,あとは main.js の中で パネルの名前.port.on("メッセージ") でメッセージを受け取って,widget のアイコンを変更するプロセスに入るようにすれば完了です。
 実装した所無事動作しました!以下動作画面。


 あくまでも金剛さん推し。
 ダウンロードはこちらの記事からお願いします。
 夏本番。暑さに負けず,勉強頑張ります!

0 件のコメント:

コメントを投稿