Closed9

ChromeのContent APIに関するドキュメントを読む

bokkenbokken

Content API

//content/public はcontent moduleのembedderに公開されているAPIである。

Motivation

  • chrome で作業する開発者を content 内部から隔離する。
  • 開発者やその他のembedder向けにchromecontentに明瞭な境界を作る
bokkenbokken

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. ChromeContentBrowserClientcontent::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. WebContentObserverRenderFrambeObserver)はvoidメソッドのみを持つべきです。これは、そうしないと、オブザーバーが登録される順番が重要になってしまうからだ。唯一の例外はOnMessageReceived()で、これは1つのオブザーバー・クラスだけがそれぞれの特定のIPCを処理するので、順序に違いはないので問題ない。
bokkenbokken
デリゲートパターンの例(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;
  }
};
bokkenbokken

これも実装の詳細なので実際のコードを注意深く読まないと分からなさそう。

bokkenbokken

Dependencies on content

  • 大部分のChromiumコードベースは//content/publicに依存して意味明日。いくつかのそれに依存している特筆すべきディレクトリは//extensionschromeです。//componentsにあるいくつかのディレクトリもそこに依存しており、逆に //components は、//content はいくつかの components に依存しています。
bokkenbokken

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/DEPScontent/public/browser/tts_controller.hです。
このスクラップは4ヶ月前にクローズされました