IPPAutoStart.sys.mjs (5021B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; 6 7 const lazy = {}; 8 9 ChromeUtils.defineESModuleGetters(lazy, { 10 IPProtectionServerlist: 11 "moz-src:///browser/components/ipprotection/IPProtectionServerlist.sys.mjs", 12 IPPProxyManager: 13 "moz-src:///browser/components/ipprotection/IPPProxyManager.sys.mjs", 14 IPPProxyStates: 15 "moz-src:///browser/components/ipprotection/IPPProxyManager.sys.mjs", 16 IPProtectionService: 17 "moz-src:///browser/components/ipprotection/IPProtectionService.sys.mjs", 18 IPProtectionStates: 19 "moz-src:///browser/components/ipprotection/IPProtectionService.sys.mjs", 20 }); 21 22 const AUTOSTART_FEATURE_ENABLE_PREF = "browser.ipProtection.features.autoStart"; 23 const AUTOSTART_PREF = "browser.ipProtection.autoStartEnabled"; 24 25 /** 26 * This class monitors the auto-start pref and if it sees a READY state, it 27 * calls `start()`. This is done only if the previous state was not a ACTIVE 28 * because, in that case, more likely the VPN on/off state is an user decision. 29 */ 30 class IPPAutoStartSingleton { 31 #shouldStartWhenReady = false; 32 33 constructor() { 34 XPCOMUtils.defineLazyPreferenceGetter( 35 this, 36 "autoStartPref", 37 AUTOSTART_PREF, 38 false, 39 (_pref, _oldVal, featureEnabled) => { 40 if (featureEnabled) { 41 this.init(); 42 } else { 43 this.uninit(); 44 } 45 } 46 ); 47 48 XPCOMUtils.defineLazyPreferenceGetter( 49 this, 50 "autoStartFeatureEnablePref", 51 AUTOSTART_FEATURE_ENABLE_PREF, 52 false 53 ); 54 } 55 56 init() { 57 if (this.autoStart && !this.handleEvent) { 58 this.handleEvent = this.#handleEvent.bind(this); 59 this.#shouldStartWhenReady = true; 60 61 lazy.IPProtectionService.addEventListener( 62 "IPProtectionService:StateChanged", 63 this.handleEvent 64 ); 65 } 66 } 67 68 initOnStartupCompleted() {} 69 70 uninit() { 71 if (this.handleEvent) { 72 lazy.IPProtectionService.removeEventListener( 73 "IPProtectionService:StateChanged", 74 this.handleEvent 75 ); 76 77 delete this.handleEvent; 78 this.#shouldStartWhenReady = false; 79 } 80 } 81 82 get autoStart() { 83 // We activate the auto-start feature only if the pref is true and we have 84 // the serverlist already. 85 return ( 86 this.autoStartFeatureEnablePref && 87 this.autoStartPref && 88 lazy.IPProtectionServerlist.hasList 89 ); 90 } 91 92 #handleEvent(_event) { 93 switch (lazy.IPProtectionService.state) { 94 case lazy.IPProtectionStates.UNINITIALIZED: 95 case lazy.IPProtectionStates.UNAVAILABLE: 96 case lazy.IPProtectionStates.UNAUTHENTICATED: 97 this.#shouldStartWhenReady = true; 98 break; 99 100 case lazy.IPProtectionStates.READY: 101 if (this.#shouldStartWhenReady) { 102 this.#shouldStartWhenReady = false; 103 lazy.IPPProxyManager.start(/* user action: */ false); 104 } 105 break; 106 107 default: 108 break; 109 } 110 } 111 } 112 113 const IPPAutoStart = new IPPAutoStartSingleton(); 114 115 /** 116 * This class monitors the startup phases and registers/unregisters the channel 117 * filter to avoid data leak. The activation of the VPN is done by the 118 * IPPAutoStart object above. 119 */ 120 class IPPEarlyStartupFilter { 121 #autoStartAndAtStartup = false; 122 123 constructor() { 124 this.handleEvent = this.#handleEvent.bind(this); 125 this.#autoStartAndAtStartup = IPPAutoStart.autoStart; 126 } 127 128 init() { 129 if (this.#autoStartAndAtStartup) { 130 lazy.IPPProxyManager.createChannelFilter(); 131 132 lazy.IPProtectionService.addEventListener( 133 "IPProtectionService:StateChanged", 134 this.handleEvent 135 ); 136 lazy.IPPProxyManager.addEventListener( 137 "IPPProxyManager:StateChanged", 138 this.handleEvent 139 ); 140 } 141 } 142 143 initOnStartupCompleted() {} 144 145 uninit() { 146 if (this.autoStartAndAtStartup) { 147 this.#autoStartAndAtStartup = false; 148 149 lazy.IPPProxyManager.removeEventListener( 150 "IPPProxyManager:StateChanged", 151 this.handleEvent 152 ); 153 lazy.IPProtectionService.removeEventListener( 154 "IPProtectionService:StateChanged", 155 this.handleEvent 156 ); 157 } 158 } 159 160 #cancelChannelFilter() { 161 lazy.IPPProxyManager.cancelChannelFilter(); 162 } 163 164 #handleEvent(_event) { 165 switch (lazy.IPProtectionService.state) { 166 case lazy.IPProtectionStates.UNAVAILABLE: 167 case lazy.IPProtectionStates.UNAUTHENTICATED: 168 // These states block the auto-start at startup. 169 this.#cancelChannelFilter(); 170 this.uninit(); 171 break; 172 173 default: 174 // Let's ignoring any other state. 175 break; 176 } 177 178 if (lazy.IPPProxyManager.state === lazy.IPPProxyStates.ACTIVE) { 179 // We have completed our task. 180 this.uninit(); 181 } 182 } 183 } 184 185 const IPPAutoStartHelpers = [IPPAutoStart, new IPPEarlyStartupFilter()]; 186 187 export { IPPAutoStartHelpers };