Join MDN and developers like you at Mozilla's View Source conference, 12-14 September in Berlin, Germany. Learn more at https://viewsourceconf.org

Gecko Embedding Basics

 

情報、エンターテイメント、そして個人に関連したことの源としてウェブの重要性がますます高まるにつれて、HTML 形式で蓄えられたデータにアクセスし閲覧できることは、幅広い他の高度に分岐したソフトウェアアプリケーションにとってますます重要になってきています。それが単純な HTML ページビューワの問題であろうと成熟したウェブブラウザの問題であろうと、HTML ベースの文書を解釈、表示できることは本当に多くの状況においてますます重要な機能です。アプリケーション開発者にとって問題となっているのは、開発期間を最小限にしながらも機敏でがっしりとした製品を仕上げるには、どのようにしてこの決定的に重要な機能性を実装するかです。Gecko、Netscape と Mozilla の心臓部であるレンダリングエンジン "Gecko"を組み込むことは、この問題に対する傑出した解決策です。

なぜGeckoなのですか

Gecko を組み込むことは賢い選択です。Gecko は機敏で、がっしりしていて、高度に標準に準拠しています。Mozilla と Netscape のソフトウェアの中で、それは広く配付され、非常に良くレビューされています。

Gecko はオープンソースです。他の組み込み選択肢とは違って、Gecko のソースコードの全ては自由に入手でき、完全にカスタマイズできます。必要なだけいじくりまわしたり微調整したりできるのです。そして、選択されるライセンスに影響されるにもかかわらず、他の完全な私有商業製品にも、コンポーネントとして Gecko を使用することができます。

そして、Gecko は Mozilla プロジェクトと関連しているので、Gecko を組み込むための努力を援助するための多くの資源が利用できます。Mozilla のウェブサイト、mozilla.org日本語版)、には組み込みプロジェクトのエリア mozilla.org/projects/embedding/日本語版)があります。Gecko を組み込んでいる人たちに関連したたくさんのニュースグループだけでなく、彼らの間の情報交換に焦点を当てたニュースグループ、 netscape.public.mozilla.embedding、もあります。コードベースのための完全な相互参照は lxr.mozilla.org/seamonkey/日本語版)で利用できます。そして、あらゆるバグを整理したり、その過程を追跡したり、修正を支援することは、Bugzilla バグデータベースである bugzilla.mozilla.org/日本語版)を通じて簡単に行うことができます。

Gecko はまた、頭のてっぺんからしっぽの先まで完全に OS に依存しないように作られています。mozilla.org から直接に、それは Wintel、Mac OS 9.0 と OS X、そして Linux で動きます。そして、たくさんの他の OS 環境へのサードパーティーポートがあります。

最後に、Gecko の使用を許可することは無料です。たとえ最終的なアプリケーションが他の私有の商業的なアプリケーションであっても。非常に一般的に、Mozilla 提供のソースコード(組み込まれたコードではなくて)のどんな修正も私たちのコミュニティーに還元しなければなりません。その同じ元のコードをアプリケーションユーザーの方にも利用できるようにしなければなりません(しばしば mozilla.org ウェブサイトへのリンクによって)。そして、そのアプリケーションは Gecko を組み込んだものであるということを、いくつかの明らかな方法(例えば、ボックス上のロゴや About: ページ上に)で示さなければなりません。利用可能なライセンス形態の厳密な記述は www.mozilla.org/MPL/日本語版)に示されています。これはライセンス情報に関する法的効力を持つ唯一の完全な情報です。

組み込むのに必要なこと

ひとたび組み込もうと決心したならば、たどらなければならない、3つの主なステップがあります。第1に、コードを手に入れなければなりません。その後に、Gecko コードベースを上手に扱うのに使われている具体的な技術のいくつかを理解しなければなりません。最後に、どの追加の機能を加えたいのか決めなければなりません。このセクションは、あなたをこれらのステップへと案内するでしょう。

コードを手に入れる

現時点で Gecko を組み込むために必要となるファイルを入手する最も良い方法は、全ての Mozilla のソースツリーをダウンロードしてビルドすることです。これは実際、かなり単純な過程です。完全なガイドと関連するリンクは Mozilla のソースコードをダウンロードするで入手できます。次善の、コンポーネントごとに処理する方法は、発展途上で、依然としてβ版の段階です。このプロジェクトについての情報は www.mozilla.org/projects/embedding/GRE.html日本語版)に見つけられます。さらに、Gecko ランタイム環境(Gecko Runtime Environment, GRE)の開発についても作業が行われています。GRE は、単一のコアライブラリのセットを利用して、Mozilla コンポーネント上にビルドされた多彩なアプリケーションをサポートするでしょう。このプロジェクトは www.mozilla.org/projects/embedding/GRE.html日本語版)にあります。(もしコンポーネントごとに作業に取りかかりたいなら、バージョンとバイナリの互換性の問題に特に気をつけなければなりません。この領域のヘルプは mozilla.org/projects/xpcom/glue/Component_Reuse.html日本語版)を見て下さい。)

