GLOBAL-ALIGN::left ALIGN::center Firefox/Thunderbird用 拡張機能の 開発ノウハウ紹介 ---- HEADER::Firefox/Thunderbird用拡張機能の開発ノウハウ紹介 CHAPTER::自己紹介と概要 発表者:  下田洋志 aka "Piro"  自己紹介(略歴) ---- 2001  Mozilla用拡張機能の開発に手を出し始める  "コンテキストメニュー拡張"   ("ContextMenu Extensions")公開 2002  "タブブラウザ拡張"   ("Tabbrowser Extensions")公開 2004  Mozilla.Party.JP 5.0 2005  株式会社グッデイ 入社  Mozilla.Party.JP 6.0 2006  書籍 "Firefoxを究める256のテクニック" 上梓 ---- ALIGN::center 本日の 概要 ---- Part1  Firefoxの構造と  それを支える技術を知る Part2  拡張機能開発の  チュートリアル 質疑応答 ---- CHAPTER::関連技術の解説 HEADER:: ALIGN::center [[EM:Part1]] Firefoxの構造と それを支える 技術を知る ---- HEADER::Part1 Firefoxの構造とそれを支える技術を知る [[image src="01.jpg" width="800" height="555"]] ---- いくつかのキーワード ・XUL ・CSS ・JavaScript ・XPCOM ---- FOOTER::XUL ALIGN::center XUL ---- [[EM:X]]ML-based [[EM:U]]ser-interface [[EM:L]]anguage ---- ALIGN::center XMLベースの構造記述言語 [[PRE: ]] ---- ・HTMLに似通っている ・HTMLのフォーム関連要素のような  GUI部品(widget) ・DHTMLでは作るのが大変だった  様々なGUI部品を標準で利用できる  (ドロップダウンメニューや   スクロールバー、切り替え式のタブなど) ---- Firefox内部だけでなく Web上でも使える [[サンプル|https://piro.sakura.ne.jp/latest/blosxom.cgi/mozilla/index.xul]] このプレゼンツール 自体も…… ---- 言語仕様に関する情報 [[XUL Planet|http://www.xulplanet.com/]] [[http://www.xulplanet.com/]] ---- FOOTER::CSS ALIGN::center CSS ---- [[EM:C]]ascading [[EM:S]]tyle [[EM:S]]heets ---- 人間の理解しやすい形でXML文書の 表示を指定するスタイル言語 [[PRE: #content { font-size: 10pt; border-width: 1pt; border-color: red; border-style: solid; } ]] ---- [[EM:カスケーディング]]  衝突する指定は優先順位が一番高いものが  適用され、それ以外は無視される仕組み [[PRE: box#content { height: 200px; } box { height: 100px; border: 2px solid white; border-width: 3px; } ]]  ↓ [[PRE: { height: 200px; border-style: solid; border-color: white; border-width: 3px; } ]] ---- XULもCSSで整形 [[PRE: button[type="menu-button"] { -moz-box-align: center; -moz-box-pack: center; margin: 0; border: none; } .button-menu-dropmarker, .button-menubutton-dropmarker { margin: 1px; background-image: url("chrome://global/skin/arrow/arrow-dn.gif"); background-repeat: no-repeat; background-position: center center; min-width:11px; min-height:11px; } ]] ---- FOOTER::JavaScript JavaScript ---- ・[[ECMAScript(ECMA-262)|http://www.ecma-international.org/publications/standards/Ecma-262.htm]]  第3版に準拠した  プロトタイプベースの  オブジェクト指向言語 ・自由度が非常に高い ・Javaとは無関係 ---- FOOTER::XULとJavaScript ALIGN::center XUL と JavaScript の [[EM:DOM]]による 連携 ---- [[EM:D]]ocument [[EM:O]]bject [[EM:M]]odel JavaScriptの オブジェクトとして XML文書を操作 ---- FOOTER::XPCOM XPCOM ---- [[EM:Cross(X)]] [[EM:P]]latform [[EM:C]]omponent [[EM:O]]bject [[EM:M]]odel ---- ・プラットフォームに依存しない  コンポーネントの開発のための  フレームワーク ・それに基づいて開発された  コンポーネント ・そのコンポーネントが  提供する機能 ---- Firefoxにおいては 二つの役割を持つ ---- ・プラットフォームごとの差異を吸収して  単一のAPIで複数プラットフォームに  対応 ・JavaScriptでは実現できない  高度な処理を担当 ---- XPCOMの例:  [[EM:nsIFile]]インターフェースの  [[EM:create]]メソッド ・ファイルを生成する働き ・二つの引数を取る   ファイルタイプ(File or Directory)   パーミッション(UNIX形式)  →第2引数は場合によっては無視される ---- FOOTER::JavaScriptとXPCOM ALIGN::center JavaScript と XPCOM ---- [[EM:XPConnect]] JavaScriptから XPCOMを利用する 仕組み ---- 例:  XPConnectを利用して  JavaScriptからXPCOMを呼び出し  テンポラリフォルダを生成する [[PRE: const nsILocalFile = Components.interfaces.nsILocalFile; var file = Components.classes['@mozilla.org/file/local;1'] .createInstance(nsILocalFile); file.initWithPath('C:\\'); file.append('temporary-directory'); if (!file.exists()) { file.create(nsILocalFile.DIRECTORY_TYPE, 0777); } ]] ---- XPConnectを 利用するのに必要 [[EM:XPConnect特権]] ---- Firefoxのセキュリティ機構の一つ ・Firefox内部のスクリプトは特権を持つ ・拡張機能のスクリプトも特権を持つ ・Webページのスクリプトは特権を持たない ・ユーザが許可した場合は別 ---- Firefoxや拡張機能にバグがあった場合 意図せずWebページのスクリプトが XPConnect特権を取得できてしまう ことも…… ---- FOOTER:: ALIGN::center まとめ ---- [[image src="02.jpg" width="780" height="555"]] ---- FOOTER::「拡張機能」というメカニズムを実現するもの CHAPTER::拡張機能を実現する技術 拡張 機能 ---- ALIGN::center 「拡張機能」は 一体どうやって 実現されているのか ---- ALIGN::center 窓の○は [[EM:「プラグイン」]] と呼んでいるが 「プラグイン」とは どう違うのか ---- [[EM:プラグイン]] ・本体アプリケーションと  規約に則って通信を行い  処理の代行・機能の提供を行う  小さなアプリケーション部品  (一般的な意味) ・本体アプリケーションが  備えている機能のための  追加の定義ファイル ---- [[EM:Firefoxの拡張機能]]  本体に[[EM:動的に組み込まれるパッチ]]  的なもの ---- 動的に 組み込まれる ---- Firefoxを構成 している技術は どれも  [[EM:後からの変更]]  [[EM:機能の上書き・追加]] をサポート ---- ・CSS ・JavaScript ・XUL ・XPCOM ---- CSS ---- [[EM:カスケーディング]] ---- [[EM:カスケーディング]]  衝突する指定は優先順位が一番高いものが  適用され、それ以外は無視される仕組み [[PRE: box#content { height: 200px; } box { height: 100px; border: 2px solid white; border-width: 3px; } ]]  ↓ [[PRE: { height: 200px; border-style: solid; border-color: white; border-width: 3px; } ]] ---- Firefoxに内蔵されている スタイルシート  ↓ 拡張機能が追加した スタイルシート  ↓ ユーザースタイルシート という順に適用される ---- =拡張機能でFirefoxの  元々のスタイル定義を  上書きできる ---- ALIGN::center スタイルシート だけを含む 拡張機能 || [[EM:テーマ]] ---- JavaScript ---- JavaScriptでは 文字列も数値も関数も 全てオブジェクト としてアクセスする ---- オブジェクトへの プロパティやメソッドの 結びつけは Classを必要とせず 代入だけで実現できる ---- [[PRE: var obj = new Object(); obj.objectProperty = new Object(); obj.objectProperty.newProperty = 'string' obj.objectProperty.parent = obj; obj.myself = obj; ]] 関数も代入できる(=メソッドになる) [[PRE: var obj = new Object(); obj.name = 'Firefox'; function sayName() { alert(this.name); } obj.sayMyName = sayName; obj.sayMyName(); // sais "Firefox" ]] ---- プロパティ同士での代入もできる [[PRE: obj.propertyA = 'foobar'; obj.propertyB = obj.propertyA; alert(obj.propertyB); // sais "foobar" ]] メソッド同士での代入もできる [[PRE: obj.name = 'Thunderbird'; obj.methodA = function() { alert(this.name); }; obj.methodB = obj.methodA; obj.methodB(); // sais "Thunderbird" ]] ---- window.open()を乗っ取って Googleのページを開こうとしたら 必ずブロックするようにしてみる [[PRE: window.__original__open = window.open; widnow.open = function(aURI, aName, aFlag) { if (aURI.indexOf('.google.') > -1) return null; return this.__original__open(aURI, aName, aFlag); }; window.open('http://www.google.co.jp/'); // will be blocked ]] ---- 拡張機能のスクリプトで Firefox内部のオブジェクトに 新しい機能を加えることも 既存の機能を置き換えることも できる ---- XUL ---- CSSの カスケーディング のような仕組み? ---- XUL独自の機能 [[EM:オーバーレイ]] ---- 元のXUL文書 [[PRE: ]]  + content.xul [[PRE: ]]  ↓ 読み込みの段階でID名などをキーにして統合 [[PRE: ]] ---- JavaScriptとDOMを使って XULを編集する方法も ---- XPCOM ---- XPCOMコンポーネントの 機能は編集できないが 新しいXPCOMコンポーネントを 組み込むことはできる ---- JavaScriptからXPCOMを XPConnectで呼び出している部分を 拡張機能のスクリプトで 置き換えれば…… ---- ALIGN::center まとめ ---- XUL  →オーバーレイとDOM JavaScript  →プロパティ・メソッドの   乗っ取り(など) CSS  →カスケーディング XPCOM  →新しく追加して置換 ---- ・インタープリタ型なので  拡張機能による変更が  動的に適用される ・コンパイルすることなしに  誰でも簡単に  変更を適用したり  元に戻したりできる ---- つまり 拡張機能は理論上は 何でもできる (Firefoxを別物に  変えてしまうことすら) ---- CHAPTER::開発環境の整備 HEADER:: FOOTER:: ALIGN::center [[EM:Part2]] 拡張機能 開発の チュートリアル ---- HEADER::Part2 拡張機能開発のチュートリアル FOOTER::開発環境に必要なもの ALIGN::center 開発環境に 必要なもの ---- [[EM:絶対に必要]]  ・テキストエディタ   (UTF-8を扱えるもの)  ・アーカイバ   (ZIP形式を扱えるもの) [[EM:あると便利]]  ・JavaScriptデバッガ ---- テキストエディタの例 (Windows) 秀丸エディタ  [[http://hide.maruo.co.jp/]] TeraPad  [[http://www5f.biglobe.ne.jp/~t-susumu/]] ---- アーカイバの例 (Windows) 7-Zip  [[http://www.7-zip.org/ja/]] ---- Venkman JavaScriptデバッガ  [[http://www.hacksrus.com/~ginda/venkman/]]  [[(日本語パック)|https://piro.sakura.ne.jp/latest/blosxom.cgi/mozilla/extension/2005-09-30_venkman-ja.htm]] ---- ALIGN::center しておくと 便利な設定 ---- コンソールへの出力を有効化 [[PRE: user_pref("browser.dom.window.dump.enabled", true); ]] dump("文字列") という機能が使えるようになる 渡した文字列がコンソールに表示される ※Windows環境ではFirefoxを   -consoleオプション付きで起動する  LinuxやMac OS XではFirefoxを   ターミナルから起動する ---- JavaScriptコンソールへの内部エラーの表示 [[PRE: user_pref("javascript.options.showInConsole", true); ]] ※「ツール」→「JavaScriptコンソール」で  JavaScriptコンソールを起動 ---- FOOTER::拡張機能を実際に作ってみる ALIGN::center 拡張機能を 実際に 作ってみる ---- 拡張機能のタイプ ・新機能を加えるもの ・既存機能の挙動を  変えるもの ---- CHAPTER::Close All Tabs FOOTER::拡張機能を実際に作ってみる - Close All Tabs ALIGN::center [[EM:Close All Tabs]] 「すべてのタブを一度に閉じる」 ボタンをツールバーに加えてみる ---- 目標(要求仕様)  ・ツールバーに「すべてのタブを閉じる」   ボタンを加える。  ・ボタンを押すと、空のタブを残して   すべてのタブを閉じる。  ・「すべてのタブを閉じる」という項目を   「ファイル」メニューの中にも加える。  ・キーボードショートカット「Ctrl-Q」でも   機能を利用できるようにする。 ---- 作業手順  1. IDを決める  2. どこをいじればいいか調べる  3. フォルダとファイルを用意する  4. XULで構造を定義する  5. JavaScriptで挙動を定義する  6. CSSで外観を定義する  7. パッケージングする  8. 配布 ---- 用意するもの:  ボタン用アイコン画像   大サイズ 24×24 [[image src="icon.png" width="72" height="72"]]   小サイズ 16×16 [[image src="icon-small.png" width="48" height="48"]] ---- ALIGN::center IDを決める ---- 使えるIDの形式  [[EM:UUID(GUID)]]:完全なID   {E0EACCD1-98F3-4936-A229-41C667E820B8}  [[EM:名前@ドメイン]]:簡易的なID   closealltabs@piro.sakura.ne.jp ---- ALIGN::center どこをいじれば いいか調べる ---- DOMインスペクタ ---- ソースコード全文検索 (LXR) [[lxr.mozilla.org/mozilla/]] ---- ALIGN::center フォルダと ファイルを 用意する ---- [[image src="03.jpg" width="319" height="600"]] ---- ALIGN::center XULで 構造を 定義する ---- closealltabs.xul [[PRE: