# Writing a New Extension API
[TOC]
## Overview
This document describes the procedure and general advice for writing the
implementation of a new Extension API.
## Before Writing (Much) Code
Before you invest significant time and energy into writing a new Extension API,
be sure to go through the API proposal process. This is important, as we may
not accept each proposal for a new Extension API, and many require tweaks or
changes. The proposal process is designed to reach consensus on both the
general usefulness and appropriateness of an API, as well as the high-level
shape it will take.
The proposal process is documented [here](/extensions/docs/new_api_proposal.md).
## Implementation Concepts
Extension APIs are defined by their schema files. Access to these APIs is
controlled entries in the features files. APIs are generally implemented
through a combination of extension functions and events (and, occasionally,
properties). APIs are exposed in JavaScript to the extension through extension
bindings.
### Schemas
An extension schema defines the API, including the functions, events, and
properties on the API.
Read more about schemas [here](/chrome/common/extensions/api/schemas.md).
### Features
Extension feature files control access to different APIs, and can restrict APIs
(or specific methods) to different types of extensions, Chromium release
channels, or even to specific extension IDs, as well as specify required
permissions.
Read more about the features files
[here](/chrome/common/extensions/api/_features.md).
### API Functions
Extension functions are called by the extension in order to perform some action
in the Chromium browser. For instance, the `chrome.tabs.create()` API function
is called by an extension to create a tab, and is implemented in C++ by the
`TabsCreateFunction`, and instance of the `ExtensionFunction` class. Generally,
each API function will map to an instance of the `ExtensionFunction` class.
Read more about extension functions [here](/extensions/docs/api_functions.md).
### API Events
Events are dispatched by Chrome to inform the extension of an occurrence. For
instance, the `chrome.tabs.onCreated()` event is dispatched when a new tab is
created.
Read more about extension events [here](/extensions/docs/events.md).
### API Properties
Properties on the API are exposed as JavaScript properties on the API object
itself. These are generally rare. Constants defined in the API (such as
`chrome.tabs.TAB_ID_NONE`) are exposed automatically through the bindings layer.
More complex objects (such as the `StorageArea` defined in `chrome.storage` for
`chrome.storage.local`, `chrome.storage.sync`, and `chrome.storage.managed`)
need to be defined in the API, and are constructed by the bindings layer.
### Extension Bindings
The bindings system is responsible for creating the JavaScript entry points
that extensions use to invoke extension APIs, according to the definitions in
the schema and the features files. **Most APIs should not need any special code
in extension API bindings, and custom bindings are generally discouraged.**
Custom bindings are only required if an API has behavior that is unique enough
to not be built into the general extension API system.
Read more about extension bindings [here](/extensions/renderer/bindings.md).
## Implementation Process
What is the best way to approach writing a new API implementation?
### Development
#### Include a new OWNERS file
The proposal process requires a team to sign on for continued ownership and
stewardship of an API. Any extension API that is not being designed and
implemented by the core extensions team (and some that are) should have a
separate OWNERS file.
#### Include //extensions OWNERS on CLs
Even though each API should have its own dedicated OWNERS, it's good practice
to include an OWNER from [//extensions/OWNERS](/extensions/OWNERS) to review the
interaction with the core extensions system. We can offer guidance on the use
of the different core concepts of API implementation, and ensure that the new
code is following best practices.
#### Start enabled on "trunk" or "canary"
During the development process, the extension API should start restricted to
"trunk" or "canary" in the features files (ideally "trunk", which means it is
only accessible when building from source; "canary" should only be used if it
is necessary to have external testers for the verification of the API). Things
tend to change during development, and we don't want an API to reach stable
channel before it's ready or when it is likely to experience churn.
### Writing Code
Now, it's time to actually write the code to implement the API!
#### Approaches
As a general practice in Chromium, it's good to develop CLs that represent a
full logical unit, complete with tests. This does not have to mean it has to
be entirely complete - it may not even be reachable in production code.
However, it should be clear to reviewers what the functionality is, and that it
is tested and works as intended.
This applies to writing new APIs, as well. APIs should frequently be written
piecemeal, in multiple CLs, with each CL having a logical unit of tested code.
For example, a CL may include:
* An entry in the API schema (for instance, a new function or event)
* The implementation of the new capability (the implementation of that function
or dispatching that event appropriately)
* Tests for the capability (a unit test, API test, or both)
In this case, the logical unit is the new function or event, complete with tests.
For exceptionally large or complex APIs, even this may be too large of a first
step, and smaller CLs may be required before even creating the API entry (for
instance, a new API function may require changes elsewhere in Chromium to
enable a new behavior).
This approach makes it easy for reviewers to review the CL in a reasonable
period of time, and keeps development of the API moving.
#### Anti-Approaches
The below are discouraged.
**The All-in-One CL:**
In most cases, please do not try and fit an entire API implementation into a
single CL. This typically results in a large, unwieldy CL that is difficult to
review. Review times generally increase superlinearly (i.e., faster than
linearly) with the number of lines added - a 200 line CL is usually more than
5x faster to review than a 1,000 line CL.
**The Stubbed-Out CL:**
A common anti-approach is to add an API stub as the first CL, where that stub
adds the entirety of the API surface and empty extension function
implementations for each API function.
First, this makes it impossible to evaluate the correctness of the API
implementation and usage of extension system concepts. Adding a new API
method, intentionally, requires special review from API reviewers (who are
familiar with the best practices and any common pitfalls). If a stub is used,
this review is no longer useful.
Additionally, APIs may need to be slightly tweaked as a result of different
implementation details. While most of these should be ironed out in the
proposal process, some may still come up during the implementation review.
Bundling the declaration with the implementation allows us to catch any changes
that need to happen in the API surface during the primary review.
#### Code Concepts
TODO(devlin): Incorporate the below into this article.
This [article](https://www.chromium.org/developers/design-documents/extensions/proposed-changes/creating-new-apis)
describes a number of different code concepts, and can be useful for some of
the high-level approaches. Note that some of this is outdated.
### Launching
#### Add and Verify Documentation
Much of the documentation for extension APIs is auto-generated from the schema
files. This includes method signatures and descriptions and type descriptions.
If you don't require any additional documentation, the only required step is to
add a new template article in
`chrome/common/extensions/docs/templates/public/extensions`. If you need
additional documentation, you can also add an article in
`chrome/common/extensions/docs/templates/intros`.
To verify the documentation is correctly included and visible, run the preview
mode of the documentation server by running
`chrome/common/extensions/docs/server2/preview.py` and visiting
`localhost:8000/extensions/<apiName>`.
#### Adjust Features Files
Once an API has been fully implemented, tested, and is, in fact, stable, the
features file restriction can be lifted. Depending on the complexity of the
API, it may also need periods of restriction in "dev" and/or "beta".