commit 623dcff6d873596b7f7ce483738be031e85241d0
parent 0ac2f426113b56cea6794274afaec8483c707956
Author: Andrea Marchesini <amarchesini@mozilla.com>
Date: Mon, 13 Oct 2025 21:56:18 +0000
Bug 1991982 - Documentation for the IPProtection feature, r=ip-protection-reviewers,fchasen
Differential Revision: https://phabricator.services.mozilla.com/D268437
Diffstat:
8 files changed, 258 insertions(+), 0 deletions(-)
diff --git a/browser/components/ipprotection/IPProtectionHelpers.sys.mjs b/browser/components/ipprotection/IPProtectionHelpers.sys.mjs
@@ -2,6 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/**
+ * Note: If you add or modify the list of helpers, make sure to update the
+ * corresponding documentation in the `docs` folder as well.
+ */
+
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
diff --git a/browser/components/ipprotection/IPProtectionService.sys.mjs b/browser/components/ipprotection/IPProtectionService.sys.mjs
@@ -51,6 +51,9 @@ ChromeUtils.defineLazyGetter(lazy, "logConsole", function () {
* Proxy is active.
* @property {string} ERROR
* Error
+ *
+ * Note: If you update this list of states, make sure to update the
+ * corresponding documentation in the `docs` folder as well.
*/
export const IPProtectionStates = Object.freeze({
UNINITIALIZED: "uninitialized",
diff --git a/browser/components/ipprotection/docs/Components.rst b/browser/components/ipprotection/docs/Components.rst
@@ -0,0 +1,154 @@
+Components
+==========
+
+This page summarizes the main components and how to extend the system safely.
+
+Component Diagram
+-----------------
+
+A diagram of all the main components is the following:
+
+.. mermaid::
+ :align: center
+ :caption: IP Protection architecture
+
+ flowchart TD
+
+ IPProtectionService
+
+ Helpers["IPProtectionHelpers"]
+
+ %% UI
+ subgraph UI
+ IPProtection
+ IPProtectionPanel
+ IPPExceptionsManager
+ end
+
+ %% Helpers
+ subgraph Helpers
+ IPPStartupCache["Startup Cache Helper"]
+ IPPSignInWatcher["Sign-in Observer"]
+ UIHelper["UI Helper"]
+ AccountResetHelper["Account Reset Helper"]
+ VPNAddonHelper["VPN Add-on Helper"]
+ EligibilityHelper["Nimbus Eligibility Helper"]
+ IPPAutoStart["Auto-Start Helper"]
+ IPPEarlyStartupFilter["Early Startup Filter Helper"]
+ end
+
+ %% Proxy stack
+ subgraph Proxy
+ IPPProxyManager
+ IPPChannelFilter
+ IPProtectionUsage
+ IPPNetworkErrorObserver
+ IPProtectionServerlist
+ GuardianClient
+ end
+
+ %% Service wiring
+ IPProtectionService --> IPPProxyManager
+ IPProtectionService --> GuardianClient
+ IPProtectionService --> Helpers
+
+ %% UI wiring
+ IPProtection --> IPProtectionPanel
+ IPProtection --> IPProtectionService
+
+ %% Proxy wiring
+ IPPProxyManager --> GuardianClient
+ IPPProxyManager --> IPPChannelFilter
+ IPPProxyManager --> IPProtectionUsage
+ IPPProxyManager --> IPPNetworkErrorObserver
+ IPPProxyManager --> IPProtectionServerlist
+ IPPNetworkErrorObserver -- "error events (401)" --> IPPProxyManager
+
+
+GuardianClient
+ Manages communication between Firefox and the Guardian backend. It retrieves
+ account information, obtains the token for the proxy, and exposes the server list.
+
+IPPChannelFilter
+ Main network component. It processes network requests and decides which ones
+ should go through the proxy.
+
+IPPProxyManager
+ Implements the proxy activation/deactivation and exposes the current status.
+
+IPProtectionPanel
+ Controls the feature’s panel UI.
+
+IPPExceptionsManager
+ Manages the exceptions UI and logic (for example, domain exclusions and
+ exceptions mode) in coordination with the panel and preferences.
+
+IPProtectionService
+ The main service. It is initialized during browser startup, initializes helpers
+ and other components, and implements the state machine that drives the feature.
+
+IPProtection
+ Manages the UI integration and interactions with the panel.
+
+Additional proxy/telemetry components
+-------------------------------------
+
+IPProtectionServerlist
+ Provides the available proxy endpoints (server list) to the proxy manager.
+
+IPProtectionUsage
+ Gathers usage information and telemetry related to proxy activity.
+
+IPPNetworkErrorObserver
+ Observes network errors related to the proxy and notifies the proxy manager
+ (for example, authentication or connectivity failures).
+
+Helper objects
+--------------
+
+The list of helpers lives in ``IPProtectionHelpers.sys.mjs`` and is exported
+as the ``IPPHelpers`` array. Helpers implement small, self‑contained behaviors
+and listen to service events when needed.
+
+IPPAutoStart
+ Activates the proxy at startup time when auto‑start is enabled.
+
+IPPSignInWatcher
+ Observes user authentication state. It informs the state machine when the user
+ signs in or out.
+
+IPPStartupCache
+ Exposes cached information to keep the state machine responsive during startup
+ (last known state and entitlement JSON object).
+
+UIHelper
+ Shows and hides the UI based on the current state machine state.
+
+AccountResetHelper
+ Resets stored account information and stops the proxy when the account becomes
+ unavailable.
+
+VPNAddonHelper
+ Monitors the installation of the Mozilla VPN add‑on and removes the UI when
+ appropriate.
+
+EligibilityHelper
+ Monitors the Nimbus experiment flag and triggers state updates when it changes.
+
+How to implement new components
+-------------------------------
+
+Do not modify the state machine. New functionality should be added via helper
+classes to keep the core simple and robust.
+
+Recommended steps:
+
+1. Create a helper class with the methods ``init()``, ``initOnStartupCompleted()``
+ and ``uninit()`` as appropriate for lifecycle needs.
+2. If your helper reacts to state changes, listen to the
+ ``IPProtectionService:StateChanged`` event.
+3. Add your helper to the ``IPPHelpers`` array in ``IPProtectionHelpers.sys.mjs``.
+ Be mindful of ordering if your helper depends on others (e.g. Nimbus
+ eligibility is registered last to avoid premature updates).
+4. If your component needs to trigger a recomputation, call
+ ``IPProtectionService.updateState``.
diff --git a/browser/components/ipprotection/docs/Preferences.rst b/browser/components/ipprotection/docs/Preferences.rst
@@ -0,0 +1,36 @@
+Preferences
+===========
+
+This document describes preferences affecting Firefox's IP Protection.
+These preferences are normally hidden and should not be used unless you really
+know what you are doing.
+
+``browser.ipProtection.enabled`` (boolean, default: ``false``)
+ Controls the entire feature.
+
+``browser.ipProtection.autoStartEnabled`` (boolean, default: ``false``)
+ Enables the auto‑start feature.
+
+``browser.ipProtection.log`` (boolean, default: ``false``)
+ Enable/disable logging.
+
+``browser.ipProtection.stateCache`` (string, default: ``""``)
+ Caches the latest ``IPProtectionStates`` value for use during startup.
+
+``browser.ipProtection.entitlementCache`` (string, default: ``""``)
+ Cached entitlement JSON string used during startup to avoid network requests.
+
+``browser.ipProtection.cacheDisabled`` (boolean, default: ``false``)
+ For testing; disables caching of the entitlement and the state.
+
+``browser.ipProtection.guardian.endpoint`` (string, default: ``"https://vpn.mozilla.org/"``)
+ Endpoint for the server‑side infrastructure.
+
+``browser.ipProtection.exceptionsMode`` (string, default: ``"all"``)
+ Defines which network requests are processed. Default: all.
+
+``browser.ipProtection.domainExclusions`` (string)
+ Comma‑separated list of domains to exclude from the proxy.
+
+``browser.ipProtection.userEnabled`` (boolean, default: ``false``)
+ For testing; simulates user‑enabled state.
diff --git a/browser/components/ipprotection/docs/StateMachine.rst b/browser/components/ipprotection/docs/StateMachine.rst
@@ -0,0 +1,39 @@
+State Machine
+=============
+
+The finite state machine is implemented in the ``IPProtectionService`` class
+and the states are defined in the ``IPProtectionStates`` object.
+
+States
+------
+
+The service transitions across the following states:
+
+- ``UNINITIALIZED``: Service not initialized or feature disabled.
+- ``UNAVAILABLE``: User not eligible (Nimbus) or signed out with no eligibility; UI hidden.
+- ``UNAUTHENTICATED``: User signed out but eligible; UI shows login.
+- ``ENROLLING``: User signed in and eligible; enrollment in progress.
+- ``READY``: Ready to activate the proxy.
+- ``ACTIVE``: Proxy is active.
+- ``ERROR``: An error occurred (see ``IPProtectionService.errors``).
+
+High‑level transitions
+----------------------
+
+- Feature disabled → ``UNINITIALIZED``.
+- During startup, if initialization isn’t complete, use cached state from ``IPPStartupCache``.
+- Not signed in → ``UNAVAILABLE`` if not eligible, otherwise ``UNAUTHENTICATED``.
+- Proxy already active → ``ACTIVE``.
+- If an entitlement is cached/valid → ``READY``.
+- Otherwise, check enrollment with Guardian:
+ - Not enrolled → ``UNAVAILABLE`` (not eligible) or ``ENROLLING`` (eligible).
+ - Enrolled → fetch entitlement; if successful → ``READY``, else ``UNAVAILABLE`` when not eligible.
+
+Events and integration points
+-----------------------------
+
+- ``IPProtectionService:StateChanged`` is dispatched on state changes with
+ ``detail.state`` and ``detail.prevState``.
+- Helpers can call ``IPProtectionService.updateState()`` to request a recomputation.
+- Public actions: ``start(userAction)``, ``stop(userAction)``, ``maybeEnroll()``,
+ ``resetAccount()``, and ``startLoginFlow(browser)``.
diff --git a/browser/components/ipprotection/docs/index.rst b/browser/components/ipprotection/docs/index.rst
@@ -0,0 +1,18 @@
+IP Protection
+=============
+
+This document describes the implementation of the IP Protection feature in Firefox.
+
+The code lives in `browser/components/ipprotection` and is composed of three major areas:
+
+ * A finite-state machine managed by the main component: `IPProtectionService`.
+ * The UI, controlled by `IPProtection` and `IPProtectionPanel`.
+ * The proxy/network controller: `IPPProxyManager` and helper classes.
+
+See the following pages for details on components, preferences, and the state machine.
+
+.. toctree::
+
+ Components
+ Preferences
+ StateMachine
diff --git a/browser/components/ipprotection/moz.build b/browser/components/ipprotection/moz.build
@@ -30,3 +30,5 @@ BROWSER_CHROME_MANIFESTS += [
"tests/browser/browser.toml",
]
XPCSHELL_TESTS_MANIFESTS += ["tests/xpcshell/xpcshell.toml"]
+
+SPHINX_TREES["/browser/ipprotection"] = "docs"
diff --git a/browser/docs/index.rst b/browser/docs/index.rst
@@ -27,6 +27,7 @@ This is the nascent documentation of the Firefox front-end code.
places/index
components/asrouter/docs/index
search/index
+ ipprotection/index
base/tabbrowser/index
touchbar/index
components/uitour/docs/index