OLD | NEW |
1 # Mojom IDL | 1 # Mojom IDL |
2 | 2 |
3 The Mojom IDL (interface definition language) is primarily used to describe | 3 The Mojom IDL (interface definition language) is primarily used to describe |
4 *interfaces* to be used on [message pipes](message_pipes.md). Below, we describe | 4 *interfaces* to be used on [message pipes](message_pipes.md). Below, we give a |
5 practical aspects of the Mojom language. Elsewhere, we describe the [Mojom | 5 brief overview of some practical aspects of the Mojom language (for more |
6 protocol](mojom_protocol.md). (**TODO(vtl)**: Also, serialization format? | 6 details, see the [Mojom language](../mojom_lang/mojom_lang.md). Elsewhere, we |
7 Versioning?) | 7 describe the [Mojom protocol](mojom_protocol.md). (**TODO(vtl)**: Also, |
| 8 serialization format? Versioning?) |
8 | 9 |
9 Text files written in Mojom IDL are given the `.mojom` extension by convention | 10 Text files written in Mojom IDL are given the `.mojom` extension by convention |
10 (and are usually referred to as Mojom/mojom/`.mojom` files). The Mojom bindings | 11 (and are usually referred to as Mojom/mojom/`.mojom` files). Mojom IDL permits |
11 generator (**TODO(vtl)**: link?) may be used to generate code in a variety of | 12 C++-style comments: single-line comments starting with `//` or multi-line |
12 languages (including C++, Dart, and Go) from a Mojom file. Such generated code | 13 comments enclosed by `/* ... */`. |
13 "implements" the things specified in the Mojom file, in a way that's appropriate | 14 |
14 for the particular target language. | 15 The Mojom bindings generator (**TODO(vtl)**: link?) may be used to generate code |
| 16 in a variety of languages (including C++, Dart, and Go) from a Mojom file. Such |
| 17 generated code "implements" the things specified in the Mojom file, in a way |
| 18 that's appropriate for the particular target language. |
| 19 |
| 20 ## Modules and imports |
| 21 |
| 22 A Mojom file begins with an optional *module* declaration, which acts like a C++ |
| 23 namespace declaration (applying to the entire file). It is then followed by zero |
| 24 or more *import* statements, which make the contents of the imported files (and, |
| 25 transitively, their imports) available in the current file. For example: |
| 26 ```mojom |
| 27 module my_module.my_submodule; |
| 28 |
| 29 import "path/to/another.mojom"; |
| 30 import "path/to/yet/a/different.mojom"; |
| 31 ``` |
| 32 |
| 33 ### Name resolution |
| 34 |
| 35 Name resolution is basically C++-like (with `.` instead of `::`): Within |
| 36 `my_module.my_submodule`, an unnested declaration of a name `Foo` declares |
| 37 something with "full" name `my_module.my_submodule.Foo`. A *use* of a name `Foo` |
| 38 could either refer to one of the "full" names: `my_module.my_submodule.Foo`, |
| 39 `my_module.Foo`, or `Foo` (searched in that order). |
| 40 |
| 41 Nested declarations act in the expected way. E.g., if `Foo` is a struct |
| 42 containing an enum declaration of `Bar`, then `Foo.Bar` (or |
| 43 `my_submodule.Foo.Bar`, or `my_module.my_submodule.Foo.Bar`) can be used to |
| 44 refer to that enum outside of `Foo`. |
| 45 |
| 46 ### Names and ordinals |
| 47 |
| 48 Generally, at a binary (as opposed to source) level, names in Mojom are not |
| 49 important (except in that they must not collide). Names may be changed without |
| 50 affecting binary compatibility. |
| 51 |
| 52 Instead, what's important are *ordinals*, which apply to struct fields |
| 53 (including message request/response parameters) and interface messages. Often, |
| 54 these are left implicit, in which case ordinals are assigned consecutively |
| 55 starting from 0. (Obviously, with implicit declaration, the order of declaration |
| 56 of struct fields, etc. is important.) Ordinals may also be assigned explicitly, |
| 57 using the notation `@123` (for example). (This allows struct fields, etc. to be |
| 58 re-ordered in a Mojom file without breaking binary compatibility. |
| 59 |
| 60 Though ordinals are important for evolving Mojom files in a backwards-compatible |
| 61 way, we will not discuss them in this introduction. |
| 62 |
| 63 ### Naming style |
| 64 |
| 65 Though names are not important, various code generators expect names in a |
| 66 certain *style*, in order to transform them into a style more appropriate for a |
| 67 given target language: |
| 68 * `StudlyCaps` (a.k.a. `CapitalizedCamelCase`) for: (struct, interface, union, |
| 69 and enum) type names and message (a.k.a. function or method) names; |
| 70 * `unix_hacker_style` for field names (in structs and unions) and "parameter" |
| 71 names; |
| 72 * `ALL_CAPS_UNIX_HACKER_STYLE` for enum value names; and |
| 73 * `kStudlyCaps` for const names. |
| 74 |
| 75 Following this style is highly recommended (and may be required as a practical |
| 76 matter). |
15 | 77 |
16 ## Interfaces | 78 ## Interfaces |
17 | 79 |
18 A Mojom *interface* is (typically) used to describe communication on a message | 80 A Mojom *interface* is (typically) used to describe communication on a message |
19 pipe. Typically, message pipes are created with a particular interface in mind, | 81 pipe. Typically, message pipes are created with a particular interface in mind, |
20 with one endpoint designated the *client* (which sends *request* messages and | 82 with one endpoint designated the *client* (which sends *request* messages and |
21 receives *response* messages) and the other designed that *server* or *impl* | 83 receives *response* messages) and the other designed that *server* or *impl* |
22 (which receives request messages and sends response messages). | 84 (which receives request messages and sends response messages). |
23 | 85 |
24 For example, take the following Mojom interface declaration: | 86 For example, take the following Mojom interface declaration: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 of serialization. As we saw above, messages are basically just structs, with a | 123 of serialization. As we saw above, messages are basically just structs, with a |
62 small amount of additional metadata. | 124 small amount of additional metadata. |
63 | 125 |
64 Here is a simple example of a struct declaration: | 126 Here is a simple example of a struct declaration: |
65 ```mojom | 127 ```mojom |
66 struct MyStruct { | 128 struct MyStruct { |
67 int32 a; | 129 int32 a; |
68 string b; | 130 string b; |
69 }; | 131 }; |
70 ``` | 132 ``` |
71 We will discuss in greater detail how structs are declared later. | 133 Structs (and interfaces) may also contain enum and const declarations, which |
72 | 134 we will discuss below. |
73 ### Names in Mojom | 135 |
74 | 136 ## Types |
75 Names in Mojom are not important. Except in affecting compatibility at the level | 137 |
76 of source code (when generating bindings), names in a Mojom file may be changed | 138 ### Non-reference (simple and enum) types |
77 arbitrarily without any effect on the "meaning" of the Mojom file (subject to | 139 |
78 basic language requirements, e.g., avoiding collisions with keywords and other | 140 We have seen some simple types above, namely `int32`, `uint32`, and `bool`. A |
79 names). E.g., the following is completely equivalent to the interface discussed | 141 complete list of *simple* types is: |
80 above: | 142 * `bool`: boolean values; |
81 ```mojom | 143 * `int8`, `int16`, `int32`, `int64`: signed 2's-complement integers of the given |
82 interface Something { | 144 size; |
83 One(int32 an_integer, string a_string); | 145 * `uint8`, `uint16`, `uint32`, `uint64`: unsigned integers of the given size; |
84 Two() => (bool a_boolean, uint32 an_unsigned); | 146 and |
85 Three() => (); | 147 * `float`, `double`: single- and double-precision IEEE floating-point numbers. |
86 }; | 148 |
87 ``` | 149 Additionally, there are *enum* types, which are user-defined. Internally, enums |
88 The `Something` interface is compatible at a binary level with `MyInterface`. A | 150 are signed 2's complement 32-bit integers, so their values are restricted to |
89 client using the `Something` interface may communicate with a server | 151 that range. For example: |
90 implementing the `MyInterface` with no issues, and vice versa. | 152 ```mojom |
91 | |
92 The reason for this is that elements (messages, parameters, struct members, | |
93 etc.) are actually identified by *ordinal* value. They may be specified | |
94 explicitly (using `@123` notation; see below). If they are not specified | |
95 explicitly, they are automatically assigned. (The ordinal values for each | |
96 interface/struct/etc. must assign distinct values for each item, in a | |
97 consecutive range starting at 0.) | |
98 | |
99 Explicitly assigning ordinals allows Mojom files to be rearranged "physically" | |
100 without changing their meaning. E.g., perhaps one would write: | |
101 ```mojom | |
102 interface MyInterface { | |
103 Bar@1() => (bool x@0, uint32 y@1); | |
104 Baz@2() => (); | |
105 | |
106 // Please don't use this in new code! | |
107 FooDeprecated@0(int32 a@0, string b@1); | |
108 }; | |
109 ``` | |
110 | |
111 Ordinals also tie into the versioning scheme (**TODO(vtl)**: link?), which | |
112 allows Mojom files to be evolved in a backwards-compatible way. We will not | |
113 discuss this matter further here. | |
114 | |
115 **TODO(vtl)**: Maybe mention exceptions to this in attributes (e.g., | |
116 `ServiceName`). | |
117 | |
118 ## Mojom files | |
119 | |
120 A Mojom file consists of, in order: | |
121 * an optional *module* declaration; | |
122 * zero or more *import* statements (the order of these is not important); and | |
123 * zero or more declarations of *struct*s, *interface*s, *union*s, *enum*s, or | |
124 *const*s (the order of these is not important). | |
125 (These are all described further below.) | |
126 | |
127 Additionally, C/C++-style comments are supported (i.e., single-line comments | |
128 starting with `//` or multi-line comments of the form `/* ... */`). | |
129 | |
130 As stated above, the order of struct/interface/union/enum/const declarations is | |
131 not important. This is required to allow "cyclic" structures to be defined. | |
132 Nonetheless, whenever possible, one should declare things before they are | |
133 "used". For example, the following is valid but not recommended: | |
134 ```mojom | |
135 // NOT recommended. | |
136 | |
137 const MyEnum kMyConst = kMyOtherConst; | |
138 const MyEnum kMyOtherConst = A_VALUE; | |
139 | |
140 enum MyEnum { | 153 enum MyEnum { |
141 A_VALUE, | 154 ONE_VALUE = 1, |
142 ANOTHER_VALUE, | 155 ANOTHER_VALUE = -5, |
143 }; | 156 THIRD_VALUE, // Implicit value of -5 + 1 = -4. |
144 ``` | 157 A_DUPLICATE_VALUE = THIRD_VALUE, |
145 | 158 }; |
146 ### Naming style | 159 ``` |
147 | 160 Such an enum type may be used in a struct. For example: |
148 There is a standard style for naming things: | 161 ```mojom |
149 * `StudlyCaps` (a.k.a. `CapitalizedCamelCase`) for: (struct, interface, union, | 162 struct AStruct { |
150 and enum) type names and message (a.k.a. function or method) names; | 163 MyEnum x; |
151 * `unix_hacker_style` for field names (in structs and unions) and "parameter" | 164 double y; |
152 names; | 165 }; |
153 * `ALL_CAPS_UNIX_HACKER_STYLE` for enum value names; and | 166 ``` |
154 * `kStudlyCaps` for const names. | 167 (As previously mentioned, an enum declaration may be nested inside a struct or |
155 | 168 interface declaration.) |
156 Following this style is highly recommended, since code generators for various | 169 |
157 languages will expect this style, in order to transform the names into a more | 170 Together, the simple and enum types comprise the *non-reference* types. The |
158 language-appropriate style. | 171 remaining types the *reference* types: *pointer* types and *handle* types. |
159 | 172 Unlike the non-reference types, the reference types all have some notion of |
160 ### Module statement | 173 "null". |
161 | 174 |
162 The Mojom *module* statement is just a way of logically grouping Mojom | 175 ### Pointer types |
163 declarations. For example: | 176 |
164 ```mojom | 177 A struct is itself a pointer type, and can be used as a member of another struct |
165 module my_module; | 178 (or as a request/response parameter, for that matter). For example: |
166 ``` | 179 ```mojom |
167 Mojom modules are similar to C++ namespaces (and the standard C++ code generator | |
168 would put generated code into the `my_module` namespace), in that there is no | |
169 implication that the file contains the entirety of the "module" definiton; | |
170 multiple files may have the same module statement. (There is also no requirement | |
171 that the module name have anything to do with the file path containing the Mojom | |
172 file.) | |
173 | |
174 Mojom module names are hierarchical in that they can be composed of multiple | |
175 parts separated by `.`. For example: | |
176 ```mojom | |
177 module my_module.my_submodule; | |
178 | |
179 struct MyStruct { | 180 struct MyStruct { |
180 }; | 181 int32 a; |
181 ``` | 182 string b; |
182 Name look-up is similar to C++: E.g., if the current module is | 183 }; |
183 `my_module.my_submodule` then `MyStruct`, `my_submodule.MyStruct`, and | 184 |
184 `my_module.my_submodule.MyStruct` all refer to the above struct, whereas if the | 185 struct MySecondStruct { |
185 current module is just `my_module` then only the latter two do. | 186 MyStruct x; |
186 | 187 MyStruct? y; |
187 ### Import declarations | 188 }; |
188 | 189 ``` |
189 An *import* declaration makes the declarations from another Mojom file available | 190 Here, `x` is a *non-nullable* (i.e., required) field of `MySecondStruct`, |
190 in the current Mojom file. Moreover, it operates transitively, in the sense that | 191 whereas `y` is *nullable* (i.e., optional). |
191 it also makes the imports of the imported file available, etc. The "argument" to | 192 |
192 the import statement is a path to a file. Tools that work with Mojom files are | 193 A complete list of pointer types is: |
193 typically provided with a search path for importing files (just as a C++ | 194 * structs: structs, as discussed above; |
194 compiler can be provided with an "include path"), for the purposes of resolving | 195 * `string`/`string?`: Unicode strings; |
195 these paths. (**TODO(vtl)**: This always includes the current Mojom file's path, | 196 * `array<Type>`/`array<Type>?`: variable-size arrays (a.k.a. vectors or lists) |
196 right? Is the current path the first path that's searched?) | 197 of type "Type" (which may be any type); |
197 | 198 * `array<Type, n>`/`array<Type, n>?`: fixed-size arrays of type "Type" and size |
198 For example: | 199 "n"; |
199 ```mojom | 200 * `map<KeyType, ValueType>`/`map<KeyType, ValueType>?`: maps (a.k.a. |
200 module my_module; | 201 dictionaries) of key type "KeyType" (which may be any non-reference type or |
201 | 202 `string`) and value type "ValueType" (which may be any type); and |
202 import "path/to/another.mojom"; | 203 * unions: see below. |
203 import "path/to/yet/a/different.mojom"; | 204 |
204 ``` | 205 #### Unions |
205 This makes the contents of the two mentioned Mojom files available, together | 206 |
206 with whatever they import, transitively. (Note that names are resolved in the | 207 *Unions* are "tagged unions". Union declarations look like struct declarations, |
207 way described in the previous section.) | 208 but with different meaning. For example: |
208 | 209 ```mojom |
209 Import cycles are not permitted (so, e.g., it would be an error if | 210 union MyUnion { |
210 `path/to/another.mojom` imported the current Mojom file). However, it is | 211 int32 a; |
211 entirely valid for Mojom files to be imported (transitively) multiple times | 212 int32 b; |
212 (e.g., it is fine for `path/to/another.mojom` to also import | 213 string c; |
213 `path/to/yet/a/different.mojom`). | 214 }; |
214 | 215 ``` |
215 ### Struct declarations | 216 An element of type `MyUnion` must contain either an `int32` (called `a`), an |
216 | 217 `int32` (called `b`), *or* a string called `c`. (Like for structs, `MyUnion z` |
217 A Mojom *struct* declaration consists of a finite sequence of *field | 218 indicates a non-nullable instance, and `MyUnion?` indicates a nullable instance; |
218 declaration*, each of which consists of a *type*, a *name*, and optionally a | 219 in the nullable case, `z` may either be null or it must contain one of `a`, `b`, |
219 *default value* (if applicable for the given type). (If no default value is | 220 or `c`.) |
220 declared, then the default is the default value for the field type, typically 0, | 221 |
221 null, or similar.) | 222 ### Handle types |
222 | 223 |
223 Additionally, a struct may contain enum and const declarations (**TODO(vtl)**: | 224 #### Raw handle types |
224 why not struct/union/interface declarations?). While the order of the field | 225 |
225 declarations (with respect to one another) is important, the ordering of the | 226 There are the "raw" *handle* types corresponding to different [Mojo |
226 enum/const declarations (with respect to both the field declarations and other | 227 handle](handles.md) types, with mostly self-explanatory names: `handle` (any |
227 enum/const declarations) is not. (But as before, we recommend declaring things | 228 kind of Mojo handle), `handle<message_pipe>`, `handle<data_pipe_consumer>`, |
228 before "use".) | 229 `handle<data_pipe_producer>`, and `handle<shared_buffer>`. These are used to |
229 | 230 indicate that a given message or struct contains the indicated type of Mojo |
230 Here is an example with these elements: | 231 handle (recall that messages sent on [Mojo message pipes](message_pipes.md) may |
231 ```mojom | 232 contain handles in addition to simple data). |
232 struct Foo { | 233 |
233 const int8 kSomeConstant = 123; | 234 Like the pointer types, these may also be nullable (e.g., `handle?`, |
234 | 235 `handle<message_pipe>?`, etc.), where "null" indicates that no handle is to be |
235 enum MyEnum { | 236 sent (and may be realized, e.g., as the invalid Mojo handle). |
236 A_VALUE, | 237 |
237 ANOTHER_VALUE | 238 #### Interface types |
238 }; | 239 |
239 | 240 We have already seen *interface* type declarations. In a message (or struct), it |
240 int8 first_field = kSomeConstant; | 241 is just a message pipe (endpoint) handle. However, it promises that the *peer* |
241 uint32 second_field = 123; | 242 implements the given interface. For example: |
242 MyEnum etc_etc = A_VALUE; | 243 ```mojom |
243 float a; // Default value is 0. | 244 interface MyFirstInterface { |
244 string? b; // Default value is null. | 245 Foo() => (); |
245 }; | 246 }; |
246 ``` | 247 |
247 (Note that `kSomeConstant` may be referred to as `Foo.kSomeConstant` and, | 248 interface MySecondInterface { |
248 similarly, `MyEnum` as `Foo.MyEnum`. This is required outside of the `Foo` | 249 Bar(MyFirstInterface x); |
249 declaration.) | 250 Baz(MyFirstInterface& y); // Interface request! See below. |
250 | 251 }; |
251 ### Interface declarations | 252 ``` |
| 253 Here, a receiver of a `Bar` message is promised a message pipe handle on which |
| 254 it can send (request) messages from `MyFirstInterface` (and then possibly |
| 255 receive responses). I.e., on receiving a `Bar` message, it may then send `Foo` |
| 256 message on `x` (and then receive the response to `Foo`). |
| 257 |
| 258 Like other handle types, instances may be non-nullable or nullable (e.g., |
| 259 `MyFirstInterface?`). |
| 260 |
| 261 #### Interface request types |
| 262 |
| 263 *Interface request* types are very much like interface types, and also arise |
| 264 from interface type declarations. They are annotated by a trailing `&`: e.g., |
| 265 `MyFirstInterface&` (or `MyFirstInterface&?` for the nullable version). |
| 266 |
| 267 In a message (or struct), an interface request is also just a message pipe |
| 268 handle. However, it is a promise/"request" that the given message pipe handle |
| 269 implement the given interface (in contrast with the peer implementing it). |
| 270 |
| 271 In the above example, the receiver of `Baz` also gets a message pipe handle. |
| 272 However, the receiver is expected to implement `MyFirstInterface` on it (or pass |
| 273 it to someone else who will do so). I.e., `Foo` may be *received* on `y` (and |
| 274 then the response sent on it). |
| 275 |
| 276 ## Pipelining |
| 277 |
| 278 We saw above that Mojom allows both "interfaces" and "interface requests" to be |
| 279 sent in messages. Consider the following interface: |
| 280 ```mojom |
| 281 interface Foo { |
| 282 // ... |
| 283 }; |
| 284 |
| 285 interface FooFactory { |
| 286 CreateFoo1() => (Foo foo); |
| 287 CreateFoo2(Foo& foo_request); |
| 288 }; |
| 289 ``` |
| 290 |
| 291 `CreateFoo1` and `CreateFoo2` are functionally very similar: in both cases, the |
| 292 sender will (eventually) be able to send `Foo` messages on some message pipe |
| 293 handle. However, there are some important differences. |
| 294 |
| 295 In the case of `CreateFoo1`, the sender is only able to do so upon receiving the |
| 296 response to `CreateFoo1`, since the message pipe handle to which `Foo` messages |
| 297 can be written is contained in the response message to `CreateFoo1`. |
| 298 |
| 299 For `CreateFoo2`, the operation is somewhat different. Before sending |
| 300 `CreateFoo2`, the sender creates a message pipe. This consists of two message |
| 301 pipe handles (for peer endpoints), which we'll call `foo` and `foo_request` (the |
| 302 latter of which will be sent in the `CreateFoo2` message). Since message pipes |
| 303 are asynchronous and buffered, the sender can start writing `Foo` messages to |
| 304 `foo` at any time, possibly even before `CreateFoo2` is sent! I.e., it can use |
| 305 `foo` without waiting for a response message. This is referred to as |
| 306 *pipelining*. |
| 307 |
| 308 Pipelining is typically more efficient, since it eliminates eliminating the need |
| 309 to wait for a response, and it is often more natural, since receiving the |
| 310 response often entails returning to the message loop. Thus this is generally the |
| 311 preferred pattern for "factories" as in the above example. |
| 312 |
| 313 The main caveat is that with pipelining, there is no flow control. The sender of |
| 314 `CreateFoo2` has no indication of when `foo` is actually "ready", though even in |
| 315 the case of `CreateFoo1` there is no real promise that the `foo` in the response |
| 316 is actually "ready". (This is perhaps an indication that flow control should be |
| 317 done on `Foo`, e.g., by having its messages have responses.) |
| 318 |
| 319 Relatedly, with pipelining, there is limited opportunity to send back |
| 320 information regarding `foo`. (E.g., the preferred method of signalling error is |
| 321 to simply close `foo_request`.) So if additional information is *needed* to make |
| 322 use of `foo`, perhaps the pattern of `CreateFoo1` is preferable, e.g.: |
| 323 ```mojom |
| 324 CreateFoo() => (Foo foo, NeededInfo info); |
| 325 ``` |
| 326 |
| 327 ## Consts |
252 | 328 |
253 **TODO(vtl)** | 329 **TODO(vtl)** |
254 | 330 |
255 ### Union declarations | 331 ## Annotations |
256 | 332 |
257 **TODO(vtl)** | 333 **TODO(vtl)** |
258 | 334 |
259 ### Enum declarations | 335 ## See also |
260 | 336 |
261 **TODO(vtl)** | 337 **TODO(vtl)** |
262 | |
263 ### Const declarations | |
264 | |
265 **TODO(vtl)** | |
266 | |
267 **TODO(vtl)**: Write/(re)organize the sections below. | |
268 | |
269 ## Data types | |
270 | |
271 ### Primitive types | |
272 | |
273 #### Standard types | |
274 | |
275 #### Enum types | |
276 | |
277 ### "Pointer" types | |
278 | |
279 #### Nullability | |
280 | |
281 #### Strings | |
282 | |
283 #### Maps | |
284 | |
285 #### Structs | |
286 | |
287 #### Arrays | |
288 | |
289 #### Unions | |
290 | |
291 ### Handle types | |
292 | |
293 #### Raw handle types | |
294 | |
295 #### Interface types | |
296 | |
297 #### Interface request types | |
298 | |
299 ## Annotations | |
300 | |
301 ## Pipelining | |
OLD | NEW |