アドオンした事がない人が15分間でFirefoxアドオン開発

カテゴリ
ブックマーク数
このエントリーを含むはてなブックマーク はてなブックマーク - アドオンした事がない人が15分間でFirefoxアドオン開発
このエントリーをはてなブックマークに追加

こんにちは。ライブドアの駒井です。

つい先日、友人に誘われて半ば強制的に「Firefox Developers Conference 2009」に参加してきました。誘ってきた友人が、当日の急用で北海道に帰る事になり、何故か私1人で不慣れな場に参加してきました。当日優しくしてくれた皆さんありがとうございました。いただいたFirefoxのTシャツも大事にします。

自分の予想に反してとっても有意義な時間となりました。筆者は普段、JavaScriptを全く書きません。C++とJAVAがメインです。そんな私でも気軽に楽しめてしまうのがFirefoxアドオンでした。ということで、Firefoxアドオンを作成するための最低構成で、簡易的なアドオンを15分程度で実験的に作ってみたいと思います。

題材を模索中に自社営業部の人から次のようなアドオンがあったらありがたいと聞きました。営業訪問に際して必ず行う下記2点のうち(1)の作業に関するものでした。

(1) 訪問予定の顧客のHPで訪問先の住所を調べる。
(2) その住所周辺のカフェやWifiアクセスポイントの情報を知りたい。

なるほど、訪問先の顧客ビルの近くで時間をつぶすときなどに、カフェや公衆無線LANのあるカフェを見つけたくなるようです。ブラウザの中で表示される「住所」や「駅名」を見つけたら、ノンストップで周囲のカフェやアクセスポイント情報を知りえる簡易的なアドオンなら15分程度で作れそうだと思い、作ってみることにしました。

開発にあたって用意したのは次の3つだけ。「Firefox」、「メモ帳」、「最低3つのファイル」。具体的には次の3つのファイルになります。

1. install.rdf

作成するアドオンに関するメタデータを記載したXMLファイル。作成する拡張固有の情報などが中心となります。例えば、作成するアドオンの名前、概要、バージョン、作成者などを記述します。アドオンのIDの記述に際しては、一意の識別IDを決める必要があり、ドメインなどを利用するのがいいと思います。コード1にあるようなソースを書いてみました。XMLなのでエンコードはUTF-8にしておきました。

コード1(install.rdf)

<?xml version="1.0" encoding="UTF-8"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">

<Description about="urn:mozilla:install-manifest">
<em:id>yourID</em:id>
<em:version>1.0.0</em:version> 
<em:type>2</em:type>

<em:targetApplication>
<Description>
<em:id>{techblog.livedoor.jp}</em:id> 
<em:minVersion>3.0</em:minVersion> 
<em:maxVersion>3.5.*</em:maxVersion>
</Description>
</em:targetApplication>

<!-- 拡張機能の説明 -->
<em:name>ten_minutes</em:name>
<em:description>【sample】周辺にcafeあるか?</em:description>
<em:creator>livedoor_techblog</em:creator>
<em:homepageURL>http://blog.livedoor.jp/techblog/</em:homepageURL>
</Description>
</RDF>

2. overlay.xul

