Home | History | Annotate | only in /external/libchrome/mojo/public/js
Up to higher level directory
NameDateSize
base.js22-Oct-20204.2K
bindings.js22-Oct-202017K
BUILD.gn22-Oct-20202K
interface_types.js22-Oct-20202.9K
lib/22-Oct-2020
mojo_bindings_resources.grd22-Oct-2020841
README.md22-Oct-202010.6K

README.md

      1 # Mojo JavaScript Bindings API
      2 This document is a subset of the [Mojo documentation](/mojo/README.md).
      3 
      4 [TOC]
      5 
      6 ## Getting Started
      7 The bindings API is defined in the `mojo` namespace and implemented in
      8 `mojo_bindings.js`, which could be generated by the GN target
      9 `//mojo/public/js:bindings`.
     10 
     11 When a Mojom IDL file is processed by the bindings generator, JavaScript code is
     12 emitted in a `.js` file with the name based on the input `.mojom` file. Suppose
     13 we create the following Mojom file at
     14 `//services/echo/public/interfaces/echo.mojom`:
     15 
     16 ```
     17 module test.echo.mojom;
     18 
     19 interface Echo {
     20   EchoInteger(int32 value) => (int32 result);
     21 };
     22 ```
     23 
     24 And a GN target to generate the bindings in
     25 `//services/echo/public/interfaces/BUILD.gn`:
     26 
     27 ```
     28 import("//mojo/public/tools/bindings/mojom.gni")
     29 
     30 mojom("interfaces") {
     31   sources = [
     32     "echo.mojom",
     33   ]
     34 }
     35 ```
     36 
     37 Bindings are generated by building one of these implicitly generated targets
     38 (where "foo" is the target name):
     39 * `foo_js` JavaScript bindings; used as compile-time dependency.
     40 * `foo_js_data_deps` JavaScript bindings; used as run-time dependency.
     41 
     42 If we then build this target:
     43 ```
     44 ninja -C out/r services/echo/public/interfaces:interfaces_js
     45 ```
     46 
     47 This will produce several generated source files. The one relevant to JavaScript
     48 bindings is:
     49 ```
     50 out/gen/services/echo/public/interfaces/echo.mojom.js
     51 ```
     52 
     53 In order to use the definitions in `echo.mojom`, you will need to include two
     54 files in your html page using `<script>` tags:
     55 * `mojo_bindings.js`
     56   __Note: This file must be included before any `.mojom.js` files.__
     57 * `echo.mojom.js`
     58 
     59 ``` html
     60 <!DOCTYPE html>
     61 <script src="URL/to/mojo_bindings.js"></script>
     62 <script src="URL/to/echo.mojom.js"></script>
     63 <script>
     64 
     65 var echoPtr = new test.echo.mojom.EchoPtr();
     66 var echoRequest = mojo.makeRequest(echoPtr);
     67 // ...
     68 
     69 </script>
     70 ```
     71 
     72 ## Interfaces
     73 Similar to the C++ bindings API, we have:
     74 * `mojo.InterfacePtrInfo` and `mojo.InterfaceRequest` encapsulate two ends of a
     75   message pipe. They represent the client end and service end of an interface
     76   connection, respectively.
     77 * For each Mojom interface `Foo`, there is a generated `FooPtr` class. It owns
     78   an `InterfacePtrInfo`; provides methods to send interface calls using the
     79   message pipe handle from the `InterfacePtrInfo`.
     80 * `mojo.Binding` owns an `InterfaceRequest`. It listens on the message pipe
     81   handle and dispatches incoming messages to a user-defined interface
     82   implementation.
     83 
     84 Let's consider the `echo.mojom` example above. The following shows how to create
     85 an `Echo` interface connection and use it to make a call.
     86 
     87 ``` html
     88 <!DOCTYPE html>
     89 <script src="URL/to/mojo_bindings.js"></script>
     90 <script src="URL/to/echo.mojom.js"></script>
     91 <script>
     92 
     93 function EchoImpl() {}
     94 EchoImpl.prototype.echoInteger = function(value) {
     95   return Promise.resolve({result: value});
     96 };
     97 
     98 var echoServicePtr = new test.echo.mojom.EchoPtr();
     99 var echoServiceRequest = mojo.makeRequest(echoServicePtr);
    100 var echoServiceBinding = new mojo.Binding(test.echo.mojom.Echo,
    101                                           new EchoImpl(),
    102                                           echoServiceRequest);
    103 echoServicePtr.echoInteger({value: 123}).then(function(response) {
    104   console.log('The result is ' + response.value);
    105 });
    106 
    107 </script>
    108 ```
    109 
    110 ### Interface Pointers and Requests
    111 In the example above, `test.echo.mojom.EchoPtr` is an interface pointer class.
    112 `EchoPtr` represents the client end of an interface connection. For method
    113 `EchoInteger` in the `Echo` Mojom interface, there is a corresponding
    114 `echoInteger` method defined in `EchoPtr`. (Please note that the format of the
    115 generated method name is `camelCaseWithLowerInitial`.)
    116 
    117 There are some control methods shared by all interface pointer classes. For
    118 example, binding/extracting `InterfacePtrInfo`, setting connection error
    119 handler, querying version information, etc. In order to avoid name collision,
    120 they are defined in `mojo.InterfacePtrController` and exposed as the `ptr` field
    121 of every interface pointer class.
    122 
    123 In the example above, `echoServiceRequest` is an `InterfaceRequest` instance. It
    124 represents the service end of an interface connection.
    125 
    126 `mojo.makeRequest` creates a message pipe; populates the output argument (which
    127 could be an `InterfacePtrInfo` or an interface pointer) with one end of the
    128 pipe; returns the other end wrapped in an `InterfaceRequest` instance.
    129 
    130 ### Binding an InterfaceRequest
    131 A `mojo.Binding` bridges an implementation of an interface and a message pipe
    132 endpoint, dispatching incoming messages to the implementation.
    133 
    134 In the example above, `echoServiceBinding` listens for incoming `EchoInteger`
    135 method calls on the messsage pipe, and dispatches those calls to the `EchoImpl`
    136 instance.
    137 
    138 ### Receiving Responses
    139 Some Mojom interface methods expect a response, such as `EchoInteger`. The
    140 corresponding JavaScript method returns a Promise. This Promise is resolved when
    141 the service side sends back a response. It is rejected if the interface is
    142 disconnected.
    143 
    144 ### Connection Errors
    145 If a pipe is disconnected, both endpoints will be able to observe the connection
    146 error (unless the disconnection is caused by closing/destroying an endpoint, in
    147 which case that endpoint won't get such a notification). If there are remaining
    148 incoming messages for an endpoint on disconnection, the connection error won't
    149 be triggered until the messages are drained.
    150 
    151 Pipe disconnecition may be caused by:
    152 * Mojo system-level causes: process terminated, resource exhausted, etc.
    153 * The bindings close the pipe due to a validation error when processing a
    154   received message.
    155 * The peer endpoint is closed. For example, the remote side is a bound interface
    156   pointer and it is destroyed.
    157 
    158 Regardless of the underlying cause, when a connection error is encountered on
    159 a binding endpoint, that endpoint's **connection error handler** (if set) is
    160 invoked. This handler may only be invoked *once* as long as the endpoint is
    161 bound to the same pipe. Typically clients and implementations use this handler
    162 to do some kind of cleanup or recovery.
    163 
    164 ``` js
    165 // Assume echoServicePtr is already bound.
    166 echoServicePtr.ptr.setConnectionErrorHandler(function() {
    167   DoImportantCleanUp();
    168 });
    169 
    170 // Assume echoServiceBinding is already bound:
    171 echoServiceBinding.setConnectionErrorHandler(function() {
    172   DoImportantCleanUpToo();
    173 });
    174 ```
    175 
    176 **Note:** Closing one end of a pipe will eventually trigger a connection error
    177 on the other end. However it's ordered with respect to any other event (*e.g.*
    178 writing a message) on the pipe. Therefore, it is safe to make an `echoInteger`
    179 call on `echoServicePtr` and reset it immediately (which results in
    180 disconnection), `echoServiceBinding` will receive the `echoInteger` call before
    181 it observes the connection error.
    182 
    183 ## Associated Interfaces
    184 An associated interface connection doesn't have its own underlying message pipe.
    185 It is associated with an existing message pipe (i.e., interface connection).
    186 
    187 Similar to the non-associated interface case, we have:
    188 * `mojo.AssociatedInterfacePtrInfo` and `mojo.AssociatedInterfaceRequest`
    189   encapsulate a *route ID*, representing a logical connection over a message
    190   pipe.
    191 * For each Mojom interface `Foo`, there is a generated `FooAssociatedPtr` class.
    192   It owns an `AssociatedInterfacePtrInfo`. It is the client side of an
    193   interface.
    194 * `mojo.AssociatedBinding` owns an `AssociatedInterfaceRequest`. It listens on
    195   the connection and dispatches incoming messages to a user-defined interface
    196   implementation.
    197 
    198 See [this document](https://www.chromium.org/developers/design-documents/mojo/associated-interfaces)
    199 for more details.
    200 
    201 ## Automatic and Manual Dependency Loading
    202 By default, generated `.mojom.js` files automatically load Mojom dependencies.
    203 For example, if `foo.mojom` imports `bar.mojom`, loading `foo.mojom.js` will
    204 insert a `<script>` tag to load `bar.mojom.js`, if it hasn't been loaded.
    205 
    206 The URL of `bar.mojom.js` is determined by:
    207 * the path of `bar.mojom` relative to the position of `foo.mojom` at build time;
    208 * the URL of `foo.mojom.js`.
    209 
    210 For exmple, if at build time the two Mojom files are located at:
    211 ```
    212 a/b/c/foo.mojom
    213 a/b/d/bar.mojom
    214 ```
    215 
    216 The URL of `foo.mojom.js` is:
    217 ```
    218 http://example.org/scripts/b/c/foo.mojom.js
    219 ```
    220 
    221 Then the URL of `bar.mojom.js` is supposed to be:
    222 ```
    223 http://example.org/scripts/b/d/bar.mojom.js
    224 ```
    225 
    226 If you would like `bar.mojom.js` to live at a different location, you need to
    227 set `mojo.config.autoLoadMojomDeps` to `false` before loading `foo.mojom.js`,
    228 and manually load `bar.mojom.js` yourself. Similarly, you need to turn off this
    229 option if you merge `bar.mojom.js` and `foo.mojom.js` into a single file.
    230 
    231 ``` html
    232 <!-- Automatic dependency loading -->
    233 <script src="http://example.org/scripts/mojo_bindings.js"></script>
    234 <script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
    235 
    236 
    237 <!-- Manual dependency loading -->
    238 <script src="http://example.org/scripts/mojo_bindings.js"></script>
    239 <script>
    240   mojo.config.autoLoadMojomDeps = false;
    241 </script>
    242 <script src="http://example.org/scripts/b/d/bar.mojom.js"></script>
    243 <script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
    244 ```
    245 
    246 ### Performance Tip: Avoid Loading the Same .mojom.js File Multiple Times
    247 If `mojo.config.autoLoadMojomDeps` is set to `true` (which is the default
    248 value), you might accidentally load the same `.mojom.js` file multiple times if
    249 you are not careful. Although it doesn't cause fatal errors, it hurts
    250 performance and therefore should be avoided.
    251 
    252 ``` html
    253 <!-- Assume that mojo.config.autoLoadMojomDeps is set to true: -->
    254 
    255 <!-- No duplicate loading; recommended. -->
    256 <script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
    257 
    258 <!-- No duplicate loading, although unnecessary. -->
    259 <script src="http://example.org/scripts/b/d/bar.mojom.js"></script>
    260 <script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
    261 
    262 <!-- Load bar.mojom.js twice; should be avoided. -->
    263 <!-- when foo.mojom.js is loaded, it sees that bar.mojom.js is not yet loaded,
    264      so it inserts another <script> tag for bar.mojom.js. -->
    265 <script src="http://example.org/scripts/b/c/foo.mojom.js"></script>
    266 <script src="http://example.org/scripts/b/d/bar.mojom.js"></script>
    267 ```
    268 
    269 If a `.mojom.js` file is loaded for a second time, a warnings will be showed
    270 using `console.warn()` to bring it to developers' attention.
    271 
    272 ## Name Formatting
    273 As a general rule, Mojom definitions follow the C++ formatting style. To make
    274 the generated JavaScript bindings conforms to our JavaScript style guide, the
    275 code generator does the following conversions:
    276 
    277 | In Mojom             | In generated .mojom.js |
    278 |----------------------|------------------------|
    279 | MethodLikeThis       | methodLikeThis
    280 | parameter_like_this  | parameterLikeThis
    281 | field_like_this      | fieldLikeThis
    282 | name_space.like_this | nameSpace.likeThis
    283