diff options
Diffstat (limited to 'toolkit/components/extensions/docs/webidl_bindings.rst')
-rw-r--r-- | toolkit/components/extensions/docs/webidl_bindings.rst | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/toolkit/components/extensions/docs/webidl_bindings.rst b/toolkit/components/extensions/docs/webidl_bindings.rst new file mode 100644 index 0000000000..93556e9296 --- /dev/null +++ b/toolkit/components/extensions/docs/webidl_bindings.rst @@ -0,0 +1,246 @@ +WebIDL WebExtensions API Bindings +================================= + +While on ``manifest_version: 2`` all the extension globals (extension pages and content scripts) +that lives on the main thread and the WebExtensions API bindings can be injected into the extension +global from the JS privileged code part of the WebExtensions internals (`See Schemas.inject defined in +Schemas.jsm <https://searchfox.org/mozilla-central/search?q=symbol:Schemas%23inject&redirect=false>`_), +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 of 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. + +.. warning:: + + For more general in depth details about WebIDL in Gecko: + + - :doc:`/dom/bindings/webidl/index` + - :doc:`/dom/webIdlBindings/index` + +Review process on changes to webidl definitions +----------------------------------------------- + +.. note:: + + When new webidl definitions are being introduced for a WebExtensions API, or + existing ones need to be updated to stay in sync with changes applied to the + JSONSchema definitions of the same WebExtensions API, the resulting patch + will include a **new or changed WebIDL located at dom/webidl** and that part of the + patch **will require a mandatory review and sign-off from a peer part of the** + webidl_ **phabricator review group**. + +This section includes a brief description about the special setup of the +webidl files related to WebExtensions and other notes useful to the +WebIDL peers that will be reviewing and signing off these webidl files. + +.. _webidl: https://phabricator.services.mozilla.com/tag/webidl/ + +How/Where are these webidl interfaces restricted to the extensions background service workers? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All the webidl interfaces related to the extensions API are only visible in +specific extension globals: the WebExtensions background service worker +(a service worker declared in the extension ``manifest.json`` file, through +the ``background.service_worker`` manifest field). + +All webidl interfaces related to the WebExtensions API interfaces are exposed +through the ``ExtensionBrowser`` interface, which gets exposed into the +``ServiceWorkerGlobalScope`` through the ``ExtensionGlobalsMixin`` interface and +restricted to the WebExtensions background service worker through the +``mozilla::extensions::ExtensionAPIAllowed`` helper function. + +See ``ExtensionBrowser`` and ``ExtensionGlobalsMixin`` interfaces defined from +ExtensionBrowser.webidl_ and ``mozilla::extensions::ExtensionAPIAllowed`` defined in +ExtensionBrowser.cpp_. + +.. _ExtensionBrowser.webidl: https://searchfox.org/mozilla-central/source/dom/webidl/ExtensionBrowser.webidl +.. _ExtensionBrowser.cpp: https://searchfox.org/mozilla-central/source/toolkit/components/extensions/webidl-api/ExtensionBrowser.cpp + +Why do all the webidl interfaces for WebExtensions API use LegacyNoInterfaceObject? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The existing WebExtensions API bindings are not exposing any constructor in the +globals where they are available (e.g. the webidl bindings for the ``browser.alarms`` +API namespace is defined by the ``ExtensionAlarms`` webidl interface, but there +shouldn't be any ``ExtensionAlarms`` constructor available as a global to extension +code running in the background service worker). + +A previous attempt to create W3C specs for the WebExtensions APIs described in WebIDL +syntaxes (https://browserext.github.io/browserext) was also using the same +``NoInterfaceObject`` WebIDL attribute on the definitions of the API namespace +with the same motivations (eg. see ``BrowserExtBrowserRuntime`` as defined here: +https://browserext.github.io/browserext/#webidl-definition-4). + +Bug 1713877_ is tracking a followup to determine a long term replacement for the +``LegacyNoInterfaceObject`` attribute currently being used. + +.. _1713877: https://bugzilla.mozilla.org/1713877 + +Background Service Workers API Request Handling +----------------------------------------------- + +.. figure:: webidl_bindings_backgroundWorker_apiRequestHandling.drawio.svg + :alt: High Level Diagram of the Background Service Worker API Request Handling + +.. + This svg diagram has been created using https://app.diagrams.net, + the svg file also includes the source in the drawio format and so + it can be edited more easily by loading it back into app.diagrams.net + and then re-export from there (and include the updated drawio format + content into the exported svg file). + +Generating WebIDL definitions from WebExtensions API JSONSchema +--------------------------------------------------------------- + +WebIDL definitions for the extension APIs are being generated based on the WebExtensions API JSONSchema +data (the same metadata used to generate the "privilged JS"-based API bindings). + +Most of the API methods in generated WebIDL are meant to be implemented using stub methods shared +between all WebExtensions API classes, a ``WebExtensionStub`` webidl extended attribute specify +which shared stub method should be used when the related API method is called. + +For more in depth details about how to generate or update webidl definition for an Extension API +given its API namespace: + +.. toctree:: + :maxdepth: 2 + + generate_webidl_from_jsonschema + +Wiring up new WebExtensions WebIDL files into mozilla-central +------------------------------------------------------------- + +After a new WebIDL definition has been generated, there are a few more steps to ensure that +the new WebIDL binding is wired up into mozilla-central build system and to be able to +complete successfully a full Gecko build that include the new bindings. + +For more in depth details about these next steps: + +.. toctree:: + :maxdepth: 2 + + wiring_up_new_webidl_bindings + +Testing WebExtensions WebIDL bindings +------------------------------------- + +Once the WebIDL definition for an WebExtensions API namespace has been +implemented and wired up, the following testing strategies are available to +cover them as part of the WebExtensions testing suites: + +``toolkit/components/extensions/test/xpcshell/webidl-api`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The xpcshell tests added to this group of xpcshell tests are meant to provide testing coverage +related to lower level components and behaviors (e.g. when making changes to the shared C++ +helpers defined in ``toolkit/components/extensions/webidl-api``, or adding new ones). + +These tests will often mock part of the internals and use a ``browser.mockExtensionAPI`` +API namespace which is only available in tests and not mapped to any actual API implementation +(instead it is being mocked in the test cases to recreate the scenario that the test case is meant +to cover). + +And so **they are not meant to provide any guarantees in terms of consistency of the behavior +of the two different bindings implementations** (the new WebIDL bindings vs. the current implemented +bindings), instead the other test suites listed in the sections below should be used for that purpose. + +All tests in this directory are skipped in builds where the WebExtensions WebIDL API bindings +are being disabled at build time (e.g. beta and release builds, where otherwise +the test would permafail while riding the train once got on those builds). + + +``toolkit/components/extensions/test/xpcshell/xpcshell-serviceworker.ini`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a new or existing xpcshell tests added to this xpcshell-test manifest, all test extensions +will be generated with a background service worker instead of a background page. + +.. warning:: + **Unless the background page or scripts are declared as part of the test extension manifest**, + the test file added to this manifest should be explicitly reviewed to make sure all tests + are going to provide the expected test coverage in all modes. + +.. note:: + In a background script that runs in both a background page and a background + service worker it may be necessary to run different code for part of the + test, ``self !== self.window`` is a simple check that can be used to detect if + the script is being executed as a background service worker. + +Test tasks that should be skipped when running in "background service worker mode", but temporarily +until a followup fixes the underlying issue can use the ``ExtensionTestUtils.isInBackgroundServiceWorkerTests()`` in the optional +``add_task``'s ``skip_if`` parameter: + +.. code-block:: js + + add_task( + { + // TODO(Bug TBF): remove this once ... + skip_if: () => ExtensionTestUtils.isInBackgroundServiceWorkerTests(), + }, + async function test_someapi_under_scenario() { + ... + } + ); + +On the contrary if the test tasks is covering a scenario that is specific to a background page, +and it would need to be permanently skipped while the background script is running as a service worker, +it may be more appropriate to split out those tests in a separate test file not included in this +manifest. + +.. warning:: + Make sure that all tests running in multiple modes (in-process, + remote, and "background service worker mode") do not assume that the WebIDL + bindings and Background Service Worker are enabled and to skip them when appropriate, + otherwise the test will become a permafailure once it gets to a channel + where the "Extensions WebIDL API bindings" are disabled by default at build + time (currently on **beta** and **release**). + +While running the test files locally they will be executed once for each manifest file +where they are included, to restrict the run to just the "background service +workers mode" specify the ``sw-webextensions`` tag: + +.. code-block:: + + mach xpcshell-test --tag sw-webextensions path/to/test/file.js + +``toolkit/components/extensions/test/mochitest/mochitest-serviceworker.ini`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Same as the xpcshell-serviceworker.ini manifest but for the mochitest-plain tests. + +.. warning:: + The same warnings described in the xpcshell-serviceworker.ini subsection do + also apply to this manifest file. + +Test tasks that should be skipped when not running in "background service worker +mode" can be split into separate test file or skipped inside the ``add_task`` +body, but mochitests' ``add_task`` does not support a ``skip_if`` option and so +that needs to be done manually (and it may be good to also log a message to make +it visible when a test is skipped): + +.. code-block:: js + + add_task(async function test_someapi_in_background_service_worker() { + if (!ExtensionTestUtils.isInBackgroundServiceWorkerTests()) { + is( + ExtensionTestUtils.getBackgroundServiceWorkerEnabled(), + false, + "This test should only be skipped with background service worker disabled" + ) + info("Test intentionally skipped on 'extensions.backgroundServiceWorker.enabled=false'"); + return; + } + + + ... + }); + +While executing the test files locally they will run once for each manifest file +where they are included, to restrict the run to just the "background service +workers mode" specify the ``sw-webextensions`` tag: + +.. code-block:: + + mach mochitest --tag sw-webextensions path/to/test/file.js |