blob: 2556133c00fdc061bcdcadcb66780f1856e52a63 [file] [log] [blame] [view]
Matt Falkenhagenad915cb2019-09-22 13:49:161# Content API
2
Matt Falkenhagen973af9d2019-10-03 00:35:383`//content/public` is the API exposed to embedders of the [content
4module](/content/README.md).
5
Matt Falkenhagenad915cb2019-09-22 13:49:166## Motivation
7- isolate developers working on Chrome from inner workings of content
8- make the boundary between content and chrome clear to developers and other
Matt Falkenhagen973af9d2019-10-03 00:35:389 embedders
Matt Falkenhagenad915cb2019-09-22 13:49:1610
11## Design
Matt Falkenhagen973af9d2019-10-03 00:35:3812In general, we follow the design of the [Blink Public
13API](/third_party/blink/public/README.md). This makes it easier for people
14who're already familiar with it, and also keeps things consistent.
Matt Falkenhagenad915cb2019-09-22 13:49:1615
Matt Falkenhagen973af9d2019-10-03 00:35:3816- `//content/public` should contain only interfaces, enums, structs and (rarely)
17 static functions.
18 - An exception is `//content/public/test`. We allow concrete classes that
19 chrome test classes derive from or use in here.
John Abd-El-Malek59eacd672021-03-26 07:26:1620- Tests for files in `//content/public` should be inside implementation directories,
21e.g. `//content/browser`, `//content/renderer` etc...
Matt Falkenhagenad915cb2019-09-22 13:49:1622- While we don't allow old-style Chrome IPC `_messages.h` files in
Matt Falkenhagen973af9d2019-10-03 00:35:3823 `//content/public`, we do allow `.mojom` files (see
Matt Falkenhagenad915cb2019-09-22 13:49:1624 [discussion](https://groups.google.com/a/chromium.org/forum/#!searchin/chromium-mojo/cross-module/chromium-mojo/ZR2YlRV7Uxs/Ce-h_AaWCgAJ)).
Matt Falkenhagen973af9d2019-10-03 00:35:3825 If a mojom is only used inside content, it should be in
26 `//content/common`. If it's an interface that is implemented or called by
27 content's embedder, then it belongs in `//content/public/common`.
28- In general, if there is a struct or enum which is only used by an interface,
29 they are put in the same file, but when the struct/enum is used in other
30 places or if it's pretty big, then it should be in its own file.
31- All code under `//content` should be in the `"content"` namespace.
32- Interfaces that content implements usually should be pure abstract, because
Matt Falkenhagenad915cb2019-09-22 13:49:1633 usually there's only one implementation. These should not be implemented
Matt Falkenhagen973af9d2019-10-03 00:35:3834 outside of content. (i.e., content will freely assume that it can cast to
35 its implementation(s)).
36- Interfaces that embedders implement, especially ones which are used in tests
Matt Falkenhagenad915cb2019-09-22 13:49:1637 or are observer-style and have many implementations, should have default
Matt Falkenhagen973af9d2019-10-03 00:35:3838 (empty) implementations.
39- Prefer enum classes over enum types. For enum types, the value should start
40 with the name of the type, i.e., `PAGE_TRANSITION_LINK` in the
41 `content::PageTransition` enum.
42- content implementation code should use other implementations directly and
43 not go through the interface (i.e., code in `//content/renderer` should use
44 `RenderViewImpl` instead of `content::RenderView`).
45- It's acceptable to put implementation files that hold constructors/destructors
Matt Falkenhagenad915cb2019-09-22 13:49:1646 of interfaces/structs which might have member variables. For structs, this
47 covers initializing member variables. For interfaces (i.e.
48 `RenderViewObserver`) this might cover things like automatic
49 registration/unregistration. Normally we would put this small code in headers,
50 but because of the clang checks against putting code in headers, we're forced
51 to put it in .cc files (we don't want to make a clang exception for the
52 `content/public` directory since that would lead to confusion).
Matt Falkenhagen973af9d2019-10-03 00:35:3853- When code in chrome implements an interface from content, usually the
Matt Falkenhagenad915cb2019-09-22 13:49:1654 convention is to prefix the implementation with "Chrome" (i.e.
Matt Falkenhagen973af9d2019-10-03 00:35:3855 `ChromeContentBrowserClient` derives from `content::ContentBrowserClient`).
56- Only expose methods in the public API that embedders need. If a method is only
57 used by other code in content, it belongs in `foo_impl.h` and not `foo.h`.
58- Methods in the API should be there because either content is calling out to
Matt Falkenhagenad915cb2019-09-22 13:49:1659 its embedder, or the embedder is calling to content. There shouldn't be any
60 methods which are used to call from the embedder to the embedder.
Matt Falkenhagen973af9d2019-10-03 00:35:3861- All classes/structs/enums in the public API must be used by embedders and
Matt Falkenhagenad915cb2019-09-22 13:49:1662 content. i.e. if the chrome layer uses a struct but content doesn't know about
Matt Falkenhagen973af9d2019-10-03 00:35:3863 it, it doesn't belong in `//content/public` but instead some module that's
64 higher level.
65- We avoid single-method delegate interfaces, and in those case we use
Matt Falkenhagenad915cb2019-09-22 13:49:1666 callbacks.
Dave Tapuska74bcc372021-05-19 19:36:0467- The `const` identifier can be added to simple getter APIs implemented by
68 content. Don't add `const` to interfaces implemented by the embedder, where
69 we can't make assumptions about what the embedder needs to implement it.
Matt Falkenhagen973af9d2019-10-03 00:35:3870- Observer interfaces (i.e. `WebContentsObserver`, `RenderFrameObserver`,
71 `RenderViewObserver`) should only have void methods. This is because otherwise
Matt Falkenhagenad915cb2019-09-22 13:49:1672 the order that observers are registered would matter, and we don't want that.
Matt Falkenhagen973af9d2019-10-03 00:35:3873 The only exception is `OnMessageReceived()`, which is fine since only one
74 observer class handles each particular IPC, so ordering doesn't make a
75 difference.
Matt Falkenhagenbe5e2312021-09-08 22:09:1876
77## Dependencies on content
78
79Large parts of the Chromium codebase depend on `//content/public`. Some notable
80directories that depend on it are (parts of) `//extensions`, `//chrome`,
81and `//weblayer`. Some directories in `//components` also depend on it, while
82conversely `//content` depends on some components.
83
84Directories that do not depend on content include `//third_party/blink` and
85`//services`.
86
87When adding and reviewing DEPS changes that take a dependency on
88content, some things to consider are:
89
90- Directories outside content can only depend on code inside
91 `//content/public` and not `//content` itself or other subdirectories.
92- Try to consider whether it makes architectural sense for the directory to
93 depend on content.
94- Circular dependencies are not allowed. One reasonable way to check this is
95 `git gs <directory>` inside `//content`. There is no complete automated check
96 at this time.
97- Figure out if code really needs `//content`. For example, if it just needs
98 `BrowserThread`, you could instead inject the main task runner (or they can
99 grab it from the static getter on creation of their object).
100- Use `//content/public/test` if only test code is needed.
101- `//components` subdirectories *can* depend on `//content/public`, but be
102 careful of circular dependencies because content depends on some components.
103 Full guidelines for components are in the [README](/components/README.md).
104- Confirm the code is running in the correct process: e.g.,
105 `//component/foo/browser` can only use `//content/public/browser`. Some
106 modules/components run only in one process and don't have the explicit
107 directory name.
108- General DEPS tip: If an ancestor DEPS file already adds a dependency, the
109 descendent DEPS file does not need to add the dependency also, unless
110 something explicitly overrode the dependency. When reviewing a CL that adds a
111 dependency in a descendent directory, confirm that it is required for the
112 build to succeed, and if so determine what overrode the dependency and why. An
113 example of this is `content/public/browser/tts_controller.h` in
114 [/chrome/browser/DEPS](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/DEPS;l=485;drc=a2b0d55a9ccd93c898835c2462a86698603ad40d).