まず第一に、あなたはいくつかのツールを手に入れなければなりません(基本的には、サポートされたコンパイラ、Perl 配布パッケージ(ディストリビューション)、そして、いくつかの一般的な目的のユーティリティー)。その後、あなたのコンピュータ環境を設定しなければなりません。その次に、ソースをダウンロードしなければなりません。全ツリーをダウンロードしようと思っているなら、2つの方法があります:完全なツリーの tarball を FTP で入手できます。(これは、最も単純な方法です。そして、コンパイルする保証がされています。しかし、それはコードへの最新の追加を含んでいないかもしれません。)または、完全に最新のコードを入手したり、追加更新するために CVS を使うことができます。ひとたびツリーとツールを手に入れ、環境を適切に準備したら、あなたは提供された適切な makefile を走らせさえすれば良いのです。サポートされた OS 環境ごとに詳細な説明があります。

ビルドが完了した時、mozilla/embedding/ config ディレクトリへ、ナビゲートして下さい。そこでは、異なった OS 環境でそれぞれ組み込むための manifest ファイルのサンプルが見つかるでしょう。(全ての名前は "basebrowser" で始まります。)これらはただのサンプルであり、あなたの必要性に完全には合わないかもしれません。しかし、始めるには良い場所です。見本として使うことのできるそれぞれの OS 環境のための組み込みプロジェクトのサンプルもあります。mozilla.org/projects/embedding/examples/index.html日本語版)を見て下さい。

コーディング環境を理解する

Mozilla は始めから様々なプラットフォーム間とプログラム言語間を横断して設計と開発をサポートする準備をしていました。この目的のために、数多くの組織内でプログラミング技術が開発されました。そして、それら全てがオブジェクトのカプセル化(情報隠ぺい)という理想に基づいていました。Gecko を組み込む作業をする際には、必然的にこれらの技術の実践的な知識を身に付けることが伴います。そしてそれには、XPCOM、XPIDL、 XPConnect、特別な文字列クラス、場合によっては XUL、を含んでいます。以下の章では、それらへの端的な導入を提供します。更なる情報は mozilla.org サイトで見つけることができます。

XPCOM

Mozilla の技術の最も重要なのは XPCOM、the Cross-Platform Component Object Model(プラットフォームに依存しないコンポーネントオブジェクトモデル)、です。XPCOM は Mozilla 全体を通じてオブジェクトと他のデータの生成、所有、削除を管理する枠組みを提供します。もしあなたが MSCOM を使っているならば、ある基礎的な類似に気がつくでしょう。しかし、重大な違いもあります - XPCOM はプラットフォームに依存せず単一のスレッドの中で幅広く動くよう意図されていて - そしてその2つは今のところ互換性はありません。

インターフェース

XPCOM の核となる部分にこそ、インターフェースの構想があります。インターフェースは、全て特定の機能に関連した、一連のメソッド、属性、関連した定数の単純な記述です:それらのものを実装するクラスとは完全に違います。インターフェースは一種の契約(コントラクト)として供給します:特定のインターフェースをサポートするあらゆるオブジェクトは、それに記述されたサービスをそれが演じることを保証します。インターフェースを可能な限り言語間で平等に保つために、それは特別な言語、インターフェース定義言語 (Interface Difinition Language、IDL)、で書かれています。インターフェースのファイルはしばしば .idl ファイルとして参照されます。これらのファイルは、インターフェースの機能を明細に述べているのに加えて、インターフェースの IID、すなわち、そのグローバルに唯一な識別番号(ID 番号)を運びます。

Gecko 内でのコミュニケーションの多くは、これらの抽象的な構造の点で起きます(慣習から、それらの名前は nsISomething という形式に従います)。

