summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/docs/basics.rst
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /toolkit/components/extensions/docs/basics.rst
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/extensions/docs/basics.rst')
-rw-r--r--toolkit/components/extensions/docs/basics.rst275
1 files changed, 275 insertions, 0 deletions
diff --git a/toolkit/components/extensions/docs/basics.rst b/toolkit/components/extensions/docs/basics.rst
new file mode 100644
index 0000000000..35d61561e2
--- /dev/null
+++ b/toolkit/components/extensions/docs/basics.rst
@@ -0,0 +1,275 @@
+.. _basics:
+
+API Implementation Basics
+=========================
+This page describes some of the pieces involved when creating
+WebExtensions APIs. Detailed documentation about how these pieces work
+together to build specific features is in the next section.
+
+The API Schema
+--------------
+As described previously, a WebExtension runs in a sandboxed environment
+but the implementation of a WebExtensions API runs with full chrome
+privileges. API implementations do not directly interact with
+extensions' Javascript environments, that is handled by the WebExtensions
+framework. Each API includes a schema that describes all the functions,
+events, and other properties that the API might inject into an
+extension's Javascript environment.
+Among other things, the schema specifies the namespace into which
+an API should be injected, what permissions (if any) are required to
+use it, and in which contexts (e.g., extension pages, content scripts, etc)
+it should be available. The WebExtensions framework reads this schema
+and takes care of injecting the right objects into each extension
+Javascript environment.
+
+API schemas are written in JSON and are based on
+`JSON Schema <http://json-schema.org/>`_ with some extensions to describe
+API functions and events.
+The next section describes the format of the schema in detail.
+
+The ExtensionAPI class
+----------------------
+Every WebExtensions API is represented by an instance of the Javascript
+`ExtensionAPI <reference.html#extensionapi-class>`_ class.
+An instance of its API class is created every time an extension that has
+access to the API is enabled. Instances of this class contain the
+implementations of functions and events that are exposed to extensions,
+and they also contain code for handling manifest keys as well as other
+part of the extension lifecycle (e.g., updates, uninstalls, etc.)
+The details of this class are covered in a subsequent section, for now the
+important point is that this class contains all the actual code that
+backs a particular WebExtensions API.
+
+Built-in versus Experimental APIs
+---------------------------------
+A WebExtensions API can be built directly into the browser or it can be
+contained in a special type of extension called a privileged extension
+that defines a WebExtensions Experiment (i.e. experimental APIs).
+The API schema and the ExtensionAPI class are written in the same way
+regardless of how the API will be delivered, the rest of this section
+explains how to package a new API using these methods.
+
+Adding a built-in API
+---------------------
+Built-in WebExtensions APIs are loaded lazily. That is, the schema and
+accompanying code are not actually loaded and interpreted until an
+extension that uses the API is activated.
+To actually register the API with the WebExtensions framework, an entry
+must be added to the list of WebExtensions modules in one of the following
+files:
+
+- ``toolkit/components/extensions/ext-toolkit.json``
+- ``browser/components/extensions/ext-browser.json``
+- ``mobile/android/components/extensions/ext-android.json``
+
+Here is a sample fragment for a new API:
+
+.. code-block:: js
+
+ "myapi": {
+ "schema": "chrome://extensions/content/schemas/myapi.json",
+ "url": "chrome://extensions/content/ext-myapi.js",
+ "paths": [
+ ["myapi"],
+ ["anothernamespace", "subproperty"]
+ ],
+ "scopes": ["addon_parent"],
+ "permissions": ["myapi"],
+ "manifest": ["myapi_key"],
+ "events": ["update", "uninstall"]
+ }
+
+The ``schema`` and ``url`` properties are simply URLs for the API schema
+and the code implementing the API. The ``chrome:`` URLs in the example above
+are typically created by adding entries to ``jar.mn`` in the mozilla-central
+directory where the API implementation is kept. The standard locations for
+API implementations are:
+
+- ``toolkit/components/extensions``: This is where APIs that work in both
+ the desktop and mobile versions of Firefox (as well as potentially any
+ other applications built on Gecko) should go
+- ``browser/components/extensions``: APIs that are only supported on
+ Firefox for the desktop.
+- ``mobile/android/components/extensions``: APIs that are only supported
+ on Firefox for Android.
+
+Within the appropriate extensions directory, the convention is that the
+API schema is in a file called ``schemas/name.json`` (where *name* is
+the name of the API, typically the same as its namespace if it has
+Javascript visible features). The code for the ExtensionAPI class is put
+in a file called ``ext-name.js``. If the API has code that runs in a
+child process, that is conventionally put in a file called ``ext-c-name.js``.
+
+The remaining properties specify when an API should be loaded.
+The ``paths``, ``scopes``, and ``permissions`` properties together
+cause an API to be loaded when Javascript code in an extension references
+something beneath the ``browser`` global object that is part of the API.
+The ``paths`` property is an array of paths where each individual path is
+also an array of property names. In the example above, the sample API will
+be loaded if an extension references either ``browser.myapi`` or
+``browser.anothernamespace.subproperty``.
+
+A reference to a property beneath ``browser`` only causes the API to be
+loaded if it occurs within a scope listed in the ``scopes`` property.
+A scope corresponds to the combination of a Javascript environment
+(e.g., extension pages, content scripts, etc) and the process in which the
+API code should run (which is either the main/parent process, or a
+content/child process).
+Valid ``scopes`` are:
+
+- ``"addon_parent"``, ``"addon_child``: Extension pages
+
+- ``"content_parent"``, ``"content_child``: Content scripts
+
+- ``"devtools_parent"``, ``"devtools_child"``: Devtools pages
+
+The distinction between the ``_parent`` and ``_child`` scopes will be
+explained in further detail in following sections.
+
+A reference to a property only causes the API to be loaded if the
+extension referencing the property also has all the permissions listed
+in the ``permissions`` property.
+
+A WebExtensions API that is controlled by a manifest key can also be loaded
+when an extension that includes the relevant manifest key is activated.
+This is specified by the ``manifest`` property, which lists any manifest keys
+that should cause the API to be loaded.
+
+Finally, APIs can be loaded based on other events in the WebExtension
+lifecycle. These are listed in the ``events`` property and described in
+more detail in :ref:`lifecycle`.
+
+Adding Experimental APIs in Privileged Extensions
+-------------------------------------------------
+
+A new API may also be implemented within a privileged extension. An API
+implemented this way is called a WebExtensions Experiment (or simply an
+Experimental API). Experiments can be useful when actively developing a
+new API, as they do not require building Firefox locally. These extensions
+may be installed temporarily via ``about:debugging`` or, on browser that
+support it (current Nightly and Developer Edition), by setting the preference
+``xpinstall.signatures.required`` to ``false``. You may also set the
+preference ``extensions.experiments.enabled`` to ``true`` to install the
+addon normally and test across restart.
+
+.. note::
+ Out-of-tree privileged extensions cannot be signed by addons.mozilla.org.
+ A different pipeline is used to sign them with a privileged certificate.
+ You'll find more information in the `xpi-manifest repository on GitHub <https://github.com/mozilla-extensions/xpi-manifest>`_.
+
+Experimental APIs have a few limitations compared with built-in APIs:
+
+- Experimental APIs can (currently) only be exposed to extension pages,
+ not to devtools pages or to content scripts.
+- Experimental APIs cannot handle manifest keys (since the extension manifest
+ needs to be parsed and validated before experimental APIs are loaded).
+- Experimental APIs cannot use the static ``"update"`` and ``"uninstall"``
+ lifecycle events (since in general those may occur when an affected
+ extension is not active or installed).
+
+Experimental APIs are declared in the ``experiment_apis`` property in a
+WebExtension's ``manifest.json`` file. For example:
+
+.. code-block:: js
+
+ {
+ "manifest_version": 2,
+ "name": "Extension containing an experimental API",
+ "experiment_apis": {
+ "apiname": {
+ "schema": "schema.json",
+ "parent": {
+ "scopes": ["addon_parent"],
+ "paths": [["myapi"]],
+ "script": "implementation.js"
+ },
+
+ "child": {
+ "scopes": ["addon_child"],
+ "paths": [["myapi"]],
+ "script": "child-implementation.js"
+ }
+ }
+ }
+ }
+
+This is essentially the same information required for built-in APIs,
+just organized differently. The ``schema`` property is a relative path
+to a file inside the extension containing the API schema. The actual
+implementation details for the parent process and for child processes
+are defined in the ``parent`` and ``child`` properties of the API
+definition respectively. Inside these sections, the ``scope`` and ``paths``
+properties have the same meaning as those properties in the definition
+of a built-in API (though see the note above about limitations; the
+only currently valid values for ``scope`` are ``"addon_parent"`` and
+``"addon_child"``). The ``script`` property is a relative path to a file
+inside the extension containing the implementation of the API.
+
+The extension that includes an experiment defined in this way automatically
+gets access to the experimental API. An extension may also use an
+experimental API implemented in a different extension by including the
+string ``experiments.name`` in the ``permissions``` property in its
+``manifest.json`` file. In this case, the string name must be replace by
+the name of the API from the extension that defined it (e.g., ``apiname``
+in the example above.
+
+Globals available in the API scripts global
+-------------------------------------------
+
+The API scripts aren't loaded as an JSM and so:
+
+- they are not fully isolated from each other (and they are going to be
+ lazy loaded when the extension does use them for the first time) and
+ be executed in a per-process shared global scope)
+- the experimental APIs embedded in privileged extensions are executed
+ in a per-extension global (separate from the one used for the built-in APIs)
+
+The global scope where the API scripts are executed is pre-populated with
+some useful globals:
+
+- ``AppConstants``
+- ``console``
+- ``CC``, ``Ci``, ``Cr`` and ``Cu``
+- ``ChromeWorker``
+- ``extensions``, ``ExtensionAPI``, ``ExtensionCommon`` and ``ExtensionUtils``
+- ``global``
+- ``MatchGlob``, ``MatchPattern`` and ``MatchPatternSet``
+- ``Services``
+- ``StructuredCloneHolder``
+- ``XPCOMUtils``
+
+For a more complete and updated list of the globals available by default in
+all API scripts look to the following source:
+
+- `SchemaAPIManager _createExtGlobal method <https://searchfox.org/mozilla-central/search?q=symbol:SchemaAPIManager%23_createExtGlobal&redirect=false>`_
+- Only available in the parent Firefox process:
+ `toolkit/components/extensions/parent/ext-toolkit.js <https://searchfox.org/mozilla-central/source/toolkit/components/extensions/parent/ext-toolkit.js>`_
+- Only available in the child Firefox process:
+ `toolkit/components/extensions/child/ext-toolkit.js <https://searchfox.org/mozilla-central/source/toolkit/components/extensions/child/ext-toolkit.js>`_
+- Only available in the Desktop builds:
+ `browser/components/extensions/parent/ext-browser.js <https://searchfox.org/mozilla-central/source/browser/components/extensions/parent/ext-browser.js>`_
+- Only available in the Android builds:
+ `mobile/android/components/extensions/ext-android.js <https://searchfox.org/mozilla-central/source/mobile/android/components/extensions/ext-android.js>`_
+
+.. warning::
+ The extension API authors should never redefine these globals to avoid introducing potential
+ conflicts between API scripts (e.g. see `Bug 1697404 comment 3 <https://bugzilla.mozilla.org/show_bug.cgi?id=1697404#c3>`_
+ and `Bug 1697404 comment 4 <https://bugzilla.mozilla.org/show_bug.cgi?id=1697404#c4>`_).
+
+WebIDL Bindings
+---------------
+
+In ``manifest_version: 3`` the extension will be able to declare a background service worker
+instead of a background page, and the existing WebExtensions API bindings can't be injected into this
+new extension global, because it lives off the main thread.
+
+To expose WebExtensions API bindings to the WebExtensions ``background.service_worker`` global
+we are in the process of generating new WebIDL bindings for the WebExtensions API.
+
+An high level view of the architecture and a more in depth details about the architecture process
+to create or modify WebIDL bindings for the WebExtensions API can be found here:
+
+.. toctree::
+ :maxdepth: 2
+
+ webidl_bindings