ここで定義したGUIがブラウザウィンドウ(chrome://browser/content/browser.xul)にオーバーレイし、メニュー項目やボタンなどの追加などを実現します。xulファイルを作成します。今回は、コンテキストメニューに表示するメニュー項目の追加をしてみました。(コード2)

コード2(overlay.xul)

<?xml version="1.0"?>

<overlay
    id="techblog.livedoor.jp"
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

    <script
	type="application/x-javascript"
	src="chrome://techblog.livedoor.jp/content/conf.js" />
    <script
	type="application/x-javascript"
		src="chrome://techblog.livedoor.jp/content/overlay.js" />

 <popupid
		id="contentAreaContextMenu">
    <menu
		id="techblogMenu"
		class="menu-iconic"
	    	image="chrome://techblog.livedoor.jp/skin/ld.png"
			insertafter="context-bookmarkpage"
			label="lookup cafe or WIFI"

	        onclick="setTimeout('techblogOnMap()',200);"
	        style="list-style-image: url('chrome://techblog.livedoor.jp/skin/ld.png')" >

      <menupopup
        	id="techblogMenupopup">

		<menuitem
			label="Cafe"
			oncommand="changeMapType(0);" />
		<menuitem
			label="Cafe + WIFI"
			oncommand="changeMapType(1);" />
      </menupopup>

    </menu>
 </popupid>

</overlay>

メニュー項目を選択した後の具体的なイベントハンドラも付け加えたかったのでJavaScriptで記述しました。xulファイルの中にもJavaScriptを記述出来ますが、今回は分離してファイルを作成しました。(コード3)

コード3(overlay.js)

var SELECTED_TEXT = "";
var MAP_TYPE = -1;
var DEFAULT_LOCATION = "";

var sampleOptions = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
function changeMapType(mapType)
{
   setSelectedText();
   MAP_TYPE = mapType;
}

function techblogOnMap()
{
   try
	{
        if(MAP_TYPE == -1)
	{
	    setSelectedText();
	}

	document.getElementById('contentAreaContextMenu').hidePopup();
	switch(MAP_TYPE)
	{
		case 1 :
		{
		gBrowser.selectedTab = gBrowser.addTab("http://local.google.co.jp/maps?q=Wireless cafe loc:"+SELECTED_TEXT);
		break;
		}
		case 0 :
		{
		}
		case -1 :
		{
		gBrowser.selectedTab = gBrowser.addTab("http://local.google.co.jp/maps?q=cafe loc:"+SELECTED_TEXT);
		break;
		}
	}
	MAP_TYPE = -1;
	}

   catch(e)
	{
	if(DEBUG)
	{
        alert("Error: (teckblogOnMap)" + e);
	}
	}
}

function setSelectedText()
{
	try
	{
		SELECTED_TEXT = "";
		if(gContextMenu.onTextInput)
		{
			var oTextBox = gContextMenu.target;
			SELECTED_TEXT = oTextBox.value.substring(oTextBox.selectionStart, oTextBox.selectionEnd);
		}
		else
		{
			if(gContextMenu.searchSelected)
			{
				SELECTED_TEXT = gContextMenu.searchSelected();
			}
			else
			{
				SELECTED_TEXT = getBrowserSelection();
			}
		}

		SELECTED_TEXT = SELECTED_TEXT.replace(/s+/g, ' ').replace(/^s+|s+$/g, '');
		if(SELECTED_TEXT == "")
		{
			SELECTED_TEXT = DEFAULT_LOCATION;
		}
	}
	catch(e)
	{
	if(DEBUG)
	{
		alert("Error: (setSelectedText)" + e);
	}
  }
}
DEFAULT_LOCATION = sampleOptions.getCharPref("sample.options.location");

XULファイル内の「label部」にて、メニュー項目内で表示する文字列を記述し、「oncommand部」にて、メニュー項目を選択時に実行するJavaScriptを指定しています。JavaScriptは次の3つのイベントを担当するだけの単純なものにしました。

(A) 選択した文字列の取得
(B) 選択した文字列からURLの構築(検索する文字列のパターンを構築)
(C) 新規TABでURLを開く

3. chrome.manifest

Firefoxに対する拡張のリソースを定義するファイルです。作成した拡張は、拡張内の各ソースファイルのパスが「クロムURL」と呼ぶ特殊なURIへマッピングされて利用可能となるため、ソースファイルを格納するフォルダへのパスの設定を記述します。(コード4)

コード4(chrome.manifest)

content techblog.livedoor.jp chrome/chrome/content/
overlay chrome://browser/content/browser.xul chrome://techblog.livedoor.jp/content/overlay.xul

例えば、Firefoxのブラウザウィンドウは「chrome://browser/content/browser.xul」というクロムURLによって表されます。これは、パッケージ名が「browser」のcontentパッケージ内に格納された「browser.xul」というソースファイルに対応していることになります。クロムURLは「chrome://<パッケージ名>/<パッケージの種類>/<ソースファイルの相対パス>」という記述形式となります。

「overlay」で始まる2行目の記述により、contentフォルダ内のoverlay.xulは「chrome://techblog.livedoor.jp/content/overlay.xul」というクロムURLでアクセスできるようになり、「overlay.xul」をFirefoxウィンドウ「chrome://browser/content/browser.xul」へオーバーレイ出来るようになります。

と、以上3つのファイルを作成しインストールする作業をストップウォッチ片手に全速力でやってみました。

15分で出来るのか?

結果
★ install.rdf 作成 (0秒 → 2分50秒)
    ↓
★ overlay.xul 作成 [+ overlay.js] (2分50秒 → 13分20秒)
    ↓
★ chrome.manifest 作成 (13分20秒 → 14分45秒)
    ↓
★ 拡張のインストール作業 + firefox再起動 (14分45秒 → 15分30秒)

15分を少し超えてしまいましたが(orz)、想像以上のスピードで作成することが出来ました。

私は今回の15分間で新しい楽しみを覚えてしまいました。皆さんも試してみてください。

作成したアドオンのイメージ

1

2

3

4

最後にFirefoxのアドオンを作ってみての感想を書いてみたいと思います。

  • 特別な開発ツールは必要ない。効率的な開発を行うに当たっては、便利なアドオンがいくつかあった。
  • 自社サービスを使ってもらいやすく出来る。
  • Firefoxの拡張により、特定のターゲットにリーチする機会を得る事が出来る。