中編から引き続き、選択範囲の文字列からブックマークへタグ付けする処理などをJavaScriptで実装していきます。
その前に、処理を実装するために必要となるPlaces APIについて簡単な紹介をします。
Places API
ここからは、選択範囲の文字列からブックマークへタグ付けする処理などを実装していきますが、その前に、処理を実装するために必要となるPlaces APIについて簡単な紹介をします。
ご存知の通りFirefox 3ではブックマークと履歴の管理機能が一新されましたが、この新しい管理システムを「Places」と呼びます。Placesでは、ブックマークや履歴を操作するための多数のAPIがXPCOMサービスとして提供されいます。そのうち、今回使用するAPIの概要を表1に示します。
表1に挙げた以外にも様々なAPIが存在します。詳しくは下記URLをご覧ください。
ブックマーク済みかどうかのチェック
ここからは、選択範囲を取得する処理の前に、現在表示しているWebページのURLがブックマーク済みかどうかをチェックする処理を追加します。また、ブックマーク済みでない場合は警告メッセージを表示して処理を終了するようにします。「overlay.js」へリスト1の内容を追加してください。
あるURLがブックマーク済みかどうかを調べるには、表1に示したnsINavBookmarksServiceのisBookmarkedメソッドを使用します。nsINavBookmarksServiceのリファレンスに記載されている通り、isBookmarkedはnsIURIオブジェクトを引数とし、指定したURLがブックマーク済みかどうかを真偽値で返します。そこで、リスト1では、まずnsIIOServiceを使用してURLの文字列(変数「url」)からnsIURIオブジェクトを生成します。次に、nsINavBookmarksServiceを呼び出し(変数「bookmarksSvc」)、isBookmarkedによって先ほどのnsIURIオブジェクトがブックマーク済みかどうかを調べ、戻り値がfalseなら警告を表示して終了します。
なお、リスト1では「Cc」と「Ci」を使用していますが、これらは「browser.xul」から読み込まれるFirefox自体のJavaScriptソースファイル内で定義された定数で、それぞれ「Components.classes」「Components.interfaces」への参照です。
ブックマークへのタグ付け
ここからは、選択範囲を取得する処理の後に、現在表示しているWebページのURLに対するブックマークに対し、選択範囲の文字列からタグ付けする処理を追加します。「overlay.js」へリスト2の内容を追加してください。
ブックマークに対してタグ付けするには、表1に示したnsITaggingServiceのtagURIメソッドを使用します。nsITaggingServiceのリファレンスに記載されている通り、tagURIはnsIURIオブジェクトとタグ付けする文字列の配列を引数とします。そこで、リスト2では、タグ付けする文字列の配列(変数「keywords」)の要素が1個以上あるかを調べてから、nsITaggingServiceを呼び出し(変数「taggingSvc」)、tagURIによってタグ付けを行います。
JavaScriptコードモジュールを利用する
JavaScriptコードモジュールとは、Firefox 3で新たに導入された機能で、異なるJavaScriptのスコープ間で共有可能なシングルトンのオブジェクトを容易に実現することができます。例えば、複数のXULから利用される関数を大量に定義するような場合、それらをひとつのJavaScriptファイルにまとめて各XUL内で<script>タグで読み込むよりも、JavaScriptコードモジュール化して各XULへインポートしたほうがメモリの面などで効率が良いといった利点があります。
もちろん拡張機能が独自にJavaScriptコードモジュールを定義することもできますが、Firefox 3自体が定義している便利なJavaScriptコードモジュールがいくつかあり、これらを拡張機能から利用することもできます。そのうちのひとつである「PlacesUtils」は、Places APIがより利用しやすい形にまとめられています。あるJavaScriptのスコープで「PlacesUtils」をインポートして利用可能にするためには、リスト3のように記述します。
ただし、今回色々と機能を実装している「TagHelper」オブジェクトのスコープでは、すでにFirefox自体によって「PlacesUtils」がインポートされていますので[1]、リスト3の内容を記述しなくても「PlacesUtils」が利用可能です。
JavaScriptコードモジュールは、そのソースコード内で定義された配列「EXPORTED_SYMBOLS」の各要素と同一の名前を有するJavaScriptのオブジェクト(およびその全プロパティ)が外部から利用可能となります。「PlacesUtils」オブジェクトで利用可能な各プロパティについての説明は、下記URLにて解説されていますが、場合によっては「PlacesUtils」自体のソースコードを見たほうが早いかもしれません[2]。
「PlacesUtils」で定義されたプロパティのうち、今回使用するものを表2に示します。これらのプロパティを利用することで、リスト2の内容はリスト4のように簡潔に書き直すことができます。
表2 使用するPlacesUtilsのプロパティ
プロパティ | 詳細 |
PlacesUtils.bookmarks | nsINavBookmarksServiceへの参照。 |
PlacesUtils.tagging | nsITaggingServiceへの参照。 |
PlacesUtils._uri | nsIIOServiceでURL文字列からnsIURIオブジェクトを生成する[3]。 |
右クリックメニュー項目の表示制御
ここからは、DOMイベントリスナの仕組みによって、右クリックメニュー表示時に選択範囲の有無を調べてタグヘルパーのメニュー項目を表示/非表示する処理を追加します。「overlay.js」へリスト5の内容を追加してください。
リスト5の最後の2行は、「overlay.js」読み込み直後に実行されます。DOM:windowに対してイベントリスナを登録し、イベント発生時に以下の2処理を実行します。
- ブラウザウィンドウを開いた直後(「browser.xul」ロード完了に伴う「load」イベント発生時)に「TagHelper.init」を実行する。
- ブラウザウィンドウを閉じた直後(「browser.xul」アンロード完了に伴う「unload」イベント発生時)に「TagHelper.destroy」を実行する。
「TagHelper.init」は、右クリックメニューへ自分自身(「TagHelper」オブジェクト)をイベントリスナとして登録し、メニューを開いた直後(「popupshowing」イベント発生時)に「handleEvent」が呼び出されるようにします[4]。「TagHelper.destroy」は「TagHelper.init」の逆で、登録したイベントリスナを解除します。「TagHelper.handleEvent」では、念のため発生したイベントが「popupshowing」であることを確認し、「chrome://browser/content/browser.js」で定義された関数「getBrowserSelection」を使って選択範囲の文字列を取得し、空であればメニュー項目を非表示にします。
動作確認
ここまでのソースコード記述が完了したら、動作確認を行います。Firefoxの新しいウィンドウを開き、以下の3点を確認してください。
- ブックマークされていないWebページ上で範囲を選択し、右クリックから「Generate Tags from Selection」メニュー項目を選択すると、警告メッセージが表示される。
- ブックマーク済みのWebページ上で範囲を選択し、右クリックから「Generate Tags from Selection」メニュー項目を選択すると、選択範囲の文字列からタグ付けされる。
- 範囲を選択していない状態で右クリックすると、メニュー項目「Generate Tags from Selection」が非表示となる。
まとめと次回の予告
中編・後編とひたすらJavaScriptのコードを書いてタグヘルパーの機能を実装しました。機能のオブジェクト化、XPCOMサービス呼び出しよる高度な処理、DOMイベントリスナによるユーザの操作に応じた処理などは、拡張機能を開発する上では基本といえるでしょう。また、Firefox 3ならではのトピックとして、以下の3点についても触れました。
- FUEL
- Places API
- JavaScriptコードモジュール
ブックマークや履歴に関する拡張機能を開発するのであれば、Places APIの利用は欠かせないでしょう。また、JavaScriptコードモジュールはお手軽かつ有用であり、規模の大きな拡張機能を開発するのであれば、ぜひ導入を検討してみてはいかがでしょうか。
次回はタグヘルパーへlocaleパッケージを追加して拡張機能のUIをローカライズ可能にします。