#FxOS Gecko勉強会 その2 の参加メモ

忘れる前にとっととまとめました。
誤った記述がありましたらツッコミ入れてください。

Moz2D

@makoto_kato さん。

Firefoxとかの話をやっている。

直近のお仕事。

ECMA-402(日付のフォーマットを決めるとか、それを日本とドイツのフォーマットを作るとか、桁区切りの文字とか、ロケール毎の文字列)の実装とか。

Androidのbionicはバグっていて使い物にならないので、libicuを実装している。

プロセス分離のプロジェクト、Electrolysis

OS integrationも。

Geckoの下にgfxというのがあるが、今日はその一般的な話をする。

gfxがなぜ重要か

プラットフォーム間の差異をgfxで吸収している。
Firefoxのデスクトップ版やAndroid版等の差分を吸収するために、このレイヤが非常に重要。

ブラウザベンダの各社とも、ブラウザエンジンが凝っている。
GfxはCairoとMoz2Dを使っている。
Chromium/Blinkはskia。
WebKitはCairo/Core Graphics等。WebKitでは昔はchromium/skiaやQtも使えたが、今は使えない。

PF間で描画周りが違うのは、ここのところが全然違うから。

Core GraphicsはOSXのAPI。
Direct 2DはWindows系。
Open GLはKhronos

CairoはGTK等で使われている2D APIで、様々なバックエンドを持っている。
ソフトウェアレイヤの描画だけでなく、OSのAPI、例えばXのAPIを使うといったことができる。

SkiaはAndroidやChromiumで利用されている2D APIで、オプションとしてOpenGLバックエンドを使うことができる。

Thebes(テーベ)。語源は遺跡の名前。
これはFirefox 3から使っているAPIで、現在も使われている。

Moz2Dは新しい2D APIでGecko 7から採用された。
元々はAzureという名前だった。

リフローをどう軽減させるか。

レイヤー分けして計算量を減らす仕組み。
CSS Transisionを使うと、他の要素に影響が出ないようにできる。
色変換のところにOpen GLやDirect 2Dを使うことでハードウェアの仕組みを使うことができるが、そういうことを行う。

ブラウザで一番重いのはUIのビューなので、それ以外(描画以外)のことはできる限りUIのスレッドでやらないということを行っている。
OMTC(Off Main Thread Composing)。

Geckoのブラウザエンジンの歴史。
Firefox 2ぐらいは、SVGはWindowsだと綺麗に出るがMacだと出ない、ということがあった。
Firefox 3ではThebes(Cairo)を使って、プラットフォームの差異が出ないようにした。
Firefox 4ではCairoのバックエンドを弄って、Direct2Dバックエンドを追加して高速化した。

Gecko 7+ではCanvas用にMoz2d/Azure APIを追加した。
Gecko 15+ではContent用にThebeとAzure(Moz2D)のラッパーを追加した。

Moz2DはMozillaで作った。
ソフトウェアレンダはほとんど持っておらず、ハードウェアアクセラレーションがメイン。

Canvasで(に?)実装した。
なぜCanvasで実装したかというと、全部Cairoを使わないといけないがこれが重かったので、Canvasでは基本的にThebes APIを使わないようにした。

GonkではSkiaGLでラップしている。
Firefox OSを高速化しようとしたら、SkiaGLのところを改良すれば早くなるはず。

GonkのSkiaGLはまだバグがあるので入っていない。(前の文章と噛み合わないので何か聞き逃したっぽい)
THebesラッパ経由でMoz2Dが使われる。

最終的にはThebes APIを消してMoz2Dで書き換えようとしている。

Moz2Dで提供しているのは描画とパスの計算とグラデーション、Glyph Rendering、Filterなど。
Pathは、複雑な図形を書いても今のGPUだとすごく早く描画できるのでそこ。
GlyphもGPUに任してしまった方が早い。

