tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 1ba924db4f5170942397430e5f76e2303623dd0b
parent c7dd1efaff8180014af79b6db9aaebc30ab2a7ec
Author: Andrea Marchesini <amarchesini@mozilla.com>
Date:   Mon, 10 Nov 2025 14:06:23 +0000

Bug 1998795 - IPProtection: implement the ACTIVATING state - part 5 - documentation r=ip-protection-reviewers,sstreich

Differential Revision: https://phabricator.services.mozilla.com/D271908

Diffstat:
Mbrowser/components/ipprotection/IPProtectionService.sys.mjs | 9++++-----
Mbrowser/components/ipprotection/docs/Components.rst | 5+++--
Mbrowser/components/ipprotection/docs/StateMachine.rst | 51+++++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/browser/components/ipprotection/IPProtectionService.sys.mjs b/browser/components/ipprotection/IPProtectionService.sys.mjs @@ -136,12 +136,11 @@ class IPProtectionServiceSingleton extends EventTarget { } /** - * Request to update the current state. - * - * Updates will be queued if another update is in progress. + * Recomputes the current state synchronously using the latest helper data. + * Callers should update their own inputs before invoking this. */ #updateState() { - this.#setState(this.#checkState()); + this.#setState(this.#computeState()); } /** @@ -149,7 +148,7 @@ class IPProtectionServiceSingleton extends EventTarget { * * @returns {Promise<IPProtectionStates>} */ - #checkState() { + #computeState() { // The IPP feature is disabled. if (!this.featureEnabled) { return IPProtectionStates.UNINITIALIZED; diff --git a/browser/components/ipprotection/docs/Components.rst b/browser/components/ipprotection/docs/Components.rst @@ -157,5 +157,6 @@ Recommended steps: Be mindful of ordering if your helper depends on others. For example, ``IPPNimbusHelper`` is registered last to avoid premature state updates triggered by Nimbus’ immediate callback. -4. If your component needs to trigger a recomputation, call - ``IPProtectionService.updateState``. +4. If your component needs to recompute the service state, call + ``IPProtectionService.updateState()`` after updating the helper data it + relies on; the recomputation is synchronous. diff --git a/browser/components/ipprotection/docs/StateMachine.rst b/browser/components/ipprotection/docs/StateMachine.rst @@ -1,11 +1,14 @@ State Machine ============= +Service state machine +--------------------- + The finite state machine is implemented in the ``IPProtectionService`` class and the states are defined in the ``IPProtectionStates`` object. -States ------- +Service states +~~~~~~~~~~~~~~ The service transitions across the following states: @@ -15,20 +18,56 @@ The service transitions across the following states: - ``READY``: Ready to activate the proxy. 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``. - If an entitlement is cached/valid → ``READY``. -- Otherwise, check enrollment with Guardian (via ``IPPErollHelper``): +- Otherwise, check enrollment with Guardian (via ``IPPEnrollAndEntitleManager``): - Not enrolled → ``UNAVAILABLE`` (not 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. +- Helpers can call ``IPProtectionService.updateState()`` to recompute the state immediately; update any helper-owned data first because the call is synchronous. - Public actions: ``start(userAction)``, ``stop(userAction)``, and ``startLoginFlow(browser)``. + +Proxy manager state machine +--------------------------- + +The ``IPPProxyManager`` layers a proxy‑specific finite state machine on top of +``IPProtectionService``. It mirrors eligibility changes from the service and +drives the lifecycle of the proxy connection. + +Proxy states +~~~~~~~~~~~~ + +- ``NOT_READY``: Service is not ``READY``. Channel filters are torn down and UI should not offer activation. +- ``READY``: Service is ``READY`` and the proxy can be activated. +- ``ACTIVATING``: ``start()`` is creating a channel filter, fetching a proxy pass, and selecting an endpoint. +- ``ACTIVE``: Proxy connected. Usage and network observers are reporting metrics. +- ``ERROR``: A recoverable error occurred while activating or rotating credentials. Errors are kept in a bounded history. + +Proxy transitions +~~~~~~~~~~~~~~~~~ + +- ``IPProtectionService:StateChanged`` → ``IPPProxyManager.updateState()``: + - Service ``READY`` → proxy ``READY`` (resets connection/error history). + - Any other service state → proxy ``NOT_READY`` (stops active connections). +- ``start(userAction)`` from ``READY`` moves to ``ACTIVATING``. + - Successful activation → ``ACTIVE`` and telemetry ``ipprotection.toggled``. + - Failures (missing entitlement, server list, proxy pass…) → ``ERROR`` via ``#setErrorState``. +- ``stop(userAction)`` from ``ACTIVE`` → ``READY`` after closing the channel filter and observers. +- ``reset()`` or helper‑driven recomputations call ``updateState()`` which demotes the proxy back to ``READY``/``NOT_READY`` and clears the credential cache. +- Network errors (``proxy-http-error`` with 401) trigger Proxy Pass rotation while staying ``ACTIVE``; repeated failures bubble up through ``#setErrorState``. + +Proxy events and hooks +~~~~~~~~~~~~~~~~~~~~~~ + +- ``IPPProxyManager:StateChanged`` is dispatched with ``detail.state`` whenever the proxy state machine moves. +- ``IPPProxyManager`` listens to ``IPProtectionService:StateChanged`` and to ``proxy-http-error`` from ``IPPNetworkErrorObserver``. +- Consumers can observe ``IPPProxyManager.state`` (or listen for events) to synchronize UI/telemetry with the proxy lifecycle.