- isolate developers working on Chrome from inner workings of content
- make the boundary between content and chrome clear to developers and other embedders
- Embedder API is under src/content/public
- DEPS rules would prevent chrome from reaching to the implementation files
In general, we will follow the design of the WebKit API. This makes it easier for people who're already familiar with it, and also keeps things consistent.
- content/public should contain only interfaces, structs and (rarely) static functions
- An exception is content/public/test. We allow concrete classes that chrome test classes derive from or use in here.
- While we don't allow old-style Chrome IPC _messages.h files in content/public, we do allow .mojom files (see discussion). If a mojom is only used inside content, it should be in content/common. If it's an interface that is implemented or called by content's embedder, then it belongs in content/public/common.
- each interface/struct/enum should be in a separate file
- all code under content should be in the "content" namespace
- interfaces that content implements usually should be pure abstract, because usually there's only one implementation. These should not be implemented outside of content (i.e. content will freely assume that it can cast to its implementation(s)).
- interfaces that embedders implement, especially ones which are used in tests or are observer-style and have many implementations, should have default (empty) implementations
- enum values should start with the name of the type, i.e. PAGE_TRANSITION_LINK in the content::PageTransition enum
- content implementation code should use other implementations directly and not go through the interface (i.e. code in content/renderer should use RenderViewImpl instead of content::RenderView)
- it's acceptable to put implementation files that hold constructors/destructors of interfaces/structs which might have member variables. For structs, this covers initializing member variables. For interfaces (i.e. RenderViewObserver) this might cover things like automatic registration/unregistration. Normally we would put this small code in headers, but because of the clang checks against putting code in headers, we're forced to put it in .cc files (we don't want to make a clang exception for the content/public directory since that would lead to confusion).
- when code in chrome implements an interface from content, usually the convention is to prefix the implementation with "Chrome" (i.e. ChromeContentBrowserClient derives from content::ContentBrowserClient)
- only expose methods in the public API that embedders need. If a method is only used by other code in content, it belongs in foo_impl.h and not foo.h.
- methods in the API should be there because either content is calling out to its embedder, or the embedder is calling to content. There shouldn't be any methods which are used to call from the embedder to the embedder.
- all classes/structs/enums in the public API must be used by embedders and content. i.e. if the chrome layer uses a struct but content doesn't know about it, it doesn't belong in content/public but instead some module that's higher level.
- we avoid single-method delegate interfaces, and in those case we use callbacks.
- don't add the const identifier to interfaces. For interfaces implemented by the embedder, we can't make assumptions about what the embedder needs to implement it. For interfaces implemented by content, the implementation details doesn't have to be exposed.
- Observer interfaces (i.e. WebContentsObserver, RenderFrameObserver, RenderViewObserver) should only have void methods. This is because otherwise the order that observers are registered would matter, and we don't want that. The only exception is OnMessageReceived, which is fine since only one observer class handles each particular IPC, so ordering doesn't make a difference.