Files
sousa-gecko/toolkit/components/ipprotection/IPPAutoStart.sys.mjs
T
Josh Porter e72386a621 Bug 2041803 - Add IPPAlwaysOn for enterprise AccessConnector policy. r=sstreich,ip-protection-reviewers
Adds IPPAlwaysOn, an enterprise-only helper that keeps the proxy alive whenever the policy is active. Unlike IPPAutoStart, it recovers from ERROR states, restarts on unexpected stops, and hot-swaps the server when the list changes.

- For Enterprise, use IPPAlwaysOnHelpers instead of IPPAutoRestoreHelper + IPPAutoStartHelpers
- Extract IPPEarlyStartupFilter from IPPAutoStart into its own module for sharing with IPPAlwaysOn
- Fix PrefServerList to deduplicate maybeFetchList calls and fix pref observer reference
- Live-update IPPChannelFilter inclusion set on pref change

Differential Revision: https://phabricator.services.mozilla.com/D302499
2026-06-02 12:14:21 +00:00

124 lines
3.4 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
import { PrivateBrowsingUtils } from "resource://gre/modules/PrivateBrowsingUtils.sys.mjs";
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
import { IPPEarlyStartupFilter } from "moz-src:///toolkit/components/ipprotection/IPPEarlyStartupFilter.sys.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
IPProtectionServerlist:
"moz-src:///toolkit/components/ipprotection/IPProtectionServerlist.sys.mjs",
IPPProxyManager:
"moz-src:///toolkit/components/ipprotection/IPPProxyManager.sys.mjs",
IPProtectionService:
"moz-src:///toolkit/components/ipprotection/IPProtectionService.sys.mjs",
IPProtectionStates:
"moz-src:///toolkit/components/ipprotection/IPProtectionService.sys.mjs",
});
const AUTOSTART_FEATURE_ENABLE_PREF = "browser.ipProtection.features.autoStart";
const AUTOSTART_PREF = "browser.ipProtection.autoStartEnabled";
/**
* This class monitors the auto-start pref and if it sees a READY state, it
* calls `start()`. This is done only if the previous state was not a ACTIVE
* because, in that case, more likely the VPN on/off state is an user decision.
*/
class IPPAutoStartSingleton {
#shouldStartWhenReady = false;
constructor() {
XPCOMUtils.defineLazyPreferenceGetter(
this,
"autoStartPref",
AUTOSTART_PREF,
false,
(_pref, _oldVal, featureEnabled) => {
if (featureEnabled) {
this.init();
} else {
this.uninit();
}
}
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"autoStartFeatureEnablePref",
AUTOSTART_FEATURE_ENABLE_PREF,
false
);
}
init() {
if (this.autoStart && !this.handleEvent) {
this.handleEvent = this.#handleEvent.bind(this);
this.#shouldStartWhenReady = true;
lazy.IPProtectionService.addEventListener(
"IPProtectionService:StateChanged",
this.handleEvent
);
}
}
initOnStartupCompleted() {}
uninit() {
if (this.handleEvent) {
lazy.IPProtectionService.removeEventListener(
"IPProtectionService:StateChanged",
this.handleEvent
);
delete this.handleEvent;
this.#shouldStartWhenReady = false;
}
}
get autoStart() {
// We activate the auto-start feature only if the pref is true and we have
// the serverlist already.
return (
this.autoStartFeatureEnablePref &&
this.autoStartPref &&
lazy.IPProtectionServerlist.hasList
);
}
#handleEvent(_event) {
switch (lazy.IPProtectionService.state) {
case lazy.IPProtectionStates.UNINITIALIZED:
case lazy.IPProtectionStates.UNAVAILABLE:
case lazy.IPProtectionStates.UNAUTHENTICATED:
this.#shouldStartWhenReady = true;
break;
case lazy.IPProtectionStates.READY:
if (this.#shouldStartWhenReady) {
this.#shouldStartWhenReady = false;
lazy.IPPProxyManager.start(
false,
PrivateBrowsingUtils.permanentPrivateBrowsing
);
}
break;
default:
break;
}
}
}
const IPPAutoStart = new IPPAutoStartSingleton();
const IPPAutoStartHelpers = [
IPPAutoStart,
new IPPEarlyStartupFilter(() => IPPAutoStart.autoStart),
];
export { IPPAutoStartHelpers };