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, which correspond to sending Mojo handles |
vardhan
2016/03/08 00:41:24
not sure what you mean by "correspond to sending M
| |
226 enum/const declarations (with respect to both the field declarations and other | 227 (with mostly self-explanatory names): `handle` (any kind of Mojo handle), |
227 enum/const declarations) is not. (But as before, we recommend declaring things | 228 `handle<message_pipe>`, `handle<data_pipe_consumer>`, |
228 before "use".) | 229 `handle<data_pipe_producer>`, and `handle<shared_buffer>`. Like the pointer |
229 | 230 types, these may also be nullable (e.g., `handle?`, `handle<message_pipe>?`, |
230 Here is an example with these elements: | 231 etc.), where "null" indicates that no handle is to be sent (and may be realized, |
231 ```mojom | 232 e.g., as the invalid Mojo handle). |
232 struct Foo { | 233 |
233 const int8 kSomeConstant = 123; | 234 #### Interface types |
234 | 235 |
235 enum MyEnum { | 236 We have already seen *interface* type declarations. In a message (or struct), it |
236 A_VALUE, | 237 is just a message pipe (endpoint) handle. However, it promises that the *peer* |
237 ANOTHER_VALUE | 238 implements the given interface. For example: |
238 }; | 239 ```mojom |
239 | 240 interface MyFirstInterface { |
240 int8 first_field = kSomeConstant; | 241 Foo() => (); |
241 uint32 second_field = 123; | 242 }; |
242 MyEnum etc_etc = A_VALUE; | 243 |
243 float a; // Default value is 0. | 244 interface MySecondInterface { |
244 string? b; // Default value is null. | 245 Bar(MyFirstInterface x); |
245 }; | 246 Baz(MyFirstInterface& y); // Interface request! See below. |
246 ``` | 247 }; |
247 (Note that `kSomeConstant` may be referred to as `Foo.kSomeConstant` and, | 248 ``` |
248 similarly, `MyEnum` as `Foo.MyEnum`. This is required outside of the `Foo` | 249 Here, a receiver of a `Bar` message is promised a message pipe handle on which |
249 declaration.) | 250 it can send (request) messages from `MyFirstInterface` (and then possibly |
250 | 251 receive responses). I.e., on receiving a `Bar` message, it may then send `Foo` |
251 ### Interface declarations | 252 message on `x` (and then receive the response to `Foo`). |
253 | |
254 Like other handle types, instances may be non-nullable or nullable (e.g., | |
255 `MyFirstInterface?`). | |
256 | |
257 #### Interface request types | |
258 | |
259 *Interface request* types are very much like interface types, and also arise | |
260 from interface type declarations. They are annotated by a trailing `&`: e.g., | |
261 `MyFirstInterface&` (or `MyFirstInterface&?` for the nullable version). | |
262 | |
263 In a message (or struct), an interface request is also just a message pipe | |
264 handle. However, it is a promise/"request" that the given message pipe handle | |
265 implement the given interface (in contrast with the peer implementing it). | |
266 | |
267 In the above example, the receiver of `Baz` also gets a message pipe handle. | |
268 However, the receiver is expected to implement `MyFirstInterface` on it (or pass | |
269 it to someone else who will do so). I.e., `Foo` may be *received* on `y` (and | |
270 then the response sent on it). | |
271 | |
272 ## Pipelining | |
273 | |
274 We saw above that Mojom allows both "interfaces" and "interface requests" to be | |
275 sent in messages. Consider the following interface: | |
276 ```mojom | |
277 interface Foo { | |
278 // ... | |
279 }; | |
280 | |
281 interface FooFactory { | |
282 CreateFoo1() => (Foo foo); | |
283 CreateFoo2(Foo& foo_request); | |
284 }; | |
285 ``` | |
286 | |
287 `CreateFoo1` and `CreateFoo2` are functionally very similar: in both cases, the | |
288 sender will (eventually) be able to send `Foo` messages on some message pipe | |
289 handle. However, there are some important differences. | |
290 | |
291 In the case of `CreateFoo1`, the sender is only able to do so upon receiving the | |
292 response to `CreateFoo1`, since the message pipe handle to which `Foo` messages | |
293 can be written is contained in the response message to `CreateFoo1`. | |
294 | |
295 For `CreateFoo2`, the operation is somewhat different. Before sending | |
296 `CreateFoo2`, the sender creates a message pipe. This consists of two message | |
297 pipe handles (for peer endpoints), which we'll call `foo` and `foo_request` (the | |
298 latter of which will be sent in the `CreateFoo2` message). Since message pipes | |
299 are asynchronous and buffered, the sender can start writing `Foo` messages to | |
300 `foo` at any time, possibly even before `CreateFoo2` is sent! I.e., it can use | |
301 `foo` without waiting for a response message. This is referred to as | |
302 *pipelining*. | |
303 | |
304 Pipelining is typically more efficient, since it eliminates eliminating the need | |
305 to wait for a response, and it is often more natural, since receiving the | |
306 response often entails returning to the message loop. Thus this is generally the | |
307 preferred pattern for "factories" as in the above example. | |
308 | |
309 The main caveat is that with pipelining, there is no flow control. The sender of | |
310 `CreateFoo2` has no indication of when `foo` is actually "ready", though even in | |
311 the case of `CreateFoo1` there is no real promise that the `foo` in the response | |
312 is actually "ready". (This is perhaps an indication that flow control should be | |
313 done on `Foo`, e.g., by having its messages have responses.) | |
314 | |
315 Relatedly, with pipelining, there is limited opportunity to send back | |
316 information regarding `foo`. (E.g., the preferred method of signalling error is | |
317 to simply close `foo_request`.) So if additional information is *needed* to make | |
318 use of `foo`, perhaps the pattern of `CreateFoo1` is preferable, e.g.: | |
319 ```mojom | |
320 CreateFoo() => (Foo foo, NeededInfo info); | |
321 ``` | |
322 | |
323 ## Consts | |
252 | 324 |
253 **TODO(vtl)** | 325 **TODO(vtl)** |
254 | 326 |
255 ### Union declarations | 327 ## Annotations |
256 | 328 |
257 **TODO(vtl)** | 329 **TODO(vtl)** |
258 | 330 |
259 ### Enum declarations | 331 ## See also |
260 | 332 |
261 **TODO(vtl)** | 333 **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 |