Closed9
ChromeのContent APIに関するドキュメントを読む
ChromeのContent APIに関するドキュメント を読む。
Content API
//content/public
はcontent moduleのembedderに公開されているAPIである。
Motivation
-
chrome
で作業する開発者をcontent
内部から隔離する。 - 開発者やその他のembedder向けに
chrome
とcontent
に明瞭な境界を作る
Design
通常、私達はBlink Public APIの設計に従っています。これはすでにBlink Public APIに親しみのある人たちにとってはわかりやすいでしょう。そしてそれは一貫性をもたらします。
-
//content/public
はインターフェース、enum、structs, static functionのみを含んでいるべきです- 例外としては
//content/public/test
です。私達はchrome testクラスが派生したり、使用する具象クラス (concrete class)をここで許しています
- 例外としては
-
//content/public
ファイルのためのテストは実装ディレクトリの中にあるべきです。(e.g.//content/browser
、//content/renderer
etc...) - 古いスタイルのChrome IPC _messages.hファイルを//content/publicに置くことは許可しませんが、.mojomファイルは許可します(議論を参照)。
- 一般的に、もしinterfaceによってのみ使われるstructやenumがあるなら、それらは同じファイルにあります。しかし、struct や enum が他の場所で使われたり、とても大きいならば、それ専用のファイルに置かれるべきです。
-
//content
以下にあるすべてのコードはcontent
namespace にあるべきです。 - content が実装するインターフェースは通常、純粋な抽象であるべきだ。これらはコンテンツの外部で実装されるべきではない。(つまり、contentは自由にその実装にキャストできると仮定する)。
- embedderが実装するインターフェース、特に、テストや、observer-styleで実装されてたくさんの実装があるものは、default(empty)の実装を持つべきです。
- enum型よりもenumクラスを優先する。enum型の場合、値は型の名前で始まるべきです、例えば、
content::PageTransition
enumのPAGE_TRANSITION_LINK
です。 - contentの実装コードは他の実装を直接使うべきです、インターフェースを通してではなありません(i.e.
//content/renderer
にあるコードは、content::RenderFrame
のかわりにRenderFrameImpl
を使います) - メンバ変数を持つinterfaceやstructのconstructorやdestructorを持つ実装ファイルを配置することは許容されます。structを例にとると、これはメンバ変数の初期化も含みます。interfaceを例に取ると(i.e.
RenderFrameObserver
)、これは自動登録/登録解除のようなものを含むかもしれない。通常はこの小さなコードをヘッダーに置くのですが、clangがヘッダーにコードを置くことをチェックするため、.ccファイルに置かざるを得ません(混乱を招くので、content/publicディレクトリにclangの例外を作りたくないのです)。 -
chrome
にあるコードがcontent
からのインターフェースを実装するとき、慣習としてはたいていChrome
prefixをつけます (i.e.ChromeContentBrowserClient
はcontent::ContentBrowserClient
の派生です)。 - embedderが必要なメソッドのみをpublic APIとして公開する。もし、メソッドが
content
にある他のコードで使われるなら、そのコードはfoo_impl.h
に属するべきで、foo.h
ではない。 - APIにメソッドがあるのは、
content
がembedderが呼ぶか、embedderがcontent
を呼ぶからだ。embedderからembedderを呼ぶために使うどんなメソッドもあるべきではない。 - public APIにあるすべての classes/structs/enums は embedders と
content
から使われるなければいけない。すなわち、もし、chrome
レイヤーが struct をつかうが、 content はそのことを知らないなら、それは//content/public
に属さない、しかしかわりに、いくつかのそのモジュールの高層のモジュールに属する。 - 私達はシングルメソッドのデリゲート・インターフェイスは避け、その場合はコールバックを使う。
-
const
指定はcontent
に実装された シンプルなgetter API に付加できます。const
を embedder によって実装されるインターフェースにつけてはいけません。エンベッダーがそれを実装するために何が必要かを仮定することはできない。 - Observerインターフェース (i.e.
WebContentObserver
、RenderFrambeObserver
)はvoidメソッドのみを持つべきです。これは、そうしないと、オブザーバーが登録される順番が重要になってしまうからだ。唯一の例外はOnMessageReceived()
で、これは1つのオブザーバー・クラスだけがそれぞれの特定のIPCを処理するので、順序に違いはないので問題ない。
デリゲートパターンの例(https://blog.waqqasjabbar.com/delegation-pattern-in-c-5af7496ad268 を参照)
class sender
{
private:
ireceiver &_delegate;
public:
void do_work() {
_delegate.do_actual_work(*this);
}
};
class ireceiver {
public:
virtual void do_actual_work(const sender &) = 0;
};
class receiver : public ireceiver {
void do_actual_work(const sender &sender) override {
std::cout << "Doing actual work for sender: " << sender.id() << std::endl;
}
};
これも実装の詳細なので実際のコードを注意深く読まないと分からなさそう。
Dependencies on content
- 大部分のChromiumコードベースは
//content/public
に依存して意味明日。いくつかのそれに依存している特筆すべきディレクトリは//extensions
とchrome
です。//components
にあるいくつかのディレクトリもそこに依存しており、逆に//components
は、//content
はいくつかの components に依存しています。
content
に依存していないディレクトリは //third_party/blink
と //services
です。
あれ、//third_party/blink
は content
に依存してるんじゃなかったっけ…?
前に読んだドキュメントにはそうあったような?
content
への依存をするようなDEPSの変更を追加したり、レビューしたりするときにいくつかの考慮すべきことは次のとおりだ:
-
content
外のディレクトリは、//content/public
内のコードにのみ依存でき、//content
自体や他のサブディレクトリには依存できない。 - ディレクトリが
content
に依存することがアーキテクチャ的に理にかなっているかどうかを検討してみてください。 - 循環依存は許可されていません。それを確認する妥当な方法は
git gs <directory>
コマンドを//content
ディレクトリで実行することです。現在完全に自動化されたチェックはありません。 - コードが本当に
//content
を必要とするかどうかを把握する。例えば、BrowserThread
が必要なだけであれば、代わりにメインタスクランナーを注入することができます(または、オブジェクトの生成時に静的getterから取得することができます)。 - もしもテストコードが必要なら
//content/public/test
を使う -
//components
サブディレクトリは//content/public
に依存できる、しかし循環依存には注意すること。なぜならcontent
はいくつかのコンポーネントに依存しているからだ。componentsの完全なガイドラインはREADMEにある。 - 例えば、
//component/foo/browser
は、//content/public/browser
しか使えません。modules/components の中には、1つのプロセスでのみ実行され、明示的なディレクトリ名を持たないものがあります。 - DEPSの一般的なヒント: 先祖のDEPSファイルがすでに依存関係を追加している場合、何かが明示的に依存関係を上書きしない限り、子孫のDEPSファイルも依存関係を追加する必要はありません。子孫のディレクトリに依存関係を追加する CL をレビューする場合、その依存関係がビルドの成功に必要であることを確認し、もし必要であれば、何が依存関係を上書きしたのか、そしてなぜ上書きしたのかを判断してください。この例は、
/chrome/browser/DEPS
のcontent/public/browser/tts_controller.h
です。
このスクラップは2024/01/08にクローズされました