描画はmozilla::gfxにSourceSurfaceというのがあってそこで行う。
Pathの場合はPathBuilderにパスを渡す。
GlyphはScaledFont。フォント管理とフォントの描画パスやパターンを管理する。

moz2Dはバックエンドをいろいろ持っている。
WindowsはDirect 2D。
MacはCoreGraphics/Quartsz。
Skia/Skia GL。
Cairo。
nvpr。これはNVIDIAの2D。

Output Recording。
描画データを吐き出す機能。
「-recordin-output」オプションを指定すると吐き出すことができて、Player2Dで再生できる。今はビルドが通らないが。

Hardware Blacklist。
B2G/Gonkの場合、複数のデバイスで動くシングルバイナリということはないので空。
Windows等の場合はクラッシュデータからブラックリスト行きにするか決める。
Geckoの描画が遅い場合は、ハードウェアがブラックリストに入っている場合がある。

Geckoは何者か Geckoはどこへ行くのか 非同期とか編

OHZEKIさん。@saneyuki_s。
Servo方面の人。
冬コミでRustの薄い本を出す。

ブラウザの処理フロー。

URIを叩いたら、リソースのパース・ロードを始める。
DOMツリーを構築してCSSセレクタのマッチング処理を行う。途中でHTMLが破壊的変更を受けたらそこで止まるが。
次いでレイアウトの計算、描画。
JavaScriptの実行。その途中でDOMが修正されるとDOMの再構築が行われて、その辺の流れがリフロー。

これらが実質1スレッドで行われている。
JavaScriptを実行したときに「特定の要素がどれだけの幅や高さを持っている」というような情報が必要で、次の処理に持っていかないと行けないので事実上シングルスレッド。

他のブラウザは割とこれだけでよかった。
Firefoxのデスクトップは別の哀しみがあって、GeckoがUIを描画している(XUL)。
UIとコンテンツのスレッドが一緒。
FIrefoxが固まるのは、コンテンツがスレッドをロックして、それでUIもロックしている。1箇所詰まると全部詰まる。

Mozila Memesで出た提案。
UIスレッドからいろいろな処理を分離すれば良い。

UIスレッドとコンテンツスレッドを分ける。
さらにComposition。Video、WebGL、Canvas、CSS Animation……。
HTMLパースもFirefox 4あたりでUIスレッドから分かれている。

コンテンツスレッドの分離。
これはFennec、Firefox for Androidのやり方。
Fennecは表がjavaで裏でGeckoのスレッドが動いているが、Javaのところ=UIでスレッドが分かれている。

super-snappyは、e10s(Electrolysis、プロセス自体の分割)が方が復活したので凍結されたが。

e10s。
プロセスを分けるアプローチ。
他のブラウザでは基本的にUIとコンテンツで分けている。
Chromeなどはその典型で、1タブ毎に別スレッドを作っていて親のUIスレッドでまとめている。
Safariも7でChromeと同様のアプローチになった。
Presto(Operaの以前のエンジン)はよくわからない。

Compositionは、描画結果を合成して画面に出力するところ。
合成する対象はコンテンツのレイヤだったりHTML videoの再生部分だったり。

なおWindowsはVistaから似たような仕組み(テクスチャ毎にマッピングしてがっちゃんこする仕組み)がある。

Firefox 4以降はプラグインは丸々別プロセスに分けているので、メインスレッドには影響ない。

Off main thread compositing。
Fennec、B2G、OSXで有効。この辺はOpen GLがまともに動く。
Windowsは先日入ってすぐ消えたが、Nightly版を使っている感じではそれほど不安定ではない。
Linuxは……。

(加藤さん補足)Windowsは、Metro(Windows8のあれ)の方はDirect 2Dが効くので有効になっているはず。

これに合わせて、ユーザに提供するDOM APIを変更しようとしている。

Worker Canvas。今までHTMLのcanvasはWorker上から触れなかったので、Worker上でいくら複雑な計算をしても結局メインスレッドに引きずられていた。
これを変えようと提案しているが、まだ実装したブラウザはない。

