# Extension API Specifications

[TOC]

## Summary
Extension APIs are specified in JSON or IDL files.  These files
describe the API and the functions, events, types, and properties it contains.
This specification is used for multiple purposes, including setting up the
API’s bindings (the JavaScript end points that are exposed to extensions),
generating strong types and conversion for extension API objects, creating the
public documentation, generating JS externs, and registering extension API
functions.

## Applications

### Bindings
The Extension API specifications generate the JSON objects that describe the
extension APIs.  These JSON objects are then used in the creation of the
extension API bindings to set up the functions, events, and properties that are
exposed to the extensions in JavaScript.  For more information, see the
[bindings documentation](/extensions/renderer/bindings.md).

### Type Generation
Extension API implementations use strong types in the browser
process, generated from the arguments passed by the renderer.  Both the type
definitions themselves and the conversion code to generate between the
serialized base::Values and strong types are generated based on the API
specification.  Additionally, we also generate constants for enums and event
names used in extension APIs.

### Documentation
The public documentation hosted at https://developer.chrome.com/extensions is
largely generated from the API specifications.  Everything from the function
descriptions to parameter ordering to exposed types and enums is generated from
the specification.  Because this becomes our public documentation, special care
should be given to ensure that descriptions for events, functions, properties,
and arguments are clear and well-formed.

### JS Externs
JS externs, which are used with
[Closure Compilation](https://developers.google.com/closure/compiler/), are
generated from the API specifications as well.  These are used both internally
within Chrome (e.g., in our settings WebUI code) as well as externally by
developers writing extensions.

## Structure
The API specification consists of four different sections: functions,
events, types, and properties.  Functions describe the API functions exposed to
extensions.  Events describe the different events that extensions can register
listeners for.  Types are used to define object types to use in either
functions or events.  Finally, properties are used to expose certain properties
on the API object itself.

## Compilation
The extension API compilation is triggered as part of the normal
compilation process (e.g., `ninja -C out/debug chrome`).  The schemas are
"compiled" by the JSON Schema Compiler, which is implemented in
[src/tools/json_schema_compiler](/tools/json_schema_compiler).  As part of this
step, both IDL and JSON extension API specifications are converted to the same
object, which can be output as a JSON object.  This API object is then used in
each of the compilation steps (bindings, type generation, documentation, JS
externs, and function registration).

Compilation steps can be selective, since not all APIs need to be included
in all compilation steps. For instance, some APIs are implemented entirely
in the renderer, and thus do not need to have strong types or function
registration generated. See the JSON Schema Compiler for more information.

## File Location
Extension APIs are defined in two main locations:
[src/chrome/common/extensions/api](/chrome/common/extensions/api/) and
[src/extensions/common/api](/extensions/common/api/). These represent
two different layers in the extensions system. The chrome layer is for
concepts that are purely chrome-related, whereas the extensions layer is for
concepts that may apply to other embedders (such as AppShell or others).

If an API does not rely on Chrome-specific concepts (things like profiles and
tabs are examples of Chrome-specific topics), it should go at the /extensions
layer. The default location is the /extensions layer (though this was added
later, and, as a result, many APIs that wouldn't otherwise need to be defined
at the the /chrome layer, are).

## Adding a New File
To add a new API, create a new IDL or JSON file that defines the API and add it
to the appropriate BUILD.gn groups.  Files can be included in different targets
depending on their platform availability (e.g., an API may be only available on
ChromeOS) and whether they need to be included in various compilation steps
(e.g., an API may not need generated function registration).

### Adding to GN Files

The GN targets that you include the file in depend on which
[applications](#applications) it should be used in. Unfortunately, the targets
aren't as standardized as they should be, so you'll have to trace them to their
GN action usage. (We'd like to fix this at some point.)

The GN actions correspond as below:

`generated_json_strings`: This action generates the bundled JSON strings for
APIs, which are used to set up the extension bindings in the renderer.

`function_registration`: This action generates code to automatically register
the extension function implementations with the ExtensionFunctionRegistry.

`generated_types`: This action generates the strong types used in the browser
process and the conversion to and from these types and `base::Value`s.

Most APIs leverage all of these (and are typically called `schema_sources` or
`schema_files` in the .gni files). Others want to omit certain steps; these
are added to other groups in the .gn files.

If in doubt, you probably want to add yours to the "basic" group. Feel free to
reach out to an extensions OWNER with any questions.

## IDL vs JSON
Extension APIs can be specified in either IDL or JSON.  During
compilation, all files are converted to JSON objects.  The benefit to using a
JSON file is that it is more clear what the JSON object output will look like
(since it’s simply the result of parsing the file).  IDL, on the other hand, is
typically much more readable - especially when an API will have many methods or
long descriptions.  However, IDL is not as fully-featured as JSON in terms of
accepted properties on different nodes.

## Promise Based Function Returns
Extension functions can be made to both accept a callback as a final parameter,
or return a promise if the callback is omitted. In IDL schemas this is achieved
by adding the `[supportsPromises]` extended attribute in front of the function
definition. For JSON schemas, instead of specifying the callback as a function
at the end of the parameter list, it is explicitly defined as an asynchronous
return using the `returns_async` key on the function itself.
