このノートは、Paul Irishによる記事 “WebKit for Developers” の日本語訳です。
僕ら開発者の多くにとって、WebKit はブラックボックスだ。HTML, CSS, JS, その他のアセットを投げると、WebKit は魔法でもかけたかのように、綺麗な Web ページを返してくれる。しかし、僕の同僚 Ilya Grigorik は本当の WebKit はこうだと言っている。
WebKit はブラックボックスではない。ホワイトボックスなんだ。さらにそれだけではなく、オープンなホワイトボックスなんだ。
じゃあ、これから次のことについて理解していこう。
さて、世の中に数多くの WebKit ブラウザがあふれるようになった。とくに Opera が WebKit に移行したなんて話も新しい。ただ、それぞれの WebKit のどこが共通で、どこが違うのかを知るのはとても難しい。これからする説明で、それが少し分かるようになるだろう。そうなれば、ブラウザの違いについて今まで以上によく分かるし、適切なバグトラッカーに報告できるようにもなる。さらに特定のブラウザに対し、どうやって今まで以上に効果的に開発できるかを理解できるだろう。
今日のブラウザは、いくつかのコンポーネントから成り立っている。
WebKit ベースのブラウザ間で、このうちどれが共通だろう?ほとんどの場合において、最初の2つだけだ。
他のコンポーネントは、個々の WebKit port 側で扱われる。じゃあ、port って何だろう。
WebKit には異なる “port” がある。ここでは Sencha の エンジニアリングディレクターで WebKit ハッカーの Ariya Hidayat に説明してもらおう。
WebKit としてよく紹介されるのが、Mac OS X 上で動作する Apple の WebKit だ(これは最初の、つまりオリジナルな WebKit ライブラリだ)。そこから想像できる通り、この WebKit 上の様々なインターフェースは、Mac OS X 上の異なるネイティブライブラリを利用し実装されている(ほとんどの場合 CoreFoundation が中心だ)。たとえば、色のついたフラットなボタンに角丸を指定したとしよう。WebKit はどこから、そしてどのようにボタンを描画するかを知っている。しかし、最後のボタンの描画作業(ユーザのモニタ上に pixel でボタンを描くこと)は CoreGraphics の仕事になる。
ここで説明されている通り、CG は Mac port 特有の例だ。Mac の Chrome はこの場合 Skia を使う。
時が経ち、WebKit はデスクトップ、モバイル含め異なるプラットフォームに “port”(移植)された。これらは多くの場合 “WebKit port” と呼ばれる。Apple 自身も Windows 版の Safari の開発にあたり WebKit を移植し、Windows 上で動作するようにした。ここでは CoreFoundation ライブラリの Windows 版(限定的な実装)を利用した。
…でも、Windows 版 Safari は終わっちゃったけれど。
それ以外にも、多くの “port” が存在している(一覧をご覧あれ)。Google は Chromium port を開発し運用している。Gtk+ を元にした WebKitGtk というものもある。Nokia(が買収した Trolltech)は WebKit の Qt port を運用しており、とくに QtWebKit module として知られている。
port が独自のフォーカスを持つこともある。Mac port はブラウザと OS の分離にフォーカスし、そこに Obj-C と C++ バインディングを用意することで、レンダラをネイティブアプリに埋め込むことを可能にしている。Chromium のフォーカスは純粋にブラウザだ。QtWebKit はクロスプラットフォームな GUI アプリケーションアーキテクチャの中で、そのランタイム、もしくはレンダリングエンジンを提供するために port を提供している。
まず、すべての WebKit port で共有されている機能をおさらいしよう。
というわけで、とても複雑だ。
Flickr や Github が機能を有効フラグ付きで実装しているように、WebKit でも同じ事をしている。これによって port が WebKit のコンパイルタイム Feature Flag を使い、機能を有効・無効にできるようになっている。機能はランタイム flag として現れることもある。この場合はコマンドラインスイッチ(これは Chromium のもの)や about:flags みたいな設定から有効・無効にできる。
じゃあ、今度こそ WebKit で何が共通なのかまとめてみよう……
すこしぼやけてきたので、共通でないものを挙げてみよう。こちらはそれほどぼやけていない。
ひとつ紹介しよう。2D 描画 では、port ごとにまったく異なるライブラリを使用し、スクリーンへの描画処理を行なっている。
細かいところで言えば、最近実装された機能 ちょっと技術的な感じになってきたから、ちょっと細かいところをつつこうか。いま説明したことも、厳密には正しくない。共有されているものは、実際には WebCore なんだ。WebCore はレイアウト、レンダリング、HTML と SVG の DOM ライブラリで、みんなが “WebKit” と呼んでるものは基本的にこいつだ。では実際の “WebKit” は何かというと、WebCore と port のバインディングレイヤーを指す。まあ、ふつうの会話であればこの違いなんて、ほとんどどうでもいいんだけれど。
図で説明すると分かるかな。
WebKit 中の多くのコンポーネントが交換できるようになっている(灰色のところね)。
たとえば、WebKit の JavaScript エンジン JavaScriptCore。これは WebKit のデフォルトのエンジン(WebKit が KHTML を fork しスタートした際は、KDE の KJS をベースにしていた)。いっぽう、Chromium port では V8 に置き換わっており、さらに固有の DOM バインディングでマップしている。
フォントやテキストの描画はプラットフォームのとても大きな部分だ。WebKit は Fast path, Complex path という2つの text path を持っている。どちらもプラットフォーム固有(ポート側の)サポートを必要とするけれど、Fast path はただどのようにグリフをブリットするかを知るだけでよい(WebKit はそれをプラットフォームのためにキャッシュする)のに対して、Complex path は実際に全文字列をプラットフォームレイヤーに渡して「描画してくれ」と伝える。
じゃあ、すこし広いところ、いくつかの port とサブシステムを見てみよう。次の表は5つの WebKit port についてまとめたものだ。WebCore の多くを共有していても、スタックが多種多様なことが分かるだろう。
* Chrome for iOS についての補足をしよう。分かってると思うけど、こいつは UIWebView を使っている。だから UIWebView が提供するもの、つまり Mobile Safari と同じレンダリングレイヤー、V8 ではなくて JavaScriptCore, そしてシングルプロセスモデルしか利用できない。しかし、ネットワークレイヤー、同期やブックマークのインフラ、Omnibox, メトリクスやクラッシュレポートなど、Chromium 側のコードもかなり利用している。(また、個人的な意見だけど、JavaScript がモバイルでボトルネックになることは非常に稀なので、JIT コンパイラが無いことのインパクトは限りなく小さいだろう。)
大丈夫!WebKit の layoutTest がカバーする範囲はとても広い(最後に見た時点で 28,000 以上)。テストは既存の機能に関するものだけじゃなくて、見つかったリグレッションについても用意されている。新しい、もしくは難解な DOM/CSS/HTML5 系の機能について調べるとき、layoutTest が小さくまとまったすばらしいデモになってることが多いんだ。
さらに、W3C は適合性テストへの取り組みを推し進めようとしている。つまり、異なる WebKit port やすべてのブラウザが同じテストスイートでテストされ、結果として変なバグの少ない、相互運用性が確保された Web になっていくんだ。この取り組みに関わるべく Test The Web Forward に参加したみんな、ありがとう。
Robert Nyman と Rob Hawkes が 触れているけど、Opera の発表で重要なことのひとつに、Opera が Chromium を採用したことがあると思う。つまり、WebGL, Canvas, HTML5 フォーム、2D グラフィックス実装、これらすべてが Chrome と Opera で同じように動作することになる。なぜなら、同じ API で, 同じバックエンド実装だから。Opera が Chromium ベースになるので、君がつくった最新技術のデモもすぐ Chrome と Opera で使えるようになる。
もうひとつ言いたいこと。Chromium を採用するのは すべての Opera ブラウザだ。だから Windows 版 Opera, Mac 版 Opera, Linux 版 Opera, Opera Mobile が Chromium ベースになる。さらにはシンクライアントの Opera Mini も、いまの Presto ベースなサーバサイドレンダリングファームを Chromium ベースに変更するんだ。
WebKit Nightly は Mac port の WebKit で、Safari が使うバイナリの中で動作する(ただ、内部のライブラリがいくつか差し替わってはいる)。だから WebKit Nightly の挙動や搭載している機能は将来の Safari と一緒だ。ざっくりと言えば、WebKit Nightly と Safari の関係は、Chromium と Chrome のそれみたいなものかな。
Chrome Canary も、ここ1, 2日の最新の WebKit ソースを使っている。
ほーらよ、相棒!
標準的な Web ブラウザのコンポーネント
WebKit port とは
代表的な WebKit port
すべての WebKit ブラウザで共通なもの
window
オブジェクトと document
オブジェクトを生成する。
※ ただしそれらのプロパティやコンストラクタは feature flag の有効度合いによって異なる。
-webkit-
接頭辞のみをサポートするが、Apple や他の port は古い -khtml-
, -apple-
もサポートするという違いがある。
WebKit port 間で共通なもの
window
, document
WebKit port 間で共通ではないもの
<video>
& <audio>
要素の挙動(とサポートしているコーデック)
CSS.supports()
は win port と wincairo port 以外で有効にされている。これは、これら2つの port で CSS3 Conditional の機能が有効にされていないからだ。
WebKit はサンドウィッチのようなものだ。しかし Chromium においてはタコスに近い。そう、美味しい Web プラットフォームのタコスなのだ。 Dimitri Glazkov, Chrome WebKit hacker. Champion of Web Components and Shadow DOM
Chrome (OS X)
Safari (OS X)
QtWebKit
Android Browser
Chrome for iOS
レンダリング
Skia
CoreGraphics
QtGui
Android stack/Skia
CoreGraphics
ネットワーク
Chromium network stack
CFNetwork
QtNetwork
Chromium network stack の fork
Chromium stack
フォント
CoreText via Skia
CoreText
Qt 内部のもの
Android stack
CoreText
JavaScript
V8
JavaScriptCore
JSC (V8 は Qt のその他で利用)
V8
JavaScriptCore (JIT 無し) *
わかった。それでどうなるの?
WebKit がそれぞれ違うのがわかって怖いよー
Opera が WebKit に移行したけど、これからどうなるの?
んーと、WebKit Nightly ってなに?
WebKit の中身についてもっと教えてよ!
あわせて読みたい
この記事で WebKit ブラウザの内部について説明でき、またどこからどこまでを WebKit, どこからどこまでが WebKit port なのかを伝えられたら嬉しい。
Reviewed by Peter Beverloo (Chrome), Eric Seidel (WebKit).
I’ll update with any corrections or modifications.
Nokia (through Trolltech, which it acquired) maintains the Qt port of WebKit, popular as its QtWebKit module. It might be valuable to mentioned that Digia acquired the Trolltech/Qt division of Nokia and now maintains QtWebKit. Also, not to be too nit-picker, in your subtitles “Some of the ports of WebKit” I would have said “Some of the Products running on top of specific ports of WebKit” because strictly speaking Safari is not a port, but a “Browser that makes use of the Apple WebKit port on Mac”.True.