Web Animeations APIは、ざっくりいうとCSS AnimationやCSS Transisionなどをまとめようというもの。

Async APIは、返ってくるのに時間がかかるAPIは全部非同期にしようという話。例えばGeolocationなど。

バッテリー監視の為にバックグラウンドタスクについて調べたらなくなってたから作ってみた話のはずだった

藪下さん。@aoi_nagatsuki。

にしむねあさんあたりからデバッグ情報付きのビルドができるといいよね、ということで試してみた。
デバッグビルドしたsoをKEONに入れるとバッテリが非常に減るようになったので、バッテリー監視アプリを作ろうと思った。

Firefox OS 1.2ぐらいからバックグラウンドアプリを作れなくなったと聞いていたが、実際にはAPIは残っていて、パフォーマンスの問題で削られていたようだった。

バックグラウンドアプリの仕組み。

gaia/apps/system/js/background_service.jsの中にBackgroundServiceManagerがいて、systemアプリが起動するときに(
systemアプリの)windowオブジェクトにいくつかのイベントを登録している。
何をやっているのかを確認してみると、アプリをインストールsる時にアプリケーションのオブジェクトが来る。Manifestの中にbackground_pageがあるので、それをごにょごにょしてロードしたりしている。

systemアプリのdocument.body.appendChild(frame);でバックグラウンドアプリが動くようになる。
frameには、アプリのマニフェストのURLやバックグラウンド動作するHTMLのURL等が入っている。

今回はGecko勉強会ということで、イベントリスナを追いかけてみた。

(藪下さんから会場に質問。JavaScriptをグルグル動かしていると一定時間殺されるような動きをしているが、そこら辺詳しい人いない?→いなかった。完。)

addEventListener。
BackgroundServiceManagerがmozbrowseropenwindow等のイベントリスナを追加している。

nsEventListenrManagerがmListenersというリスナの一覧を持っている。

各イベントは誰がどう投げているか。
Mozbrowseropenwindowから掘り下げる。
gecko/dom/browser-element/browserElementParent.cppにDispatchOpenWindowEentがいる。
タブが作られたときなどに呼ばれている。

mozbeowseropenwindow以外のイベントが見つからないのはなぜ?
→(加藤さんコメント)基本的にATOMを使っている(文字を数字に置き換えている=とすると早い)ので、普通に検索しても出てこないのではと思う。

Firefox OS 日本語IME開発状況

@masapさん。
組み込みプログラマ。(主にWi-Fi周り)

元々IMEには興味がなかったが、日本語に問題があると言うことでやってみようと思った。
Google日本語入力を使って日本語入力ができるのかを調査した。
そうしたらFirefox OSのIME周りのバグが多かったので、何とか原状復帰させようと取り組んだ。

Keyboard API。
Firefox OS 1.3から導入されていて、このAPIを使ってIMEを作る。

主なKeyboard API。
seCompositionは変換中の文字列を下線付きで表示。
endCompositionは変換中文字列を確定。
setSelectionRangeは選択範囲を表示。
sendKey。入力された文字を単に送る。

Firefox OS 1.3では、キーボード周りで2つの大きい変更があった。
1つは先ほどのKeyboard APIで、もう一つはサードパーティ製キーボードへの対応。

これはいいと思ったが、実際のところはこれらのせいで日本語入力が取り残された。
1.3で日本語が入力できない。
「あ」と入力すると「あ」は出るが、変換できないしエラーも出ない。

ソースコードを修正してビルドしても直らないのでよくよくMakefileを確認すると、焼き込み前にcheckoutで元に戻すコードが入っていた。

既存バグについてはBugzillaに報告して、Google日本語入力の方に入った。
暫定キーボードを作った。
「さてんるいこ」だけ変換できる。
あとキーボードを変更するためのボタンをキーボード上に置いている。
いらないと思うかも知れないが、これがないとキーボードを変更できない。

