2013年10月25日金曜日

wpf : GeckoFxを試す

GeckoFxをWPFで使ってみました。 GeckoFxはフォームの方で使うライブラリですが、フォームコントロールのホストでWPFのWindowにのせることができました。 とりあえず動いたのでメモ。

環境や使ったライブラリはこちら。

  • OS : Windows7 home 64bit
  • 開発環境 : Microsoft Visual Studio Express 2012 for Windows Desktop
  • .NET Framework 4.5 x86
  • GeckoFx-Windows-22.0-0.6
  • xulrunner-22.0.en-US.win32

まずはライブラリを用意します。

XULRunnerはruntimesを選びましょう。 GeckoFxとXULRunnerのバージョンは同じでなければなりません。 当然ながらXULRunnerの方が先にバージョンが上がります。 セキュリティ的なことを考えるとGeckoFxでブラウザを作るのは得策ではないですね。 ちょっと重いけど、ローカルのツールとか通信の種類を制限したネットツールとかのレンダリングエンジンとして使うのがいいかな?

GeckoFxは適当なフォルダに解凍しておきましょう。 これはVisual Studioが参照するライブラリなのでプロジェクト内にある必要はありません。 実行に必要なファイルはビルド時にexeファイルと同じ場所にコピーされます。

Visual Studioを起動して適当なWPFプロジェクトを作成します。 今回はWpfGeckoFxTestという名前にしました。 64bit環境の場合は構成マネージャでx86を追加。 一度ビルドしてDebug/Releaseフォルダを作りましょう。 それぞれのフォルダにXULRunnerを解凍してフォルダごと入れておきます。 解凍のさいにフォルダが2重にならないように注意。 今回は「~\Debug\xulrunner\」の中にdllが並ぶようにしました。

さっき解凍したGeckoFxを参照設定で追加します。 追加するのはGeckofx-Core.dllとGeckofx-Winforms.dllの2つです。 フォームコントロールのホストをするのでアセンブリ一覧からWindowsFormsIntegrationとSystem.Windows.Formsも追加。

App.xaml.csでGeckoFxのプロファイルフォルダの設定とXPCOMの初期化をします。 アプリケーション終了時にはXPCOMのシャットダウンも必要になりますが、そちらはタイミングの関係でMainWindowを閉じるときにした方がいいようです。

App.xamlでStartupUriを消してStartupを追加。

App.xaml.csでMainWindowを表示する前にプロファイルフォルダを設定し、Gecko.Xpcom.Initializeをします。

あたりまえのことですが、順番注意。 プロファイルフォルダを設定してから初期化です。

何も設定しないとデフォルトのフォルダ(windows7の場合はC:\Users\ユーザ名\AppData\Local\Geckofx\DefaultProfile\)にGeckoFxのプロファイルができてしまいます。 そのままだと全てのGeckoFxのツールで同じ設定を使うことになってしまうので、アプリケーションの先頭でGecko.Xpcom.ProfileDirectoryにプロファイルのフォルダを設定します。

Gecko.Xpcom.Initializeの引数はXULRunnerへのフルパスです。 ツールを配布することも考えるならexeファイルからの相対フォルダにあった方がいいでしょう。 GeckoFxとXULRunnerのバージョンは同じでなければならないので、重複する可能性があってもアプリケーション毎にXULRunnerを用意するのが現実的かと。

(2013/10/26ちょっと修正、設定のセーブロードは自動かと思ってたけど自分で書かなければならないらしい。) Gecko.Xpcom.Initializeの後はGeckoPreferences.Loadで設定を読み込みます。 初回起動時の場合はGeckoの初期設定です。 このサンプルではプロファイルフォルダの有無で初回起動か判断しています。 Gecko.GeckoPreferences.User["項目"] = 値; のようにして設定します。 設定内容はFireFoxのabout:configと同じです。 FireFox独自の項目でGecko自体には無い項目がけっこうあるので注意。 設定が終わったらGeckoPreferences.Saveで保存します。

続いてMainWindowの処理です。 MSDNのチュートリアルを参考にGeckoWebBrowserをMainWindowにのせます。

MainWindow.xamlでLoadedイベントを追加。 ClosedイベントはXPCOMのシャットダウンで使います。 Gridに適当な名前を付けて、

MainWindow.xaml.csのLoadedイベントで実際にGeckoWebBrowserを追加、ClosedイベントでXPCOMのシャットダウンをします。

このサンプルはGeckoFxが動くかどうか確認するだけなので「戻る」「進む」ボタンやアドレスバーなどは付けてません。 アプリケーションの用途に合わせて追加しましょう。 最初の方で書いた通り、セキュリティ的なことを考えるとGeckoFxでブラウジングするべきではありません。 ここでは試しにwikipediaを表示してますが、変なサイトを見に行かないように注意。

サンプルコードではabout:configへのナビゲートがコメントアウトされています。 このコードを有効にしたらFireFoxのabout:configのようにユーザが設定を変更できます。

ClosedイベントでXPCOMのシャットダウンをしているけど、これはApplicationのExitイベントでシャットダウンすると例外で怒られてしまうためです。 タイミング的にこれが正しいのかは不明。 公式FAQによると、フォームではApplicationのApplicationExitイベントでシャットダウンするものらしいんですけどね。 XPCOMのシャットダウンはWindowsで試す分には無くても(表面上?)問題ないんですよね。 LinuxのMonoで動かす場合はシャットダウンしないとフリーズするんだそうです。

ホントはそっちの方でも動作確認しないとダメなのか。 ええと、Monoは.NET Framework 2.0相当でしたっけ? 面倒だなぁ。

まぁ、機会があったらやります。

アプリケーションが完成したらReleaseフォルダのexeファイル、Geckofx-Core.dll、Geckofx-Winforms.dll、XULRunnerフォルダとその他の必要なファイルを実行環境のフォルダにコピーしましょう。

配布する場合はライセンスには注意です。 GeckoFxはMPL(Mozilla Public License)、XULRunnerはMPL、GPL、LGPLのトリプルライセンスだそうです。 ソースコードの配布は必須。 敷居は高めですね。

あと、Readmeやヘルプなどでユーザーにプロファイルの位置を知らせる必要があります。 このサンプルの通りにやるなら、C:\Users\ユーザ名\AppData\Roaming\アプリケーション名\ がそれに当たります。