//こう
void ProcessSample(nsISample* aSample) {
	aSample->Poke("Hello"); 
//こうではない
void ProcessSample(nsSampleImpl* aSample) {
	aSample->Poke("hello"); 
@status FROZEN

XPCOM の抽象のレベルはシステム内での大きな柔軟性を生みます。実装は必要な時に自由に変化します。しかし、はたらくためにはインターフェース自体は固定したままでなければなりません。Mozilla の初期の設計と開発期間全体を通じて、インターフェースはいくらか流動的であってきました。しかしプロジェクトが成熟してくるにつれて、ますます多くのインターフェースが FROZEN(凍結)と印を付けられました。印付けされたどんなインターフェースも将来変化しないと保証されています。

組み込み努力のカギとなる主要なインターフェースのほとんどは、現在凍結されています。しかし、あらゆるインターフェースを使う前に確かめるのは常に良い考えです。インターフェースの状態は .idl ファイルのコメントに一覧表にされています。凍結されたインターフェースは @status FROZEN と印が付けられています。あなたは mozilla 相互参照ツールを使って、lxr.mozilla.org/seamonkey/search?string=%40status+FROZEN に凍結されたインターフェースを探すことができます。凍結されるまでインターフェースはいつ何時変わるかもしれません。凍結過程について詳しい情報は、 組み込みプロジェクトのページ を見て下さい。

ひとたびインターフェースが凍結されたら、Gecko 組み込み API リファレンス に加えられます。

nsISupports

1つのオブジェクトが1つよりも多くのインターフェースをサポートできます。実際、基本的には全てのオブジェクトは、少なくとも2つのインターフェースをサポートします - 特別に役立つ何かをする最小限のインターフェースと、より一般的な目的を供給するインターフェース、nsISupports です。ある意味、nsIsupports は全ての XPCOM インターフェースの原型です。全てのインターフェースはそれから継承します。ほとんどは直接的に継承しています。 それは2つの主要機能を供給します - ランタイムタイプの発見とオブジェクトの寿命管理です。これは MSCOM の IUnknown と機能的には同一のものです。

オブジェクトは多様なインターフェースをサポートできるので、 1つのインターフェースへポインタをもつことや、異なったインターフェース - あなたがひょっとしたらそのインターフェースの機能を必要とするかもしれない - もまたサポートするかどうか知りたい、といったことは完全に可能です。 nsISupports の最初のメソッドである QueryInterface はまさにこれを行うものです。これは実際、「私はこのオブジェクトがタイプ A(インタフェース A に対応)のものであることを知ってるけど、タイプ B(インタフェース B に対応)でもあるかい?」といった質問ができます。

もしそれがそうである(または知っている)ならば、QueryInterface() は新たに要求されたインターフェースに縛りつけられたポインタを呼び出し元に返します。

void ProcessSample(nsISample* aSample) {
	nsIExample *example;
	nsresult rv;
	rv = aSample->QueryInterface(NS_GET_IID(nsIExample),(void **)&example);
	if (NS_SUCCEEDED(rv)) {
		example->DoSomeOperation();
		NS_RELEASE(example); //Release を呼び出すためにマクロを使用します
	}
}

XPCOM は実際にオブジェクトを生成するための間接的なメソッド、コンポーネントマネージャー(Conponent Manager)を使用しているから、そして同じオブジェクトへの - しばしば異なったインターフェースに縛りつけられた - 多様なポインタが存在できるから、呼び出し元がそれらのポインタがポイントする全てのオブジェクトを現在見失わないことは、急速に難しくなってきているかもしれません。オブジェクトはそれらが必要とするのよりもより長く、メモリー内のまわりに保たれている可能性があります、それがリークの原因となっているのですが。または、オブジェクトが早まって削除される可能性があります、それがポインタのダングリングの原因となっているのですが。nsISupports における残り2つのメソッド AddRef()Release() は、この問題を処理するよう設計されています。ポインタが出てくるたびに、そのオブジェクトに対して AddRef() が呼び出され、内部カウンタを増やします。 ポインタがリリースされるたびに Release() が呼び出され、同じ内部カウンタを減らします。 カウンタが 0 に到達するとき、残っているオブジェクトへのポインタはなくなり、オブジェクトは安全に自身を削除します。オブジェクトの寿命の制御はオブジェクト自身の中で留まります。XPCOM の "賢い" ポインタ、nsCOMPtr、すなわちこの過程を自動でするのを助けるユーティリティーについての情報はここを見て下さい。

Object の生成

オブジェクトを生成することもまた、XPCOM では間接的な過程です。ちょうどインターフェースがグローバルな唯一の ID 番号 (IID) をもっているのと同じように、XPCOM のクラスはそれら自身の GUID (グローバルな唯一の ID 番号)すなわち CID が割り当てられます。加えて、XPCOM のクラスはまたテキストベースの ID、契約 ID(Contract ID)、と呼ばれるのもしばしば与えられます。これらの ID の一方またはもう一方は、実際にオブジェクトを作っている永続的な XPCOM コンポーネント、コンポーネントマネージャー、についてのメソッドへと通されます。(XPCOM ではモジュールと呼ばれている)クラスの新しいライブラリがシステムへと初めて導入されるとき、それは自身をコンポーネントマネージャーに登録しなければなりません。コンポーネントマネージャーはそれらが存在しているライブラリへ、それらの ID とともにクラスの地図を作っているレジストリを維持しています。

シングルトンオブジェクトによって供給された限られた数の永続的なサービスは、コンポーネントマネージャーの仲間、サービスマネージャーによって作られて、制御されています。コンポーネントマネージャーはそれ自体、そのような永続的なサービスの例です。

要約

XPCOM 内の機能は抽象的なインターフェースによって記述されています。そして、システムの部分間のほとんどのコミュニケーションは、それらのインターフェースの点で起こります。一方で、インターフェースを実装する基礎的なオブジェクトは、それが維持している相互参照レジストリに基づいたコンポーネントマネージャーによって、間接的に作られます。

全てのインターフェースによって共有された1つの機能とは、実行時(ランタイム)に基盤となるオブジェクトに対して他のインタフェースも実装しているかどうかを聞くことができるというものです。理論上では、ある1つのインターフェースは固定されて変更できません。しかし、Mozilla コードベース内でのこのステージでは、FROZEN と宣言されたインターフェースのみがはっきりと変化しないと保証されます。オブジェクトの寿命管理は加えられた、またはリリースされたオブジェクトへポインタの数を見失わない内部カウンタを通じて、オブジェクト自身の中で起こります。クライアントの唯一の責任はカウンタを増減することです。内部カウンタが 0 に達したとき、オブジェクトは自身を削除します。

nsCOMPtr

しかし、正しいタイミングで AddRef()Release() を忘れずに呼び出すのが難しいこともあるかもしれません。 この過程をより簡単に、そしてより信頼できるようにするために、XPCOM は内蔵の "賢い" ポインタ、すなわち nsCOMPtr をもっています。このポインタはあなたのために AddRef()Release() を呼び出すことの面倒をみます。可能な限り nsCOMPtr を使うことはあなたのコードをよりきれいに、そしてより効率よくするでしょう。その賢いポインタについて更なる情報は "完全な nsCOMPtr ユーザーマニュアル" を見て下さい。

Mozilla は実際に非常に多くの内蔵マクロ(慣習から、コード内に全て大文字で書かれています)とか、XPCOM でのコーディングの全過程をより簡単にすることができる nsCOMPtr のようなユーティリティーを提供します。これらの多くは下記のファイルに見つけられます:<tt>nsCom.h</tt>、<tt>nsDebug.h</tt>、<tt>nsError.h</tt>、<tt>nsIServiceManager.h</tt>、<tt>nsISupportsUtils.h</tt>。Mozilla はまたメモリの使用をたどるための他の開発ツールなどのものを提供します。これらについての更なる情報は http://www.mozilla-japan.org/performance/ に見つけられます。

更なる情報

XPCOM 全般についての更なる情報は XPCOM に見つけることができます。XPCOM コンポーネント群を作ることを一通り目を通すには、O'Reilly の Creating Applications with Mozilla の第8章を見て下さい。このトピックに完全に専念した新しい本、 Creating XPCOM Components もあります。COM システムへの基礎にある論理のいくつかのより完全な説明は、Don Box による Essential COM の最初の方の章で見つけることができます。それが特に MSCOM に焦点を置いている一方で、その本はそのようなオブジェクトモデルを使うために核となっている合理性のいくつかについての素晴らしい背景を提供します。

XPIDL

ンターフェースは XPIDL、Cross Platform Interface Definition Language(プラットフォームに依存しないインターフェース定義言語)で書かれた抽象的なクラスです。そして、役立つようにするために、それらのインターフェース内で約束された機能は、ある恒常的なプログラミング言語で実装されなければなりません。これを容易にするのは XPIDL コンパイラの仕事です。ひとたびインターフェースが .idl ファイルに定義されたら、XPIDL コンパイラがそれを処理することができます。

コンパイラは多くの物事を出力することができます。しかし、一般的には出力は2つの重要な部分をもっています:完全な C++ インターフェース実装のためのコメントアウトされたテンプレートを含んだ C++ .h ファイルと、インターフェースを Javascript に利用できるようにさせるための XPConnect とともにはたらくタイプライブラリ情報を含んだ XPT ファイルです。XPIDL(単純な C のような言語)の文法・構文についてと、コンパイラの使用についての更なる情報は XPIDL に見つけることができます。

XPConnect と XPT ファイル

XPConnect は、 Javascript で書かれたコードが、C++ で書かれた XPCOM コンポーネントにアクセスして扱うことを可能にし、またその逆のこともできるようにする XPCOM モジュールです。XPConnect によって、XPCOM インターフェースのどちらの側のコンポーネントも、もう一方の側のオブジェクトがこれらの言語のうちどちらで実装されているかということについて、知ることも気にすることも普通は必要ありません。

あるインターフェースが XPIDL コンパイラを通じて実行されるとき、それは XPT、すなわちタイプライブラリファイルを1つ作ります。XPConnect は、XPCOM インターフェースを横断して C++ のオブジェクトと Javascript のオブジェクトの間に透過的なコミュニケーションを実装するためにこのファイル内の情報を使用するので、たとえあなたがもっぱら C++ で開発しているとしても、それらがあなたのコードとともに生成され、含まれることを確かめるのは重要です。実際には、JS(Javascript)に実装されたブラウザの重要な部分だけではなく、将来的にはあなたが作ったどんなコンポーネントとも互いに影響しあうための JS ベースのコードを誰かが使いたいかもしれません。

Mozilla の出身である XPConnet は C++ と JS の間の相互命令ができることを現在容易にしています。(Python を含んだ)他の言語からのアクセスを可能にするためにそれを広げるためのモジュールは、独立開発の途上です。

文字列クラス

ウェブブラウジングには、概して大量の文字列を扱うことが伴います。Mozilla はそのような扱いを容易にし、それを効率的に素早く描画するための C++ クラス階層を開発してきました。オブジェクト間のやりとり(メッセージ)をより単純でエラーのないようにするために、Mozilla はインターフェース、つまり抽象クラスを使用しています。文字列階層もまた、同様の理由により、一連の抽象的なクラス、 nsAStringnsASingleFragmentStringnsAFlatString によって保証されています。(これらは、ダブルバイト文字列を参照しています。 nsACString などが最上層である、シングルバイト文字列を参照する同様な(クラス)階層もあります。) nsAString は文字の連なりであることだけが保証されます。 nsASingleFragmentString は、文字が単一のバッファに蓄えられているということが保証されます。 nsAFlatString は、文字が、単一で終端が null で示されるバッファに蓄えられているだろうことが保証されます。下層には具体的なクラスがある一方で、一般には、ある特定の状況下において、可能な限り最も抽象的な型を使うことが一番です。例えば、ポインタ(の使用)を介して、連結操作を仮想的に行うことができます。そしてその連結操作は、他の文字列同様に使うことのできる nsAString という結果になります。これにより、別のやり方でなされなければならないであろう、メモリの割り当て及びコピーをせずに済むわけです。更なる情報は "XPCOM string guide Mozilla 文字列クラスガイド" を見て下さい。

XUL/XBL

この最後の Mozilla 技術は、使用するかどうか選択できます。あなたのアプリケーションに、UI(ユーザーインターフェース)をどのように作ると決めるか次第です。 XUL は Mozilla の高度な、柔軟性のある XML UI 言語です。XUL は UI を構築するために、大部分のプラットフォームから独立したウィジェットを、数多く提供します。Netscape と Mozilla は両方ともインターフェースに XUL を使用しています。しかし、全ての組み込み開発者が、XUL を選択しているわけではありません。XBL(eXtensible Binding Language、拡張可能な結びつけの言語)によって、 XUL の XML 要素への挙動を貼付けることができます。XUL についての更なる情報は XUL Reference に、XBL についての更なる情報は XBL - Extensible Binding Language 1.0 に見つけることができます。また、XUL の役立つ良い情報も、XulPlanet日本語版)にたくさんあります。

追加の機能を選択する

これを書いている時点では(02/8/19)、Gecko は部分的にモジュール化された描画エンジンです。基本的なブラウジングよりも高度ないくつかの機能は、いつも Gecko とともに組み込まれます。そして、ある構造上の決定の結果、いくつかの機能についてはいつも Gecko と共に組み込まれるでしょう;現在もいくつかはいつも Gecko とともに組み込まれています。しかし、将来のある時点で、分離可能になるかもしれません;そして、いくつかは現在、完全に選択可能なものとして利用できます。下記の表は、これら追加の機能の現在の状況が書いてあります。

機能 現在の状況 将来の状況
FTP サポート 選択可能  
HTTPS サポート 選択可能  
国際文字サポート 選択可能  
XUL サポート 必須 おそらく選択可能
ネットワークサポート 必須 もしかしたら選択可能
JavaScript サポート 必須 もしかしたら選択可能
CSS サポート 必須 常に必須
DOM サポート 必須 ほぼ必須
XML サポート 必須 ほぼ必須

現時点では、状況は改善しているけれども、レンダリングエンジン Gecko とともに、Mozilla エディタを組み込むことは不確かな問題です。組み込み可能なエディタの状況についての更なる情報は、http://www.mozilla-japan.org/editor/...ing_Guide.html を見て下さい。

Gecko が提供するもの

以下にあげるのは、Gecko を組み込む際に最も一般的に使われるインターフェースのいくつかについての記述です。これは決して利用できるインターフェースを網羅しているリストではありません。このセクションでのインターフェースは、Mozilla によって提供されたクラスにあるものです。Gecko は、組み込み作業者がインターフェースに実装を提供することを期待しているような、そういった一連のインターフェースもあります。それらの例は次のセクションでカバーされています。

初期化と後始末

Gecko の初期化と、終了を提供するための、2つの C++ だけの関数があります。初期化関数(NS_InitEmbedding)は Gecko を使おうとする前に呼び出されなければなりません。それは XPCOM が動き出し、必要ならコンポーネントレジストリを作り、グローバルサービスを開始している、ということを確約します。シャットダウン関数(NS_TermEmbedding)は Gecko 組み込みレイヤーを終了させて、グローバルサービスが解放され、ファイルが閉じられ、XPCOM がシャットダウンしたことを確約します。

nsIWebBrowser

初期化の間にこのインターフェースを使うことで、組み込み作業者が新しい nsWebBrowser インスタンス(典型的なブラウザウィンドウの「クライアントエリア」を表現しているオブジェクト)と、組み込み作業者の chrome を関連させることができ、あらゆるリスナを登録することができます。このインターフェースはまた、コンテント DOM ウィンドウを得るために、そして、そこから DOM の残りのファイルを得るためにランタイムに使われるかもしれません。

XULPlanet nsWebBrowser reference にも同様にこのクラスについての多くの有益な情報があります。

nsIWebBrowserSetup

このインターフェースは、ブラウザウィンドウが開く前に、(画像読み込みを許可するかどうかといったような)基本的な属性を設定するのに使われます。

nsIWebNavigation

nsIWebNavigation インターフェースは、URI をウェブブラウザインスタンスに読み込み、セッション履歴機能 - 「戻る」とか「進む」といったような - へのアクセスを提供するのに使われます。このインターフェースはこれを書いている時点では(06/6/06)、凍結(frozen)されていません。

nsIWebBrowserPersist

nsIWebBrowserPersist インターフェースは、URI をファイルに保存するのを許可します。このインターフェースはこれを書いている時点では(06/6/06)、凍結されていません。

nsIBaseWindow

nsIBaseWindow インターフェースは、一般的なウィンドウと、そのウィンドウ上で実行されるかもしれない基本的な命令(大きさ、位置、ウィンドウタイトルの検索など)を記述します。このインターフェースはこれを書いている時点では(06/6/06)、凍結されていません。

nsISHistory

nsISHistory インターフェースは、セッション履歴情報へのアクセスを提供し、その情報を削除することを許可します。

nsIWebBrowserFind

nsIWebBrowserFind インターフェースは、ブラウザウィンドウ内のテキスト検索のセットアップと実行を制御します。

あなたが提供するもの

以下のものは、Gecko を組み込む際に組み込み作業者によって提供されたより一般的ないくつかのインターフェースについての記述です。これは決して利用できるインターフェースを網羅しているリストではありません。

nsIWebBrowserChrome

nsIWebBrowserChrome インターフェースは、組み込まれた Gecko ウェブブラウザを含んでいる、最重要で、最も外側のウィンドウに対応しています。あなたはそれを、nsIWebBrowser インターフェースを通じて WebBrowser に関連づけることができます。それはウィンドウのセットアップの制御と、ウィンドウが modal かどうかについて提供します。このインターフェースは実装されなければなりません。

nsIEmbeddingSiteWindow

nsIEmbeddingSiteWindow インターフェースは Gecko に、ウィンドウをリサイズしたり、見せたり隠したり、タイトルをセットまたは手に入れるための、ホストへ呼び出すための手段を提供します。このインターフェースは実装されなければなりません。

nsIWebProgressListener

nsIWebProgressListener インターフェースは文書読み込みの進行状況についての情報を提供します。これは、nsIWebBrowser インターフェースを通じて WebBrowser に加えられます。これを書いている時点(02/8/19)では、このインターフェースは凍結(frozen)されていません。

nsISHistoryListener

nsISHistoryListener インターフェースは、セッション履歴での活動について通知を受け取りたい組み込み作業者によって実装されます。履歴リスナは、セッション履歴からページが加えられたり、取り除かれたり、読み込まれるとき通知されます。これは nsIWebBrowser インターフェースを通じて Gecko と関連しています。このインターフェースは実装するかどうかを選択できます。

nsIContextMenuListener

nsIContextMenuListener インターフェースはコンテクストメニューイベント - すなわち、ユーザーのマウスがリンク上で右クリックすることによって生成される - で通知を受け取りたい組み込み作業者によって実装されます。これは、通知が要求されるウィンドウと関連した、ウェブブラウザの chrome オブジェクト上に実装されるべきです。コンテクストメニューイベントが起きたとき、ブラウザが存在しているなら、このインターフェースを呼び出します。このインターフェースは実装するかどうかを選択できます。

nsIPromptService

nsIPromptServices インターフェースは組み込み作業者に Mozilla の標準プロンプト:警告、ダイアログボックス、チェックボックスなど・・・、をオーバーライドするのを許可します。これらの組み込み作業者の詳細なプロンプトを実装するクラスは、Mozilla の標準プロンプトサービスが通常は使う、同じ CID とコントラクト ID(契約 ID)を使っているコンポーネントマネージャーに登録されなければなりません。これを書いている時点(02/8/19)では、このインターフェースは凍結されていません。

共通の組み込み作業

下記のものは、共通の組み込み作業と関連した、非常に端的な実装を示している(MFCEmbed、Windows ベースの Gecko 組み込みサンプルの)一連のコードの一部分です。このサンプルに関連した全てのファイルを見るためには http://lxr.mozilla.org/seamonkey/sou...ests/mfcembed/ へ行って下さい。Linux や Mac OS ベースのサンプルもあります。

Gecko のセットアップ

Gecko の組み込みレイヤーを初期化しなければ、あなたは Gecko を使うことができません。この初期化は、XPCOM が開始されて、必要ならコンポーネントレジストリを作り、グローバルサービスを開始するということを確約します。同様のシャットダウン過程もあります。

組み込みレイヤーはそれに2つのパラメータを渡すことによって、開始されるということに注意して下さい。最初のものは、ファイルシステムのどこに実行可能なファイルが蓄えられているかを指し示しています。(nsnull は working ディレクトリを指し示しています。)2つめのものは、ファイルロケーションオブジェクト "provider" を指し示しています。provider は Gecko に対して、どこにプロファイル、コンポーネントレジストリプリファレンスなどが見つけられるか指定しています。

nsresult rv;
rv = NS_InitEmbedding(nsnull, provider);
if(NS_FAILED(rv))
{
ASSERT(FALSE);
return FALSE;
} 

ブラウザインスタンスを作る

組み込み作業者の用意した BrowserView オブジェクトは、このオブジェクトのメソッド CreateBrowser を呼び出します。それぞれのブラウザオブジェクト(webbrowser)は単一のブラウザウィンドウを表現します。ユーティリティーの命令 do_CreateInstance() とマクロの使用に注意して下さい。

// Mozilla の組み込み可能なブラウザのインスタンスを作る

HRESULT CBrowserView::CreateBrowser() 
{
// Create a web shell  
nsresult rv;
mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv);
if(NS_FAILED(rv))
return rv; 

ひとたび nsWebBrowser オブジェクトが作られたら、そのアプリケーションは nsIWebNavigation インターフェースへのポインタを mWebNav メンバ変数に読み込むために do_QueryInterface を使います。これはウェブページをナビゲーションするのに、後で使われるでしょう。

rv = NS_OK;
mWebNav = do_QueryInterface(mWebBrowser, &rv);
if(NS_FAILED(rv))
return rv; 

次に、組み込み作業者が提供した CBrowserImpl オブジェクトが作られます。Gecko は組み込まれたアプリケーションとコミュニケーションできるようにするために、いくつかのインターフェースを組み込み作業者が実装するよう要求します。あなたが提供するもののセクションを見て下さい。サンプル中では、CBrowserImpl は、それら要求されたインターフェースを実装するオブジェクトです。これは、下記の SetContainerWindow() 呼び出しへと渡されます。

mpBrowserImpl = new CBrowserImpl();
if(mpBrowserImpl == nsnull)
return NS_ERROR_OUT_OF_MEMORY; 

mWebBrowser インターフェースのポインタはその後 CBrowserImpl オブジェクトにその Init() メソッドを通じて渡されます。プラットフォーム特有の BrowserFrameGlue インターフェースへの2つのポインタもまた渡されてきて保存されます。 BrowserFrameGlue ポインタによって CBrowserImpl がステータスバーやプログレスバーなどを更新するためにメソッドを呼び出すことができます。

mpBrowserImpl->Init(mpBrowserFrameGlue, mWebBrowser);
mpBrowserImpl->AddRef(); 

次に組み込み作業者が提供した chrome オブジェクトが webbrowser と関連付けられます。nsCOMPtr の使用に注意して下さい。

mWebBrowser->SetContainerWindow
	(NS_STATIC_CAST(nsIWebBrowserChrome*, mpBrowserImpl)); 
nsCOMPtr<nsIWebBrowserSetup>setup(do_QueryInterface(mWebBrowser));  
if (setup) 
	setup->SetProperty(nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER,PR_TRUE); 

本当のウェブブラウザウィンドウが作られます。

rv = NS_OK;
mBaseWindow = do_QueryInterface(mWebBrowser, &rv);
if(NS_FAILED(rv))
return rv; 

ウインドウを固定する

基本的なロケーション情報が渡されます。

RECT rcLocation;
GetClientRect(&rcLocation);
if(IsRectEmpty(&rcLocation)) 
{
	rcLocation.bottom++;
	rcLocation.top++;
}
rv = mBaseWindow->InitWindow(nsNativeWidget(m_hWnd), 
		nsnull,0, 0, rcLocation.right - rcLocation.left, 
		rcLocation.bottom - rcLocation.top);
rv = mBaseWindow->Create(); 

m_hWnd は上記の呼び出しを通じて InitWindow() へと渡されます。(CBrowserViewCWnd から m_hWnd を継承します。)この m_hWnd は組み込み可能なブラウザによって親ウィンドウとして使われるでしょう。

リスナを加える

BrowserImpl オブジェクトは nsIWebProgressListener として加えられます。これは今、プログレスメッセージを受け取ります。これらの callback はステータスバーまたはプログレスバーを更新するために使われるでしょう。

nsWeakPtr weakling
	(dont_AddRef(NS_GetWeakReference(NS_STATIC_CAST(nsIWebProgressListener*, 
			mpBrowserImpl))));
void mWebBrowser->AddWebBrowserListener(weakling, NS_GET_IID(nsIWebProgressListener)); 

最後に、ウェブブラウザのウィンドウが表示されます。

mBaseWindow->SetVisibility(PR_TRUE);

ナビゲートするためにセッション履歴を使う

上記に保存された nsIWebNavigation へのポインタはセッション履歴を通じて戻ってくるために使われます。

void CBrowserView::OnNavBack() 
{
if(mWebNav)
	mWebNav->GoBack();
} 

付録:Gecko 内のデータフロー

組み込み作業者にとって、Gecko がしていることはどうやってなされているのか厳密に理解する必要はない一方で、Gecko がディスプレイに情報を配置する際に関わる、主要な構造の簡潔な概要は役立つかもしれません。

Image:EmbeddingBasicsa.gif

ネットワークかローカルソースから、HTML データが Gecko へと入ってきます。最初に起こることは Gecko の HTML パーサー(構文解析)を使って解析がされる、ということです。その後、コンテントモデル(Content Model)がこの分析されたデータを巨大なツリー(木構造)へときちんと並べます。このツリーは "ドキュメント(Document)" としても知られていて、その構造は W3C のドキュメントオブジェクトモデル(Document Object Model、DOM)に基づいています。DOM API を使用すると、このコンテントモデル内のデータが操作されることになります。

次に、CSS とフレームコンストラクタ(Frame Constructor)を使って、データはフレーム内に置かれます。ここでのフレームは、HTML のフレームと同じものではなくて、DOM の要素が表示されるであろう、基本的には抽象的なボックスです。この処理ではフレームツリー(Frame Tree)が作られます。それはコンテントモデルのように、データのツリーであるのですが、今度は要素間の論理的関係ではなくて、データを表示するのに必要な根本的な計算に焦点が置かれています。はじめはフレームには大きさがありません。DOM の要素達がフォントや画像サイズのような情報を含めて表示されるとき、どのように見えるべきかを指定している CSS のルールを使ってそれぞれのフレームの実際の大きさが計算されます。例えば、モニター用とプリント用など、同じデータが異なったふうに表示される必要があるかもしれないので、特定のコンテントモデルは、それに関連したフレームツリーを1つよりも多く持っているかもしれません。そのような場合、それぞれ個々のフレームツリーは異なった "表現(presentation)" モードに属しているでしょう。

計算が続けられている間に、リフロー(Reflow)と呼ばれる処理を使って、新しい情報がシステム内に流れてきます。フレームツリー内の情報が変化したとき、フレームツリーのその変化に関わったセクションが、フレームコンストラクタによって "dirty(汚い)" と印付けされます。リフローは繰り返しツリー全体を歩いていき、全てのアイテムが "clean(きれい)" になるまで、遭遇した "dirty" アイテムを処理していきます。フレームツリー内の全てのアイテムはそのコンテントモデル内の一致するアイテムへと戻すポインタを持っています。つまり、要素を hidden(隠し)から visible(見える)にするための DOM API の使用を通じたコンテントモデル内での変化は、フレームツリーでの同様の変化を生み出します。これらの命令全てが純粋なデータの扱いであるということに注目するのは重要です。ディスプレイそれ自体への描画は、この時点ではまだ関わっていません。

次のステージはビューマネージャー(View Manager)です。いくつかの小規模な例外、その例外によってフレームコンストラクタがグラフィックスを読み込むよう処理しなければならない、とともに、ビューマネージャーはネイティブ OS にアクセスする処理の最初の場所です。この時点まで OS のアクセスを遅くすることは、Gecko がより速く、そしてクロスプラットフォームの問題を処理するのをより簡単にするのを手助けします。ビューマネージャーは Gecko がディスプレイ上のどこにデータを描画する必要があるだろうか、理解する場所です。それはシステムにそのエリアは "invalid(不適当)" で再描画される必要のあるということを伝えます。他の低レベルシステムの命令が widget(ウィジェット)サブモジュールを通じて実行されるのに対し、実際の描画は gfx サブモジュールによって管理されています。widget サブモジュールは、プラットフォーム特定のイベント(マウスクリックのような)、ループ処理、システムデフォルト(フォント、カラーなど)にアクセスといったことを扱います。gfx と widget は両方とも、システム特有のものです。

もしあなたが、これらの構造の下にあるコードを見てみたいなら、コンテントモデルのコードは <tt>/mozilla/content</tt> に、フレームコンストラクタ、CSS、リフローのコードは <tt>/mozilla/layout</tt> に、ビューマネージャーのコードは <tt>/mozilla/view</tt> に、DOM API のコードは <tt>/mozilla/dom</tt> に見つけることができます。

 

Original Document Information

ドキュメントのタグと貢献者

タグ: 
 このページの貢献者: teoli, Luna8bit, Mgjbot
 最終更新者: teoli,