この日記はMozillaのプロダクトへの貢献者としての私の成果を中心に、気になったバグやWeb界隈の話題について書いていますが、 断り書きがある場合を除き、いかなる団体のオフィシャルな見解ではありません。あくまでも個人的なものです。 Mozilla Foundation、Mozilla Corporation、及び関連企業の公式情報ではないことに注意してください。

現在、XHTML 1.0 (もどき)から、HTML5なコンテンツに修正中です。古い日記は修正が完了していませんので表示が崩れます。 順次、修正していく予定ですのでしばらくお待ちください。

もずはっく日記(2013年7月)

2013年7月11日

Flash PlayerのIME問題のおさらい
初回投稿日時: 2013年07月11日19時46分48秒
最終更新日時: 2013年07月12日10時56分47秒
カテゴリ: Firefox Flash Windows
SNS: (list)

スラッシュドットのコメントを見ていても、憶測で色んなこと書いてる方が多いです。そのような情報に一人歩きされても困るので、あらためて、解説しようと思います。もし、この内容に間違いがあるなら、twitter等でリプライ頂けば修正します。

まず、基本中の基本ですが、WindowsのIMEというのは、ユーザのプロセス内で動いています(厳密には間違ってると思いますが、そこまで私も詳しくない)。図にすると以下のような感じ。

アプリのプロセス内にIMEが読み込まれている図。

アプリのプロセスが作ったウインドウや、そのIMEのコンテキストに、IMEは自由にアクセスできます。システムにアクセスできるかは、アプリの実行権限に依存します。

伝統的なIMEはこのような感じですが、最近設計されたIMEは、外部プロセスに変換エンジン等を追い出し、プロセス間通信を行いながら動作するのが一般的になっています。これは、現在のプロセス間通信のコストと、メモリ利用効率を考えると、良いアプローチだと思います。

有名どころでは、Google日本語入力と、Baidu IMEが変換エンジンプロセスを別に起動していることが、タスクマネージャでも確認できます。

Google 日本語入力 コンバーターというプロセスが存在しているということを示す、タスクマネージャのスクリーンショット。 BaiduJP IME Engineというプロセスが存在しているということを示す、タスクマネージャのスクリーンショット。

このような場合、通常のアプリでは、以下の図のように、IMEは、ホストアプリと、外部プロセスの両方にアクセスして動作することになります。

アプリプロセス内のIMEが、外部のプロセスと通信している図。

では、ここからは、Firefoxとプラグインの関係について見ていきましょう。

Firefoxは、クラッシュの統計をずっと取っていましたが、Firefox 3.6当時、その原因の大半はプラグインがFirefoxのプロセス内でクラッシュしていることにありました。これに対する解決策として、OOPPという仕組みを用意しました。

OOPPは、firefox.exeの外側に、plugin-container.exeというプラグインのホストプロセスを作り、クラッシュをこのプロセス内に押さえ込むことに成功しました。これを実現するために、plugin-container.exeは、firefox.exeのウインドウ上に、自分でウインドウを生成しフォーカスを持つことができます。このため、IMEは、plugin-container.exe内で動作することになりました。

Plugin-Container内にIMEが読み込まれている図。Firefoxのプロセスが孤立している。

ここで、Adobeは、Flash Player 11.3で、Firefox上で動作する場合にのみ動作する、特殊な保護モードを導入しました

plugin-container.exe内に読み込まれたFlash Playerは、自前の保護されたプロセスを生成し、この保護されたプロセス自身がplugin-container.exeの生成したプラグイン用のウインドウの上に、自前のウインドウを生成し、フォーカスをこのウインドウが持つようになりました。このため、IMEも保護モードで起動されたプロセス内に読み込まれます。

IMEがFlash Playerの生成した、保護モードプロセス内に生成され、プロセス外部とのアクセスが遮断されている図。

ところが、この保護モードで動作するFlash Playerのプロセスは、外部プロセスとの通信は、悪意あるソフトがFlash Player内に侵入しているという前提に基づいているため、全て禁止しています。このため、外部プロセスを利用している、Google日本語入力や、Baidu IMEは、それに依存する機能を全て使えなくなってしまいました。

これが、この問題をAdobe以外が修正できないのか、という理由です。Google日本語入力や、Baidu IMEが設計をイチからやり直す、という解決策も無くはないですが、Adobe製品でしか問題ないことに対してやるような話ではありませんし、個人的には、Adobe側のIMEに対する理解が皆無だった、というところにあると思います。

ちなみに、カナロックがかからないのも、システムへのアクセスが制限されているために発生しているものと推測されます。

このような理由から、技術的には、過剰なセキュリティ対策を行っていると言える、Flash Playerの保護モードを無効化することが最も妥当だと、以前から主張してきました。この問題に悩まされているものの、保護モードの解除方法を知らない方は、解説している記事を参考に、解除された方が良いと思います。

ここまで、一般的なwindowedモードでの動作についての解説でした。では、windowlessモードはどうなのでしょうか?

以前、解説したように、実は、保護モードを利用していても、Google日本語入力や、Baidu IMEは利用可能です。

その理由は、windowlessプラグインの場合、フォーカスは、firefox.exeのウインドウが持っており、IMEもfirefox.exe内のものが利用されているためです。windowlessプラグインは、その結果だけを受けとります。

IMEがfirefox.exe内で動作し、その処理結果だけをプラグインに伝えている図。プラグインからfirefox.exe内のIMEにはアクセスできない。

インラインで入力できなかったり、変換候補ウインドウがキャレット位置に表示されないのは、plugin-container.exeや、Flash Playerの保護モードプロセスから、firefox.exe内で動作しているIMEから未確定文字列を取得できないことや、表示位置をIMEに指定することができないためです。これらの問題は、プラグインとのインターフェースが不十分なために発生しているので、ブラウザ側の問題と言えます。

個人的な見解ですが、AdobeはFlash Playerの開発を今から行うなら、妥当な設計が行えると思います。おそらく、費用対効果から、日本のIMEを見捨てることになっているんじゃないかと思います。

Google Chromeの設計や、windowlessプラグインの設計に倣うなら、Flash Playerの保護モードプロセスは、自分でウインドウを作るべきではありません。フォーカスはplugin-container.exeのウインドウが取得し、IMEもこの内部で動かせば良いのです。そして、簡単に処理したイベントをプロセス間通信で、Flash Playerの保護モードプロセスに伝達すれば良いのです。そして、IMEにアクセスするために、保護モードプロセスから、plugin-container.exe内のFlash Playerに通信手段を用意しておけば、windowlessプラグインで発生するような問題は回避することができます(IMEが悪意あるソフトならどうなんだ、という意見も見かけますが、他のアプリでも利用するIMEの問題に対し、ひとつのアプリでのみ防御策を講じるというのはナンセンスです)。

いずれにしても、ユーザにとれる唯一の対策は、保護モードを解除すること以外にない状況が続くでしょう。

この記事に関して、CorvusSKKというIMEの開発者の方から連絡があり、IMEの外部プロセスと通信する際に使用する、名前付きパイプのセキュリティ設定を変更すれば、Flash Playerの保護モード内からも、通信可能になるという情報がありました。

Adobe側の説明と食い違っていて、驚いている所ですが、実際に動いているそうなので、NyaRuRuさんが、早速、Google日本語入力のオープンソース版である、Mozcで試してみるとおっしゃってます

この話題で、初めて、明るいニュースが出てきました。

関連するかもしれないエントリ

関連するかもしれないエントリを発見できませんでしたが、無いとは限りません。