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.
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, which are used with Closure Compilation, 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.
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.
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. 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.
Extension APIs are defined in two main locations: src/chrome/common/extensions/api and src/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).
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).
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.