summaryrefslogtreecommitdiffstats
path: root/mobile/android/docs/geckoview/design/managing-extensions.rst
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/docs/geckoview/design/managing-extensions.rst')
-rw-r--r--mobile/android/docs/geckoview/design/managing-extensions.rst229
1 files changed, 229 insertions, 0 deletions
diff --git a/mobile/android/docs/geckoview/design/managing-extensions.rst b/mobile/android/docs/geckoview/design/managing-extensions.rst
new file mode 100644
index 0000000000..8592854ecd
--- /dev/null
+++ b/mobile/android/docs/geckoview/design/managing-extensions.rst
@@ -0,0 +1,229 @@
+GeckoView Extension Managing API
+================================
+
+Agi Sferro <agi@sferro.dev>
+
+November 19th, 2019
+
+Introduction
+------------
+
+This document describes the API for installing, uninstalling and updating
+Extensions with GeckoView.
+
+Installing an extension provides the extension the ability to run at startup
+time, especially useful for e.g. extensions that intercept network requests,
+like an ad-blocker or a proxy extension. It also provides additional security
+from third-party extensions like signature checking and prompting the user for
+permissions.
+
+For this version of the API we will assume that the extension store is backed
+by ``addons.mozilla.org``, and so are the signatures. Running a third-party
+extension store is something we might consider in the future but explicitly not
+in scope for this document.
+
+API
+---
+
+The embedder will be able to install, uninstall, enable, disable and update
+extensions using the similarly-named APIs.
+
+Installing
+^^^^^^^^^^
+
+Gecko will download the extension pointed by the URI provided in install, parse
+the manifest and signature and provide an ``onInstallPrompt`` callback with the
+list of permissions requested by the extension and some information about the
+extension.
+
+The embedder will be able to install bundled first-party extensions using
+``installBuiltIn``. This method will only accept URIs that start with
+``resource://`` and will give additional privileges like being able to use app
+messaging and not needing a signature.
+
+Each permission will have a machine readable name that the embedder will use to
+produce user-facing internationalized strings. E.g. “bookmarks” gives access to
+bookmarks, “sessions” gives access to recently closed sessions. The full list
+of permissions that are currently shown to the UI in Firefox Desktop is
+available at: ``chrome/browser/browser.properties``
+
+Updating
+^^^^^^^^
+
+To update an extension, the embedder will be able to call update which will
+check if any update is available (using the update_url provided by the
+extension, or addons.mozilla.org if no update_url has been provided). The
+embedder will receive a GeckoResult that will provide the updated extension
+object. This result can also be used to know when the update process is
+complete, e.g. the embedder could use it to display a persistent notification
+to the user to avoid having the app be killed while updates are in process.
+
+If the updated extension needs additional permissions, ``GeckoView`` will call
+``onUpdatePrompt``.
+
+Until this callback is resolved (i.e. the embedder’s returned ``GeckoResult``
+is completed), the old addon will be running, only when the prompt is resolved
+and the update is applied the new version of the addon starts running and the
+``GeckoResult`` returned from update is resolved.
+
+This callback will provide both the current ``WebExtension`` object and the
+updated WebExtension object so that the embedder can show appropriate
+information to the user, e.g. the app might decide to remember whether the user
+denied the request for a certain version and only prompt the user once the
+version string changes.
+
+As a side effect of updating, Gecko will check its internal blocklist and might
+disable extensions that are incompatible with the current version of Gecko or
+deemed unsafe. The resulting ``WebExtension`` object will reflect that by
+having isEnabled set to false. The embedder will be able to inspect the reason
+why the extension was disabled using ``metaData.blockedReason``.
+
+Gecko will not update any extension or blocklist state without the embedder’s
+input.
+
+Enabling and Disabling
+^^^^^^^^^^^^^^^^^^^^^^
+
+Embedders will be able to enable and disabling extension using the homonymous
+APIs. Calling enable on an extension might not actually enable it if the
+extension has been added to the Gecko blocklist. Embedders can check the value
+of ``metaData.blockedReason`` to display to the user whether the extension can
+actually be enabled or not. The returned WebExtension object will reflect the
+updated enablement state in isEnabled.
+
+Listing
+^^^^^^^
+
+The embedder is expected to keep a collection of all available extensions using
+the result of install and update. To retrieve the extensions that are already
+installed the embedder will be able to use ``listInstalled`` which will
+asynchronously retrieve the full list of extensions. We recommend calling
+``listInstalled`` every time the user is presented with the extension manager
+UI to ensure all information is up to date.
+
+Outline
+^^^^^^^
+
+.. code:: java
+
+ public class WebExtensionController {
+ // Start the process of installing an extension,
+ // the embedder will either get the installed extension
+ // or an error
+ GeckoResult<WebExtension> install(String uri);
+
+ // Install a built-in WebExtension with privileged
+ // permissions, uri must be resource://
+ // Privileged WebExtensions have access to experiments
+ // (i.e. they can run chrome code), don’t need signatures
+ // and have access to native messaging to the app
+ GeckoResult<WebExtension> installBuiltIn(String uri)
+
+ GeckoResult<Void> uninstall(WebExtension extension);
+
+ GeckoResult<WebExtension> enable(WebExtension extension);
+
+ GeckoResult<WebExtension> disable(WebExtension extension);
+
+ GeckoResult<List<WebExtension>> listInstalled();
+
+ // Checks for updates. This method returns a GeckoResult that is
+ // resolved either with the updated WebExtension object or null
+ // if the extension does not have pending updates.
+ GeckoResult<WebExtension> update(WebExtension extension);
+
+ public interface PromptDelegate {
+ GeckoResult<AllowOrDeny> onInstallPrompt(WebExtension extension);
+
+ GeckoResult<AllowOrDeny> onUpdatePrompt(
+ WebExtension currentlyInstalled,
+ WebExtension updatedExtension,
+ List<String> newPermissions);
+
+ // Called when the extension calls browser.permission.request
+ GeckoResult<AllowOrDeny> onOptionalPrompt(
+ WebExtension extension,
+ List<String> optionalPermissions);
+ }
+
+ void setPromptDelegate(PromptDelegate promptDelegate);
+ }
+
+As part of this document, we will add a ``MetaData`` field to WebExtension
+which will contain all the information known about the extension. Note: we will
+rename ``ActionIcon`` to Icon to represent its generic use as the
+``WebExtension`` icon class.
+
+.. code:: java
+
+ public class WebExtension {
+ // Renamed from ActionIcon
+ static class Icon {}
+
+ final MetaData metadata;
+ final boolean isBuiltIn;
+
+ final boolean isEnabled;
+
+ public static class SignedStateFlags {
+ final static int UNKNOWN;
+ final static int PRELIMINARY;
+ final static int SIGNED;
+ final static int SYSTEM;
+ final static int PRIVILEGED;
+ }
+
+ // See nsIBlocklistService.idl
+ public static class BlockedReason {
+ final static int NOT_BLOCKED;
+ final static int SOFTBLOCKED;
+ final static int BLOCKED;
+ final static int OUTDATED;
+ final static int VULNERABLE_UPDATE_AVAILABLE;
+ final static int VULNERABLE_NO_UPDATE;
+ }
+
+ public class MetaData {
+ final Icon icon;
+ final String[] permissions;
+ final String[] origins;
+ final String name;
+ final String description;
+ final String version;
+ final String creatorName;
+ final String creatorUrl;
+ final String homepageUrl;
+ final String optionsPageUrl;
+ final boolean openOptionsPageInTab;
+ final boolean isRecommended;
+ final @BlockedReason int blockedReason;
+ final @SignedState int signedState;
+ // more if needed
+ }
+ }
+
+Implementation Details
+^^^^^^^^^^^^^^^^^^^^^^
+
+We will use ``AddonManager`` as a backend for ``WebExtensionController`` and
+delegate the prompt to the app using ``PromptDelegate``. We will also merge
+``WebExtensionController`` and ``WebExtensionEventDispatcher`` for ease of
+implementation.
+
+Existing APIs
+^^^^^^^^^^^^^
+
+Some APIs today return a ``WebExtension`` object that might have not been
+fetched yet by ``listInstalled``. In these cases, GeckoView will return a stub
+``WebExtension`` object in which the metadata field will be null to avoid
+waiting for a addon list call. To ensure that the metadata field is populated,
+the embedder will need to call ``listInstalled`` at least once during the app
+startup.
+
+Deprecation Path
+^^^^^^^^^^^^^^^^
+
+The existing ``registerWebExtension`` and ``unregisterWebExtension`` APIs will
+be deprecated by ``installBuiltIn`` and ``uninstall``. We will remove the above
+APIs 6 releases after the implementation of ``installBuiltIn`` lands and mark
+it as deprecated in the API.