Google日本語入力。
Google CGI API for Japanese Input。(
これはGoogle日本語入力をWebから使用できるもので、JSONPで使う。

しかし試してみたらエラーが出て動かない。
確認すると、Firefox OSのCertified/PrivilegedアプリではJSONPが使えなかった。
そこでJSONPの代わりにTCPSocketを使うことにした。

TCPSocketで試したら、今度はひらがなが変換できなかった。
これは、TCPSocketでbinaryType:’string’だと化けるため。
binaryTypeを’arrayBuffer’にして自力で文字に変換することで変換できた。

別の問題。
TCPSocketの初期接続が遅い。初めて変換するときだけ5秒かかる。
WireShark(通信パケットを見るアレ)でフレームを見ると、名前解決に5秒かかっていて、Geckoとかが原因でなくネットワークレベルで遅かった。
DNS Queryをルータに投げても応答がなくて、外のDNS Serverに投げて5秒かかっていた。

なぜローカルのルータにDNS Queryを送信しているかというと、ルータからのDHCP ACKに「自分はDNSサーバ」と入っているから。
ヤマハは「ネットボランチDNS」という独自DNSサーバを持っていて、そのためか。
ルータがそういうACKを返しているので、Firefox OSに罪はない。

ちなみにAndroid 4.0.4で試したら、8.8.8.8(Googleが提供しているDNS)をデフォルトで使っていたので再現しなかった。
Ubuntu 13.04の場合は既知のDNSサーバすべてに同時に問い合わせる仕組みになっているので問題にならなかった。

対処方法はあるか。
ユーザランドからは、gethostbyname()を呼ぶくらいしかできそうにない。
根深そうなのでBugzillaに報告しておいた。

話を戻して日本語キーボードが動かない件。
bugzillaからMLに話が展開されて、その結果「日本語キーボードが動かない」→「動かないからdisableにしている」という斜め上のコメントが来た。

その後IMEを直してくれる人が現れてバグがクローズされたが、確認したらホーム画面の検索では直っていたもののブラウザの検索の方は直っていなかった。
その後修正されたと思ったら、ブラウザ側は直ったがホーム画面の方がバグった。
「あ」「か」「さ」と純に入れると「あ」→「ああか」→「ああかあかさ」のように前に入れた文字までリピートされる。

IMEとしての問題。
変換対象の文字列がハイライトされない。
以前はsendPendingSymbols()という関数があってハイライトを指定することができたが、Keyboard IMEのsetComposition()ではできなくなった。
仕方がないのでsetComposition()とsetSelectionRange()を組み合わせて代用しようとしたら、この2つは同時には使用できないことがわかった。

今のIMEに対して簡単なパッチを作った。
左下に「大小キー」があるが、このボタンは文字に濁点や半濁点を付けるときのも押す。わかりにくいので表示を修正した。
そうしたらボタンを「大小゛゜」にすべきというツッコミが来て、Wnnとかは確かにそういう表示なのだが、「大」は冗長なのでそれは避けたかった。

まとめ。
どうやらGaiaとFirefox OSのUXには日本人がいないということがわかった。
IME周りの協力者を募集。
IME入力について語る人は多いが、手を動かす人がいないので。

(質問)
他の言語のIMEについて調べた?
 →ピンインについて確認してみたが、そもそもピンインがわからなかった。

フリック入力に対応できない?
 →今のところその予定はない。

(加藤さんコメント)
compositionLengthが複数あるのは日本語ぐらい。
ただ予測変換機能の場合は海外でも同じような話になるので、修正されるとしたらそちらの経路か。

(浅井さんとあとお一人のコメント)
商用のIMEを作って足りないものは、ミーティングした上でMozillaの中村さんが実装している。
APIの詳細は把握していないが、必要であれば中村さんに伝えてほしい。
Geckoの方はやっているがGaiaサイドはやっていない。

オムロンが作っているやつは可能な範囲では公開してほしいという話はしているが、ビジネスでやっているのでどこまでかはわからない。(オムロンに限らず各社)

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)