/* 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 { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { IPProtectionService: "resource:///modules/ipprotection/IPProtectionService.sys.mjs", IPProtectionStates: "resource:///modules/ipprotection/IPProtectionService.sys.mjs", }); 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 IPPAutoStart { #shouldStartWhenReady = false; constructor() { XPCOMUtils.defineLazyPreferenceGetter( this, "autoStart", AUTOSTART_PREF, false, (_pref, _oldVal, featureEnabled) => { if (featureEnabled) { this.init(); } else { this.uninit(); } } ); } 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; } } #handleEvent(_event) { switch (lazy.IPProtectionService.state) { case lazy.IPProtectionStates.UNINITIALIZED: case lazy.IPProtectionStates.UNAVAILABLE: case lazy.IPProtectionStates.UNAUTHENTICATED: case lazy.IPProtectionStates.ENROLLING: case lazy.IPProtectionStates.ERROR: this.#shouldStartWhenReady = true; break; case lazy.IPProtectionStates.READY: if (this.#shouldStartWhenReady) { this.#shouldStartWhenReady = false; lazy.IPProtectionService.start(); } break; default: break; } } } /** * This class monitors the startup phases and registers/unregisters the channel * filter to avoid data leak. The activation of the VPN is done by the * IPPAutoStart object above. */ class IPPEarlyStartupFilter { #autoStartAndAtStartup = false; constructor() { this.handleEvent = this.#handleEvent.bind(this); this.#autoStartAndAtStartup = Services.prefs.getBoolPref( AUTOSTART_PREF, false ); } init() { if (this.#autoStartAndAtStartup) { lazy.IPProtectionService.proxyManager.createChannelFilter(); lazy.IPProtectionService.addEventListener( "IPProtectionService:StateChanged", this.handleEvent ); } } initOnStartupCompleted() {} uninit() { if (this.autoStartAndAtStartup) { this.#autoStartAndAtStartup = false; lazy.IPProtectionService.removeEventListener( "IPProtectionService:StateChanged", this.handleEvent ); } } #cancelChannelFilter() { lazy.IPProtectionService.proxyManager.cancelChannelFilter(); } #handleEvent(_event) { switch (lazy.IPProtectionService.state) { case lazy.IPProtectionStates.UNAVAILABLE: case lazy.IPProtectionStates.UNAUTHENTICATED: case lazy.IPProtectionStates.ERROR: // These states block the auto-start at startup. this.#cancelChannelFilter(); this.uninit(); break; case lazy.IPProtectionStates.ACTIVE: // We have completed our task. this.uninit(); break; default: // Let's ignoring any other state. break; } } } const IPPAutoStartHelpers = [new IPPAutoStart(), new IPPEarlyStartupFilter()]; export { IPPAutoStartHelpers };