chrome + NPAPI / nixysa

Google Japan Blog: Google Chrome 拡張(Extensions) を作ってみませんか?に参加しました。事前のアイディアソンでSCRAPBOOK :: Firefox Extensionみたいにページの中身をダウンロードしてローカルに保存してあとで見られるようにするextensionを(HTML5チーム6人で)作る、ということになったのはいいものの、ちょっと調べてみるとファイルをローカルにダウンロードするいい方法がありません。
chrome extensionのAPIにはファイルをダウンロードさせるAPIがありません。gearsのlocal serverを使うと新しいドメインで使用するたびにgearsを使っていいかのダイアログが出るのに加えて同じドメインにある画像しか保存できません(画像はamazonS3だったりするサービスも多くなってきているのでページと同じドメインしかキャッシュできないのは困る)。

nixysa

そういえばextensionでNPAPIのpluginを読み込ませられるからそれで解決できるのでは、と思って何も知らないところから調べ始めたらFirefoxやChromeのPlugin開発に便利なnixysa // CIOを目指しつつの8makiのアレnixysaというので簡単にNPAPI pluginが書けるというのを発見しました。じゃあこれでやってみるかということではじめにHelloWorldWalkThru – nixysa – Hello World Walk-Thruをやりました。環境はWindowsXP SP2+VisualStudio2008です。

scons

どうもこのチュートリアルはLinuxを対象にしているようでWindowsで動かしたい時は書いてありません。でもchromium本体をビルドする時にBuild Instructions (Windows)に従って作ったcygwin環境を使ったらビルドすることができました。ただはじめにsconsがpythonのモジュールplygflagsがないと言ってこけます。これはnixysaをsvnからcheckoutしてきたときにthird_party/の中に入っているのでそれを

./setup.py install

でインストールすれば動くようになります(入っているのに気がつかなくて自分でダウンロードしてきました…)。

std::wstring

sconsが動いてコンパイルが始まると今度はnixysa/static_glue/npapi/common.hでgccがstd::wstringというクラスはないと言い出してこけます。これはcygwinのgccがそういうものだそうでgcc(cygwin)でのstd::wstringの利用方法 -OKWaveに素っ気なく書いてある

typedef basic_string<wchar_t> wstring;
としてみる

という回答以上に詳しいことが書かれているものを見つけられなかったのでcommon.hにそう書いたらコンパイルできるようになりました。なんでcygwinのgccはwstringが使えないんでしょう?

about:plugins

これでsconsを実行するとめでたくhelloworld.dllができあがりました。manifest.jsonpluginsを追加してhelloworld.dllを指定するとchromeでabout:pluginsを開くと、プラグインのリストにhelloworldが入ってるはずなのですが出てきません。なんとかしたいけどそもそもNPAPIがどういう仕組みになっているのかがわかってない状態でnixysaがなんで動かないのかがわかるはずがないのでnixysaはあきらめました。たぶんLinuxだとちゃんと動くんだと思います。

npsimple.dll

ふつうにNPAPIで検索するとFirefox用のコードばかり出てくるので、原理的にはそれでも問題ないはずだけど問題が出た時に何も知らない素人には解決できないからchromeで動くことが分かっているNPAPI pluginのコードを手に入れてそれをいじるという方針に変えて探していたらIssue 13564 – chromium – NPAPI Chrome crash – STRINGZ_TO_NPVARIANT – Project Hosting on Google CodeにNPAPI pluginのひな形のようなものがあるのを見つけました。テスト用についているnpsimple.dllmanifest.jsonで読み込むように指定するとちゃんとabout:pluginsに出てきます(これでnixysaで作ったDLLがちゃんと機能していないのに確信を持ちました)。

コード自体はnixysaで書くのに比べるとたしかに面倒なのですが、nixysaで簡単になる部分はNPAPIからブラウザにオブジェクトを返すとき、読み込む時のメモリ管理だけで、けっきょくC++でjsのオブジェクトを操作するというめんどくささは変わらないので全体の作業量からすればそんなに便利にはならないと感じました。でもnixysaだと公開するメソッドのインターフェイスをIDLで記述できるので圧倒的に見通しがよくなるし、ミスで引数が違っていて落ちる、というようなこともなくなります。NPAPIの仕組み自体はGecko Plugin API Reference – MDCにしっかり書いてあるので読むとよくわかります。ただ、できることは非常に限られていて、ブラウザに特定のURLをリクエストさせてそのbodyをストリームとして読み取ること、与えられたウインドウ矩形を描画すること、OSネイティブのイベントをハンドリングすることぐらいしかできません。デスクトップアプリケーション開発者ならなんでもできて楽しいかんじですが、ウェブ開発者からしたら”ダウンロードしかできない”かんじです。

で、指定したファイルをダウンロードしてきてローカルファイルに保存する、というNPAPI pluginを作ったけど時間がなくてパラレルにリクエストしたりしてもちゃんと動くのかとか実用に堪えるのかのテストは全くできていなかったのであとで泣きを見たりしそうだったのと手動で環境変数を設定しないと動かないインチキ実装なのとで怖いからハッカソンでは使いませんでした。

コード

ku’s npapicache – GitHub


About this entry