Loading mobile/android/components/geckoview/GeckoViewStartup.jsm +19 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,10 @@ var EXPORTED_SYMBOLS = ["GeckoViewStartup"]; const { AppConstants } = ChromeUtils.importESModule( "resource://gre/modules/AppConstants.sys.mjs" ); const { GeckoViewUtils } = ChromeUtils.importESModule( "resource://gre/modules/GeckoViewUtils.sys.mjs" ); Loading @@ -17,6 +21,9 @@ ChromeUtils.defineESModuleGetters(lazy, { PdfJs: "resource://pdf.js/PdfJs.sys.mjs", Preferences: "resource://gre/modules/Preferences.sys.mjs", RFPHelper: "resource://gre/modules/RFPHelper.sys.mjs", TorConnect: "resource://gre/modules/TorConnect.sys.mjs", TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", TorSettings: "resource://gre/modules/TorSettings.sys.mjs", }); const { XPCOMUtils } = ChromeUtils.importESModule( Loading Loading @@ -258,6 +265,18 @@ class GeckoViewStartup { "GeckoView:SetLocale", ]); if ( AppConstants.MOZ_UPDATE_CHANNEL !== "release" && AppConstants.MOZ_UPDATE_CHANNEL !== "alpha" ) { lazy.TorProviderBuilder.init().finally(() => { lazy.TorProviderBuilder.firstWindowLoaded(); }); lazy.TorSettings.init().then(() => { lazy.TorConnect.init(); }); } Services.obs.addObserver(this, "browser-idle-startup-tasks-finished"); Services.obs.addObserver(this, "handlersvc-store-initialized"); Loading toolkit/components/tor-launcher/TorProcessAndroid.sys.mjs 0 → 100644 +115 −0 Original line number Diff line number Diff line /* 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 { ConsoleAPI } from "resource://gre/modules/Console.sys.mjs"; const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { EventDispatcher: "resource://gre/modules/Messaging.sys.mjs", }); // The only event we might emit const TOR_START_EVENT = "GeckoView:Tor:StartTor"; const logger = new ConsoleAPI({ maxLogLevel: "info", prefix: "TorProcessAndroid", }); // The events we will listen to const TorEvents = Object.freeze({ started: "GeckoView:Tor:TorStarted", startFailed: "GeckoView:Tor:TorStartFailed", exited: "GeckoView:Tor:TorExited", }); export class TorProcessAndroid { /** * The handle the Java counterpart uses to refer to the process we started. * We use it to filter the exit events and make sure they refer to the daemon * we are interested in. */ #processHandle = null; /** * The promise resolver we call when the Java counterpart sends the event that * tor has started. */ #startResolve = null; /** * The promise resolver we call when the Java counterpart sends the event that * it failed to start tor. */ #startReject = null; onExit = () => {}; get isRunning() { return !!this.#processHandle; } async start() { // Generate the handle on the JS side so that it's ready in case it takes // less to start the process than to propagate the success. this.#processHandle = crypto.randomUUID(); logger.info(`Starting new process with handle ${this.#processHandle}`); // Let's declare it immediately, so that the Java side can do its stuff in // an async manner and we avoid possible race conditions (at most we await // an already resolved/rejected promise. const startEventPromise = new Promise((resolve, reject) => { this.#startResolve = resolve; this.#startReject = reject; }); lazy.EventDispatcher.instance.registerListener( this, Object.values(TorEvents) ); let config; try { config = await lazy.EventDispatcher.instance.sendRequestForResult({ type: TOR_START_EVENT, handle: this.#processHandle, }); logger.debug("Sent the start event."); } catch (e) { this.forget(); throw e; } await startEventPromise; return config; } forget() { // Processes usually exit when we close the control port connection to them. logger.trace(`Forgetting process ${this.#processHandle}`); this.#processHandle = null; lazy.EventDispatcher.instance.unregisterListener( this, Object.values(TorEvents) ); } onEvent(event, data, callback) { if (data?.handle !== this.#processHandle) { logger.debug(`Ignoring event ${event} with another handle`, data); return; } logger.info(`Received an event ${event}`, data); switch (event) { case TorEvents.started: this.#startResolve(); break; case TorEvents.startFailed: this.#startReject(new Error(data.error)); break; case TorEvents.exited: this.forget(); if (this.#startReject !== null) { this.#startReject(); } this.onExit(data.status); break; } } } toolkit/components/tor-launcher/TorProvider.sys.mjs +31 −7 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ ChromeUtils.defineESModuleGetters(lazy, { FileUtils: "resource://gre/modules/FileUtils.sys.mjs", TorController: "resource://gre/modules/TorControlPort.sys.mjs", TorProcess: "resource://gre/modules/TorProcess.sys.mjs", TorProcessAndroid: "resource://gre/modules/TorProcessAndroid.sys.mjs", }); const logger = new ConsoleAPI({ Loading Loading @@ -182,8 +183,12 @@ export class TorProvider { logger.debug("Initializing the Tor provider."); // These settings might be customized in the following steps. if (TorLauncherUtil.isAndroid) { this.#socksSettings = { transproxy: false }; } else { this.#socksSettings = TorLauncherUtil.getPreferredSocksConfiguration(); logger.debug("Requested SOCKS configuration", this.#socksSettings); } try { await this.#setControlPortConfiguration(); Loading Loading @@ -490,10 +495,14 @@ export class TorProvider { return; } if (TorLauncherUtil.isAndroid) { this.#torProcess = new lazy.TorProcessAndroid(); } else { this.#torProcess = new lazy.TorProcess( this.#controlPortSettings, this.#socksSettings ); } // Use a closure instead of bind because we reassign #cancelConnection. // Also, we now assign an exit handler that cancels the first connection, // so that a sudden exit before the first connection is completed might Loading @@ -507,7 +516,17 @@ export class TorProvider { }; logger.debug("Trying to start the tor process."); await this.#torProcess.start(); const res = await this.#torProcess.start(); if (TorLauncherUtil.isAndroid) { this.#controlPortSettings = { ipcFile: new lazy.FileUtils.File(res.controlPortPath), cookieFilePath: res.cookieFilePath, }; this.#socksSettings = { transproxy: false, ipcFile: new lazy.FileUtils.File(res.socksPath), }; } logger.info("Started a tor process"); } Loading @@ -521,6 +540,11 @@ export class TorProvider { logger.debug("Reading the control port configuration"); const settings = {}; if (TorLauncherUtil.isAndroid) { // We will populate the settings after having started the daemon. return; } const isWindows = Services.appinfo.OS === "WINNT"; // Determine how Tor Launcher will connect to the Tor control port. // Environment variables get top priority followed by preferences. Loading toolkit/components/tor-launcher/moz.build +1 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ EXTRA_JS_MODULES += [ "TorLauncherUtil.sys.mjs", "TorParsers.sys.mjs", "TorProcess.sys.mjs", "TorProcessAndroid.sys.mjs", "TorProvider.sys.mjs", "TorProviderBuilder.sys.mjs", "TorStartupService.sys.mjs", Loading Loading
mobile/android/components/geckoview/GeckoViewStartup.jsm +19 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,10 @@ var EXPORTED_SYMBOLS = ["GeckoViewStartup"]; const { AppConstants } = ChromeUtils.importESModule( "resource://gre/modules/AppConstants.sys.mjs" ); const { GeckoViewUtils } = ChromeUtils.importESModule( "resource://gre/modules/GeckoViewUtils.sys.mjs" ); Loading @@ -17,6 +21,9 @@ ChromeUtils.defineESModuleGetters(lazy, { PdfJs: "resource://pdf.js/PdfJs.sys.mjs", Preferences: "resource://gre/modules/Preferences.sys.mjs", RFPHelper: "resource://gre/modules/RFPHelper.sys.mjs", TorConnect: "resource://gre/modules/TorConnect.sys.mjs", TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs", TorSettings: "resource://gre/modules/TorSettings.sys.mjs", }); const { XPCOMUtils } = ChromeUtils.importESModule( Loading Loading @@ -258,6 +265,18 @@ class GeckoViewStartup { "GeckoView:SetLocale", ]); if ( AppConstants.MOZ_UPDATE_CHANNEL !== "release" && AppConstants.MOZ_UPDATE_CHANNEL !== "alpha" ) { lazy.TorProviderBuilder.init().finally(() => { lazy.TorProviderBuilder.firstWindowLoaded(); }); lazy.TorSettings.init().then(() => { lazy.TorConnect.init(); }); } Services.obs.addObserver(this, "browser-idle-startup-tasks-finished"); Services.obs.addObserver(this, "handlersvc-store-initialized"); Loading
toolkit/components/tor-launcher/TorProcessAndroid.sys.mjs 0 → 100644 +115 −0 Original line number Diff line number Diff line /* 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 { ConsoleAPI } from "resource://gre/modules/Console.sys.mjs"; const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { EventDispatcher: "resource://gre/modules/Messaging.sys.mjs", }); // The only event we might emit const TOR_START_EVENT = "GeckoView:Tor:StartTor"; const logger = new ConsoleAPI({ maxLogLevel: "info", prefix: "TorProcessAndroid", }); // The events we will listen to const TorEvents = Object.freeze({ started: "GeckoView:Tor:TorStarted", startFailed: "GeckoView:Tor:TorStartFailed", exited: "GeckoView:Tor:TorExited", }); export class TorProcessAndroid { /** * The handle the Java counterpart uses to refer to the process we started. * We use it to filter the exit events and make sure they refer to the daemon * we are interested in. */ #processHandle = null; /** * The promise resolver we call when the Java counterpart sends the event that * tor has started. */ #startResolve = null; /** * The promise resolver we call when the Java counterpart sends the event that * it failed to start tor. */ #startReject = null; onExit = () => {}; get isRunning() { return !!this.#processHandle; } async start() { // Generate the handle on the JS side so that it's ready in case it takes // less to start the process than to propagate the success. this.#processHandle = crypto.randomUUID(); logger.info(`Starting new process with handle ${this.#processHandle}`); // Let's declare it immediately, so that the Java side can do its stuff in // an async manner and we avoid possible race conditions (at most we await // an already resolved/rejected promise. const startEventPromise = new Promise((resolve, reject) => { this.#startResolve = resolve; this.#startReject = reject; }); lazy.EventDispatcher.instance.registerListener( this, Object.values(TorEvents) ); let config; try { config = await lazy.EventDispatcher.instance.sendRequestForResult({ type: TOR_START_EVENT, handle: this.#processHandle, }); logger.debug("Sent the start event."); } catch (e) { this.forget(); throw e; } await startEventPromise; return config; } forget() { // Processes usually exit when we close the control port connection to them. logger.trace(`Forgetting process ${this.#processHandle}`); this.#processHandle = null; lazy.EventDispatcher.instance.unregisterListener( this, Object.values(TorEvents) ); } onEvent(event, data, callback) { if (data?.handle !== this.#processHandle) { logger.debug(`Ignoring event ${event} with another handle`, data); return; } logger.info(`Received an event ${event}`, data); switch (event) { case TorEvents.started: this.#startResolve(); break; case TorEvents.startFailed: this.#startReject(new Error(data.error)); break; case TorEvents.exited: this.forget(); if (this.#startReject !== null) { this.#startReject(); } this.onExit(data.status); break; } } }
toolkit/components/tor-launcher/TorProvider.sys.mjs +31 −7 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ ChromeUtils.defineESModuleGetters(lazy, { FileUtils: "resource://gre/modules/FileUtils.sys.mjs", TorController: "resource://gre/modules/TorControlPort.sys.mjs", TorProcess: "resource://gre/modules/TorProcess.sys.mjs", TorProcessAndroid: "resource://gre/modules/TorProcessAndroid.sys.mjs", }); const logger = new ConsoleAPI({ Loading Loading @@ -182,8 +183,12 @@ export class TorProvider { logger.debug("Initializing the Tor provider."); // These settings might be customized in the following steps. if (TorLauncherUtil.isAndroid) { this.#socksSettings = { transproxy: false }; } else { this.#socksSettings = TorLauncherUtil.getPreferredSocksConfiguration(); logger.debug("Requested SOCKS configuration", this.#socksSettings); } try { await this.#setControlPortConfiguration(); Loading Loading @@ -490,10 +495,14 @@ export class TorProvider { return; } if (TorLauncherUtil.isAndroid) { this.#torProcess = new lazy.TorProcessAndroid(); } else { this.#torProcess = new lazy.TorProcess( this.#controlPortSettings, this.#socksSettings ); } // Use a closure instead of bind because we reassign #cancelConnection. // Also, we now assign an exit handler that cancels the first connection, // so that a sudden exit before the first connection is completed might Loading @@ -507,7 +516,17 @@ export class TorProvider { }; logger.debug("Trying to start the tor process."); await this.#torProcess.start(); const res = await this.#torProcess.start(); if (TorLauncherUtil.isAndroid) { this.#controlPortSettings = { ipcFile: new lazy.FileUtils.File(res.controlPortPath), cookieFilePath: res.cookieFilePath, }; this.#socksSettings = { transproxy: false, ipcFile: new lazy.FileUtils.File(res.socksPath), }; } logger.info("Started a tor process"); } Loading @@ -521,6 +540,11 @@ export class TorProvider { logger.debug("Reading the control port configuration"); const settings = {}; if (TorLauncherUtil.isAndroid) { // We will populate the settings after having started the daemon. return; } const isWindows = Services.appinfo.OS === "WINNT"; // Determine how Tor Launcher will connect to the Tor control port. // Environment variables get top priority followed by preferences. Loading
toolkit/components/tor-launcher/moz.build +1 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ EXTRA_JS_MODULES += [ "TorLauncherUtil.sys.mjs", "TorParsers.sys.mjs", "TorProcess.sys.mjs", "TorProcessAndroid.sys.mjs", "TorProvider.sys.mjs", "TorProviderBuilder.sys.mjs", "TorStartupService.sys.mjs", Loading