ChromeのLayered Components: Designをまとめる
Layered Components: Designについて読んでまとめる。
Overview
Chrome for iOSはAppleのiOSにおけるサードパーティブラウザの制限から現状content layerを使っている[1]。この事実からこのプロジェクトのゴールは、chromeレベルやcomponentレベルの機能をiOSで使えるようにすることだ。例えば、
- iOSとその他のプラットフォームでChromium開発者のペインを最小化する
- Chromium開発者にiOSも同様にターゲットとするマルチプラットフォームの機能を開発することを可能にする
最後に、私達は、レイヤードコンポーネント―content-freeとあわせてcontentレイヤーをベースとしたドライバーともう一つのiOSのAPIを使うiOSのためのドライバーを共有したコードを有するコンポーネント―を導入するためにリファクタリングを実施する。
-
content layerが何を指してるんだろう。WebKitのWebCoreのこと? ↩︎
モチベーション
AppleはサードパーティのiOSアプリに対して、JavaScript/レンダリングエンジンとして UIWebView
を使うことと、加えて、シングルプロセスであることも強制している。この事実はChrome for iOSに次のことを意味する:
- V8/Blinkベースでマルチプロセスの既存の
content/
の実装を使えない - UIWebViewのブラックボックス的な性質のため、コンテンツAPIの部分的な代替実装を提供するのがせいぜいだろう
結果として、iOSの chrome- と component- レベルの機能の利用は現状だと、ifdefや、コードの変更、コードの追加を必要とする。この手術を上流で行うことは、保守性と可読性の問題を引き起こすだろう。
ほとんどのChromium開発者がiOSの制限や要件を把握していないという事実は、さらに、他のプラットフォームに加えてiOSをターゲットに機能開発を行おうとしている開発者にとって、難易度を上げる原因となっている。
Layered Components
我々のこの挑戦へのアプローチの要点は、徐々にiOSで使うコード上ではcontent APIへの依存を減らしていくことだ(背景や、他の検討したアプローチと、どのようにして我々がこの方法を選ぶにいたったかは下記を参照)。
このアプローチをどのようなコードベース上にどのような構造にするか決定するにあたって、DEPSの制約を開発者にとってもっとも理解するのを簡単にするのと、最低限のメンテナンス性のペインを導入するというポジションをとった。我々はレイヤードコンポーネントを導入する。これらのコンポーネントは、一つの小さい、既知のソースツリー内(src/components)内で生存する。各そのようなコンポーネントは次のものを構成している:
- すべてのプラットフォームで共有するコードで構成されているcore/ サブディレクトリ。このコードは content/ には依存できない。そして、コンポーネントのcoreモデルロジックを含んでいる。
- iOS専用のAPIに依存し、iOSのコードを共有しているコードを含んでいるios/ サブディレクトリ
- content/に依存でき、すべてのプラットフォームで共有するコードをドライブするコードを含んでいるcontent/ サブディレクトリ。例えば、このサブディレクトリは WebContentsを破棄されたときに共有コードの動作を呼び出す
WebContentsObserver
を含んでいるかもしれない
このアプローチを実現するための我々の計画の技術的な詳細はこちら。そして、提案しているChromiumのコードベースの構造の詳細な説明はこちら。
FAQ
Q: この構造を導入することは影響を受ける機能に余分なレイヤーを発生させることにはならないか?
A: 必然的にそうなる。しかし私達は、(a)保守性のペインを減らすために、追加されるレイヤーを最小限にすること、(b)デカップリングをできるだけ論理的にすること(例えば、モデルコードと、IPCを介してレンダラーとそうっご作用するコードをデカップリングする)を明確な目標としている。私達は、機能のOWNERと協力して合意可能なデザインを開発する予定である。
Q: content API や iOS APIのラッパーAPIは作られるか?
A: 現状では分からない。ゴールはそのようなAPIを避けることだ。ただし、薄いラッパーAPIが複数のコンポーネントの構造をすごく簡素化できるのであれば導入されることもあるだろう。
Q: レイヤー化されたコンポーネントの共有コードが、そのドライバーと話す必要がある場合はどうするのか?
A: 一般的に、レイヤ化されたコンポーネントの共有コードとそのドライバとの間の通信は、双方向になると予想されます。共有コードからドライバへの通信は、共有コードが宣言し、ドライバが定義するクラスを経由して行われます(これがどのように行われるかの正確な方法は、ボイラープレートやコードの重複を最小限に抑えることを目標に、ケースバイケースでアプローチする必要があるでしょう)。
Q: この作業によって、Chromiumのコードベースは全体として保守性が低下するのだろうか?
A: このプロジェクトの主な動機は、アップストリームのコードや機能を最も保守しやすい方法でiOSと共有できるようにする(そしてiOS向けに開発する)ことだが、iOSとは関係なく、他にもいくつかの潜在的なメリットがあると考えている:
- chrome/browser のモノリシックな性質を緩和する。
- 共有されるコードの単体テストをよりシンプルにする。
- 影響を受ける機能の理解しやすさを向上させるリファクタリング。
Q: このプロジェクトの範囲はどのくらいですか?
A: chrome/browserの下にある約80のディレクトリのうち、iOSは約30ある
Q: そのアプローチ<X>の方がいいと思う!
A: ご意見、ご感想をお待ちしております。背景のセクションも読んでね。
Background: iOS and the Content API
iOSのコンテンツ利用に関するいくつかのアプローチを検証してきた:
- iOSは、それが必要とする/サポートできるコンテンツAPIのすべての部分を使用し、既存の本格的な実装(例えば、WebContents)を共有することができないインターフェースの代替の部分的な実装を提供する。[1]
- iOSは、実装を共有できるコンテンツAPIの部分のみを使用し、共有コードにおいてコンテンツAPIの問題のある部分(例えばWebContents)を削除し、使用を許可しないようにChromiumコードベースをリファクタリングする。[2]
- iOSはcontent APIを使用しない(最終的に決定したアプローチ)。[3]
アプローチ1に関する結論は、iOSがcontent APIの部分的な実装しか提供できないという事実が、開発者がAPIに対して開発することをより困難にするというものだった:彼らは常に、(a)彼らが作業している所定のコード部分がiOSで共有されているかどうか、(b)iOSで共有されているコードでcontent APIのどのサブセットを使用しても問題ないかを意識しなければならない。アプローチ2に関する結論は、アプローチ1に関する結論と似ていたが、コードベース全体で多少恣意的に見えるリファクタリングを実行すると、保守性と可読性の問題が発生するという懸念が追加された(このアプローチをターゲットにした初期のCLは、これらの懸念を裏付けている)。