GLOBAL-ALIGN::left ALIGN::center 拡張機能 開発の 基礎知識 [[EM:Part2]] ---- CHAPTER::拡張機能って何? [[EM:拡張機能]]って何? どうやって作るの? ---- HEADER::拡張機能って何? どうやって作るの? FOOTER::「拡張機能」というメカニズムを実現するもの 拡張 機能 ---- ALIGN::center 「拡張機能」は 一体どうやって 実現されているのか ---- ALIGN::center [プラグイン] とはどう違うのか ---- [[EM:プラグイン]] 本体アプリケーションと 定型的な通信を行って 処理を代行する、小さな アプリケーション部品 ---- Firefoxの拡張機能は [[EM:動的に組み込まれる パッチ]]のようなもの ---- パッチ? ---- [[PRE: Index: layout/xul/base/src/nsNativeScrollbarFrame.cpp =================================================================== RCS file: /cvsroot/mozilla/layout/xul/base/src/nsNativeScrollbarFrame.cpp,v retrieving revision 1.22 diff -u -6 -p -r1.22 nsNativeScrollbarFrame.cpp --- layout/xul/base/src/nsNativeScrollbarFrame.cpp 31 Dec 2004 01:13:26 -0000 1.22 +++ layout/xul/base/src/nsNativeScrollbarFrame.cpp 28 Jul 2005 22:06:05 -0000 @@ -342,6 +342,68 @@ nsNativeScrollbarFrame::Hookup() if (!curpos || error) return; scrollbar->SetPosition(curpos); } +NS_IMETHODIMP +nsNativeScrollbarFrame::Paint(nsPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer, + PRUint32 aFlags) +{ + if (NS_FRAME_IS_UNFLOWABLE & mState) { + return NS_OK; + } + + if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { + PaintSelf(aPresContext, aRenderingContext, aDirtyRect); + } + + return nsBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, + aWhichLayer); +} ]] ---- 動的に 組み込まれる? ---- 実は ---- Firefoxを 構成している 主な技術 ---- CSS JavaScript XUL XPCOM ---- どれも ・[[EM:後からの変更]] ・[[EM:機能の上書き・追加]] ができる ---- 順番に見ていきましょう ---- CHAPTER::CSSの上書き CSS ---- [[EM:カスケーディング]] ---- 衝突する指定は、優先順位が 一番高いものが適用され それ以外は無視される (指定が上書きされる) ---- ALIGN::center [[PRE: box { height: 100px; border: 2px solid white; } box#content { height: 200px; border-width: 3px; } ]]  ↓ [[PRE: { height: 200px; /* 後から上書きされた値 */ border-style: solid; /* 元からある値 */ border-color: white; /* 元からある値 */ border-width: 3px; /* 後から上書きされた値 */ } ]] ---- ALIGN::center Firefox内蔵のスタイルシート ↓ 拡張機能のスタイルシート ↓ ユーザースタイルシート という順に読み込まれ 上書きされていく ---- つまり ---- 拡張機能でFirefoxの 元々のスタイル定義を 上書きできる ---- ちなみに ---- スタイルシート だけを含む 拡張機能 =[[EM:テーマ]] ---- 次 ---- CHAPTER::XULの上書き XUL ---- XMLの一種 ---- XMLで一般的に使える CSSのカスケーディング のような仕組みはまだ無い ---- そこで XUL独自の機能 ---- [[EM:オーバーレイ]] ---- 複数のXUL ドキュメントを 1つにまとめて 合成する機能 ---- 元のXULドキュメント [[PRE: ]]  + オーバーレイ用のXULドキュメント [[PRE: ]] ---- 2つのXUL ドキュメントを ID名などを キーにして合成 ---- 合成後のXULドキュメント [[PRE: ]] ---- HIDDEN::true オーバーレイの 3つの方法 ---- HIDDEN::true [[EM:1]] ファイルの中での オーバーレイ指定 ---- HIDDEN::true [[PRE: ]] ---- HIDDEN::true CやPHPのinclude Perlのrequire みたいな ---- HIDDEN::true ライブラリの 読み込み的な 使い方 ---- HIDDEN::true XULドキュメント 読み込み時に オーバーレイ先も 常に読み込む ---- HIDDEN::true [[EM:2]] スクリプトによる 動的オーバーレイ ---- HIDDEN::true [[PRE: var observer = { observe : function(aS, aT, aD) { ... } }; document.loadOverlay( 'somefile.xul', observer ); ]] ---- HIDDEN::true 任意のタイミング でオーバーレイ先 ドキュメントを 読み込める ---- HIDDEN::true 必要に応じて実行すれば 最初の方法に比べて XULドキュメント 読み込みの体感速度が 向上 ---- HIDDEN::true [[EM:3]] chrome.manifestの 記述に基づく オーバーレイ ---- HIDDEN::true 詳しくは 後で話します ---- オーバーレイ 以外の方法 ---- スクリプト の利用 ---- JavaScriptと DOMでXULを 編集する ---- ALIGN::center ||柔軟性|メンテナンス性 |オーバーレイ|低|~高 |JavaScript+DOM|~高|低 ---- 場合に応じて 使い分けよう ---- 次 ---- CHAPTER::JavaScriptの上書き JavaScript ---- 2つの 特徴 ---- [[EM:1]] 文字列も数値も関数も 全てオブジェクトまたは オブジェクトのプロパティ としてアクセスする ---- [[EM:2]] オブジェクトへの プロパティの結びつけは 代入だけで実現できる (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" ]] ---- HIDDEN::true プロパティ同士 での代入もできる ---- HIDDEN::true [[PRE: obj.propertyA = 'foobar'; obj.propertyB = obj.propertyA; alert(obj.propertyB); // sais "foobar" ]] ---- HIDDEN::true メソッド同士 での代入もできる ---- HIDDEN::true [[PRE: obj.name = 'Thunderbird'; obj.methodA = function() { alert(this.name); }; obj.methodB = obj.methodA; obj.methodB(); // sais "Thunderbird" ]] ---- これらを 踏まえて ---- [[EM:改造]] 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 ]] ---- 拡張機能のJavaScriptで 新しいメソッドを定義する →[[EM:機能の追加]] ---- 拡張機能のJavaScriptで 既存のメソッドを置き換える →[[EM:挙動の変更]] ---- 次 ---- CHAPTER::XPCOMの上書き XPCOM ---- XPCOM コンポーネントの 機能は編集できない (バイナリなので) ---- が ---- 新しいXPCOM コンポーネントの [追加]はできる ---- + ---- XPCOM コンポーネントは [JavaScript] から呼び出される ---- = ---- [XPCOMを呼び出している] [XPConnect]の部分の JavaScriptのメソッドや 関数を置き換えればよい ---- CHAPTER::拡張機能はプラグインと言うよりもパッチ まとめ ---- ALIGN::center |XUL |オーバーレイ+DOM |JavaScript|プロパティやメソッドの
上書き |CSS |カスケーディング |XPCOM |コンポーネントを
追加して置換 ---- プラグインとは 原理が違う ---- ALIGN::center | |はたらき |実態 |プラグイン|Firefoxに頼まれて
データを処理する |外部の
ソフトウェア |~拡張機能 |~Firefoxの
内部コードを
直接変更する|~パッチ ---- でも、ただの パッチでもない ---- パッチとの 最大の違い ---- [[EM:後から 適用できる]] ---- XULも JavaScriptも CSSも [コンパイル]不要 ---- ビルドやインストールの後から いくらでもFirefoxを 改変したり元に戻したりできる ---- [[EM:=拡張機能の  特徴]] ---- ALIGN::center | |導入/削除|できること |プラグイン |簡単 |限られている |ソースへの
パッチ|難しい |何でもできる |~拡張機能 |~簡単 |~何でもできる ---- CHAPTER::締め HEADER:: FOOTER:: つまり 言いたいのは ---- 拡張機能は プラグインよりも パッチよりも強力な カスタマイズ手段 ---- 一緒にしちゃ イヤン ---- OK ---- それは 分かった ---- 実際に やってる 所を見せれ ---- そこで ---- [[EM:Part3]] につづく