tor-commits
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
January 2024
- 1 participants
- 129 discussions
[Git][tpo/applications/firefox-android][firefox-android-115.2.1-13.5-1] fixup! Add Tor integration and UI
by Dan Ballard (@dan) 26 Jan '24
by Dan Ballard (@dan) 26 Jan '24
26 Jan '24
Dan Ballard pushed to branch firefox-android-115.2.1-13.5-1 at The Tor Project / Applications / firefox-android
Commits:
6d0a6453 by Dan Ballard at 2024-01-25T16:15:45-08:00
fixup! Add Tor integration and UI
Bug 42252: Make TorController and interface and add a Geckoview implementation
- - - - -
4 changed files:
- fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt
- + fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt
- + fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt
Changes:
=====================================
fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
=====================================
@@ -43,7 +43,8 @@ import org.mozilla.fenix.perf.StartupActivityLog
import org.mozilla.fenix.perf.StartupStateProvider
import org.mozilla.fenix.perf.StrictModeManager
import org.mozilla.fenix.perf.lazyMonitored
-import org.mozilla.fenix.tor.TorController
+import org.mozilla.fenix.tor.TorControllerGV
+import org.mozilla.fenix.tor.TorControllerTAS
import org.mozilla.fenix.utils.ClipboardHandler
import org.mozilla.fenix.utils.Settings
import org.mozilla.fenix.wifi.WifiConnectionMonitor
@@ -201,7 +202,7 @@ class Components(private val context: Context) {
),
)
}
- val torController by lazyMonitored { TorController(context) }
+ val torController by lazyMonitored { if (settings.useNewBootstrap) TorControllerGV(context) else TorControllerTAS(context) }
}
/**
=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt
=====================================
@@ -4,22 +4,7 @@
package org.mozilla.fenix.tor
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
import androidx.lifecycle.LifecycleCoroutineScope
-import androidx.localbroadcastmanager.content.LocalBroadcastManager
-
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withTimeoutOrNull
-
-import org.mozilla.fenix.BuildConfig
-
-import org.torproject.android.service.TorService
-import org.torproject.android.service.TorServiceConstants
-import org.torproject.android.service.util.Prefs
interface TorEvents {
fun onTorConnecting()
@@ -28,347 +13,59 @@ interface TorEvents {
fun onTorStopped()
}
-private enum class TorStatus {
- OFF,
- STARTING,
- ON,
- STOPPING,
- UNKNOWN;
+internal enum class TorStatus(val status: String) {
+ OFF("OFF"),
+ STARTING("STARTING"),
+ ON("ON"),
+ STOPPING("STOPPING"),
+ UNKNOWN("UNKNOWN");
- fun getStateFromString(status: String): TorStatus {
- return when (status) {
- TorServiceConstants.STATUS_ON -> ON
- TorServiceConstants.STATUS_STARTING -> STARTING
- TorServiceConstants.STATUS_STOPPING -> STOPPING
- TorServiceConstants.STATUS_OFF -> OFF
- else -> UNKNOWN
+ companion object {
+ fun fromString(status: String): TorStatus {
+ return when (status) {
+ "ON" -> ON
+ "STARTING" -> STARTING
+ "STOPPING" -> STOPPING
+ "OFF" -> OFF
+ else -> UNKNOWN
+ }
}
}
fun isOff() = this == OFF
fun isOn() = this == ON
fun isStarting() = this == STARTING
- fun isStarted() = ((this == TorStatus.STARTING) || (this == TorStatus.ON))
+ fun isStarted() = ((this == STARTING) || (this == ON))
fun isStopping() = this == STOPPING
fun isUnknown() = this == UNKNOWN
}
-@SuppressWarnings("TooManyFunctions")
-class TorController(
- private val context: Context
-) : TorEvents {
-
- private val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context)
- private val entries = mutableListOf<Pair<String?, String?>>()
- val logEntries get() = entries
-
- private var torListeners = mutableListOf<TorEvents>()
-
- private var pendingRegisterChangeList = mutableListOf<Pair<TorEvents, Boolean>>()
- private var lockTorListenersMutation = false
-
- private var lastKnownStatus = TorStatus.OFF
- private var wasTorBootstrapped = false
- private var isTorRestarting = false
-
- // This may be a lie
- private var isTorBootstrapped = false
- get() = ((lastKnownStatus == TorStatus.ON) && wasTorBootstrapped)
-
- val isDebugLoggingEnabled get() =
- context
- .getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE)
- .getBoolean("pref_enable_logging", false)
-
- val isStarting get() = lastKnownStatus.isStarting()
- val isRestarting get() = isTorRestarting
- val isBootstrapped get() = isTorBootstrapped
- val isConnected get() = (lastKnownStatus.isStarted() && !isTorRestarting)
-
+interface TorController: TorEvents {
+ val logEntries: MutableList<Pair<String?, String?>>
+ val isStarting: Boolean
+ val isRestarting: Boolean
+ val isBootstrapped: Boolean
+ val isConnected: Boolean
var bridgesEnabled: Boolean
- get() = Prefs.bridgesEnabled()
- set(value) { Prefs.putBridgesEnabled(value) }
-
var bridgeTransport: TorBridgeTransportConfig
- get() {
- return TorBridgeTransportConfigUtil.getStringToBridgeTransport(
- Prefs.getBridgesList()
- )
- }
- set(value) {
- if (value == TorBridgeTransportConfig.USER_PROVIDED) {
- // Don't set the pref when the value is USER_PROVIDED because
- // "user_provided" is not a valid bridge or transport type.
- // This call should be followed by setting userProvidedBridges.
- return
- }
- Prefs.setBridgesList(value.transportName)
- }
-
var userProvidedBridges: String?
- get() {
- val bridges = Prefs.getBridgesList()
- val bridgeType =
- TorBridgeTransportConfigUtil.getStringToBridgeTransport(bridges)
- return when (bridgeType) {
- TorBridgeTransportConfig.USER_PROVIDED -> bridges
- else -> null
- }
- }
- set(value) {
- Prefs.setBridgesList(value)
- }
-
- fun start() {
- // Register receiver
- lbm.registerReceiver(
- persistentBroadcastReceiver,
- IntentFilter(TorServiceConstants.ACTION_STATUS)
- )
- lbm.registerReceiver(
- persistentBroadcastReceiver,
- IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)
- )
- }
- fun stop() {
- lbm.unregisterReceiver(persistentBroadcastReceiver)
- }
+ fun start()
+ fun stop()
- private val persistentBroadcastReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- if (intent.action == null ||
- (intent.action != TorServiceConstants.ACTION_STATUS &&
- intent.action != TorServiceConstants.LOCAL_ACTION_LOG)
- ) {
- return
- }
- val action = intent.action
+ override fun onTorConnecting()
+ override fun onTorConnected()
+ override fun onTorStatusUpdate(entry: String?, status: String?)
+ override fun onTorStopped()
- val logentry: String?
- val status: String?
- if (action == TorServiceConstants.LOCAL_ACTION_LOG) {
- logentry = intent.getExtras()
- ?.getCharSequence(TorServiceConstants.LOCAL_EXTRA_LOG) as? String?
- } else {
- logentry = null
- }
-
- status = intent.getExtras()
- ?.getCharSequence(TorServiceConstants.EXTRA_STATUS) as? String?
-
- if (logentry == null && status == null) {
- return
- }
-
- onTorStatusUpdate(logentry, status)
-
- if (status == null) {
- return
- }
-
- val newStatus = lastKnownStatus.getStateFromString(status)
-
- if (newStatus.isUnknown() && wasTorBootstrapped) {
- stopTor()
- }
-
- entries.add(Pair(logentry, status))
-
- if (logentry != null && logentry.contains(TorServiceConstants.TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)) {
- wasTorBootstrapped = true
- onTorConnected()
- }
-
- if (lastKnownStatus.isStopping() && newStatus.isOff()) {
- if (isTorRestarting) {
- initiateTorBootstrap()
- } else {
- onTorStopped()
- }
- }
-
- if (lastKnownStatus.isOff() && newStatus.isStarting()) {
- isTorRestarting = false
- }
-
- lastKnownStatus = newStatus
- }
- }
-
- override fun onTorConnecting() {
- lockTorListenersMutation = true
- torListeners.forEach { it.onTorConnecting() }
- lockTorListenersMutation = false
-
- handlePendingRegistrationChanges()
- }
-
- override fun onTorConnected() {
- lockTorListenersMutation = true
- torListeners.forEach { it.onTorConnected() }
- lockTorListenersMutation = false
-
- handlePendingRegistrationChanges()
- }
+ fun registerTorListener(l: TorEvents)
+ fun unregisterTorListener(l: TorEvents)
- override fun onTorStatusUpdate(entry: String?, status: String?) {
- lockTorListenersMutation = true
- torListeners.forEach { it.onTorStatusUpdate(entry, status) }
- lockTorListenersMutation = false
-
- handlePendingRegistrationChanges()
- }
-
- override fun onTorStopped() {
- lockTorListenersMutation = true
- torListeners.forEach { it.onTorStopped() }
- lockTorListenersMutation = false
-
- handlePendingRegistrationChanges()
- }
-
- fun registerTorListener(l: TorEvents) {
- if (torListeners.contains(l)) {
- return
- }
-
- if (lockTorListenersMutation) {
- pendingRegisterChangeList.add(Pair(l, true))
- } else {
- torListeners.add(l)
- }
- }
-
- fun unregisterTorListener(l: TorEvents) {
- if (!torListeners.contains(l)) {
- return
- }
-
- if (lockTorListenersMutation) {
- pendingRegisterChangeList.add(Pair(l, false))
- } else {
- torListeners.remove(l)
- }
- }
-
- private fun handlePendingRegistrationChanges() {
- pendingRegisterChangeList.forEach {
- if (it.second) {
- registerTorListener(it.first)
- } else {
- unregisterTorListener(it.first)
- }
- }
-
- pendingRegisterChangeList.clear()
- }
-
- /**
- * Receive the current Tor status.
- *
- * Send a request for the current status and receive the response.
- * Returns true if Tor is running, false otherwise.
- *
- */
- private suspend fun checkTorIsStarted(): Boolean {
- val channel = Channel<Boolean>()
-
- // Register receiver
- val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context)
- val localBroadcastReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- val action = intent.action ?: return
- // We only want ACTION_STATUS messages
- if (action != TorServiceConstants.ACTION_STATUS) {
- return
- }
- // The current status has the EXTRA_STATUS key
- val currentStatus =
- intent.getStringExtra(TorServiceConstants.EXTRA_STATUS)
- channel.trySend(currentStatus === TorServiceConstants.STATUS_ON)
- }
- }
- lbm.registerReceiver(
- localBroadcastReceiver,
- IntentFilter(TorServiceConstants.ACTION_STATUS)
- )
-
- // Request service status
- sendServiceAction(TorServiceConstants.ACTION_STATUS)
-
- // Wait for response and unregister receiver
- var torIsStarted = false
- withTimeoutOrNull(torServiceResponseTimeout) {
- torIsStarted = channel.receive()
- }
- lbm.unregisterReceiver(localBroadcastReceiver)
- return torIsStarted
- }
-
- fun initiateTorBootstrap(lifecycleScope: LifecycleCoroutineScope? = null, withDebugLogging: Boolean = false) {
- if (BuildConfig.DISABLE_TOR) {
- return
- }
-
- context.getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE)
- .edit().putBoolean("pref_enable_logging", withDebugLogging).apply()
-
- if (lifecycleScope == null) {
- sendServiceAction(TorServiceConstants.ACTION_START)
- } else {
- lifecycleScope.launch {
- val torNeedsStart = !checkTorIsStarted()
- if (torNeedsStart) {
- sendServiceAction(TorServiceConstants.ACTION_START)
- }
- }
- }
- }
-
- fun stopTor() {
- if (BuildConfig.DISABLE_TOR) {
- return
- }
-
- val torService = Intent(context, TorService::class.java)
- context.stopService(torService)
- }
-
- fun setTorStopped() {
- lastKnownStatus = TorStatus.OFF
- onTorStopped()
- }
-
- fun restartTor() {
- // tor-android-service doesn't dynamically update the torrc file,
- // and it doesn't use SETCONF, so we completely restart the service.
- // However, don't restart if we aren't started and we weren't
- // previously started.
- if (!lastKnownStatus.isStarted() && !wasTorBootstrapped) {
- return
- }
+ fun initiateTorBootstrap(lifecycleScope: LifecycleCoroutineScope? = null, withDebugLogging: Boolean = false)
+ fun stopTor()
+ fun setTorStopped()
+ fun restartTor()
+}
- if (!lastKnownStatus.isStarted() && wasTorBootstrapped) {
- // If we aren't started, but we were previously bootstrapped,
- // then we handle a "restart" request as a "start" restart
- initiateTorBootstrap()
- } else {
- // |isTorRestarting| tracks the state of restart. When we receive an |OFF| state
- // from TorService in persistentBroadcastReceiver::onReceive we restart the Tor
- // service.
- isTorRestarting = true
- stopTor()
- }
- }
- private fun sendServiceAction(action: String) {
- val torServiceStatus = Intent(context, TorService::class.java)
- torServiceStatus.action = action
- context.startService(torServiceStatus)
- }
- companion object {
- const val torServiceResponseTimeout = 5000L
- }
-}
=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt
=====================================
@@ -0,0 +1,289 @@
+package org.mozilla.fenix.tor
+
+
+import android.content.Context
+import android.util.Log
+import androidx.lifecycle.LifecycleCoroutineScope
+import mozilla.components.browser.engine.gecko.GeckoEngine
+import org.mozilla.fenix.ext.components
+import org.mozilla.geckoview.TorIntegrationAndroid
+import org.mozilla.geckoview.TorIntegrationAndroid.BootstrapStateChangeListener
+import org.mozilla.geckoview.TorSettings
+import org.mozilla.geckoview.TorSettings.BridgeBuiltinType
+import org.mozilla.geckoview.TorSettings.BridgeSource
+
+// Enum matching TorConnectState from TorConnect.sys.mjs that we get from onBootstrapStateChange
+internal enum class TorConnectState(val state: String) {
+ Initial("Initial"),
+ Configuring("Configuring"),
+ AutoBootstrapping("AutoBootstrapping"),
+ Bootstrapping("Bootstrapping"),
+ Error("Error"),
+ Bootstrapped("Bootstrapped"),
+ Disabled("Disabled");
+
+ fun isStarting() = this == Bootstrapping || this == AutoBootstrapping
+ fun isError() = this == Error
+
+ fun isStarted() = this == Bootstrapped
+
+ fun isOff() = this == Initial || this == Configuring || this == Disabled || this == Error
+
+
+ // Convert to TorStatus that firefox-android uses based on tor-android-service
+ fun toTorStatus(): TorStatus {
+ return when (this) {
+ Initial -> TorStatus.OFF
+ Configuring -> TorStatus.OFF
+ AutoBootstrapping -> TorStatus.STARTING
+ Bootstrapping -> TorStatus.STARTING
+ Error -> TorStatus.UNKNOWN
+ Bootstrapped -> TorStatus.ON
+ Disabled -> TorStatus.OFF
+ }
+ }
+}
+
+class TorControllerGV(
+ private val context: Context,
+) : TorController, TorEvents, BootstrapStateChangeListener {
+
+ private val TAG = "TorControllerGV"
+
+ private var torListeners = mutableListOf<TorEvents>()
+
+ private var lastKnownStatus = TorConnectState.Initial
+ private var wasTorBootstrapped = false
+ private var isTorRestarting = false
+
+ private var isTorBootstrapped = false
+ get() = ((lastKnownStatus.isStarted()) && wasTorBootstrapped)
+
+ private val entries = mutableListOf<Pair<String?, String?>>()
+ override val logEntries get() = entries
+ override val isStarting get() = lastKnownStatus.isStarting()
+ override val isRestarting get() = isTorRestarting
+ override val isBootstrapped get() = isTorBootstrapped
+ override val isConnected get() = (lastKnownStatus.isStarted() && !isTorRestarting)
+
+ private fun getTorIntegration(): TorIntegrationAndroid {
+ return (context.components.core.engine as GeckoEngine).getTorIntegrationController()
+ }
+
+ private fun getTorSettings(): TorSettings? {
+ return getTorIntegration().getSettings()
+ }
+
+ override var bridgesEnabled: Boolean
+ get() {
+ return getTorSettings()?.bridgesEnabled ?: false
+ }
+ set(value) {
+ getTorSettings()?.let {
+ it.bridgesEnabled = value
+ getTorIntegration().setSettings(it, true, true)
+ }
+ }
+
+
+ override var bridgeTransport: TorBridgeTransportConfig
+ get() {
+ return when (getTorSettings()?.bridgesSource) {
+ BridgeSource.BuiltIn -> {
+ when (getTorSettings()?.bridgesBuiltinType) {
+ BridgeBuiltinType.Obfs4 -> TorBridgeTransportConfig.BUILTIN_OBFS4
+ BridgeBuiltinType.MeekAzure -> TorBridgeTransportConfig.BUILTIN_MEEK_AZURE
+ BridgeBuiltinType.Snowflake -> TorBridgeTransportConfig.BUILTIN_SNOWFLAKE
+ else -> TorBridgeTransportConfig.USER_PROVIDED
+ }
+
+ }
+
+ BridgeSource.UserProvided -> TorBridgeTransportConfig.USER_PROVIDED
+ else -> TorBridgeTransportConfig.USER_PROVIDED
+ }
+ }
+ set(value) {
+ getTorSettings()?.let {
+ if (value == TorBridgeTransportConfig.USER_PROVIDED) {
+ it.bridgesSource = BridgeSource.BuiltIn
+ } else {
+ val bbt: BridgeBuiltinType = when (value) {
+ TorBridgeTransportConfig.BUILTIN_OBFS4 -> BridgeBuiltinType.Obfs4
+ TorBridgeTransportConfig.BUILTIN_MEEK_AZURE -> BridgeBuiltinType.MeekAzure
+ TorBridgeTransportConfig.BUILTIN_SNOWFLAKE -> BridgeBuiltinType.Snowflake
+ else -> BridgeBuiltinType.Invalid
+ }
+ it.bridgesBuiltinType = bbt
+ }
+ getTorIntegration().setSettings(it, true, true)
+ }
+ }
+
+
+ override var userProvidedBridges: String?
+ get() {
+ return getTorSettings()?.bridgeBridgeStrings?.joinToString("\r\n")
+ }
+ set(value) {
+ getTorSettings()?.let {
+ it.bridgeBridgeStrings = value?.split("\r\n")?.toTypedArray() ?: arrayOf<String>()
+ getTorIntegration().setSettings(it, true, true)
+ }
+ }
+
+ override fun start() {
+ getTorIntegration().registerBootstrapStateChangeListener(this)
+ }
+
+ override fun stop() {
+ getTorIntegration().unregisterBootstrapStateChangeListener(this)
+ }
+
+ // TorEvents
+ override fun onTorConnecting() {
+ synchronized(torListeners) {
+ torListeners.forEach { it.onTorConnecting() }
+ }
+ }
+
+ // TorEvents
+ override fun onTorConnected() {
+ synchronized(torListeners) {
+ torListeners.forEach { it.onTorConnected() }
+ }
+ }
+
+ // TorEvents
+ override fun onTorStatusUpdate(entry: String?, status: String?) {
+ synchronized(torListeners) {
+ torListeners.forEach { it.onTorStatusUpdate(entry, status) }
+ }
+ }
+
+ // TorEvents
+ override fun onTorStopped() {
+ synchronized(torListeners) {
+ torListeners.forEach { it.onTorStopped() }
+ }
+ }
+
+ override fun registerTorListener(l: TorEvents) {
+ synchronized(torListeners) {
+ if (torListeners.contains(l)) {
+ return
+ }
+ torListeners.add(l)
+ }
+ }
+
+ override fun unregisterTorListener(l: TorEvents) {
+ synchronized(torListeners) {
+ if (!torListeners.contains(l)) {
+ return
+ }
+ torListeners.remove(l)
+ }
+ }
+
+ override fun initiateTorBootstrap(
+ lifecycleScope: LifecycleCoroutineScope?,
+ withDebugLogging: Boolean,
+ ) {
+ getTorIntegration().beginBootstrap()
+ }
+
+ override fun stopTor() {
+ getTorIntegration().cancelBootstrap()
+ }
+
+ override fun setTorStopped() {
+ lastKnownStatus = TorConnectState.Disabled
+ onTorStopped()
+ }
+
+ override fun restartTor() {
+ if (!lastKnownStatus.isStarted() && wasTorBootstrapped) {
+ // If we aren't started, but we were previously bootstrapped,
+ // then we handle a "restart" request as a "start" restart
+ initiateTorBootstrap()
+ } else {
+ // |isTorRestarting| tracks the state of restart. When we receive an |OFF| state
+ // from TorService in persistentBroadcastReceiver::onReceive we restart the Tor
+ // service.
+ isTorRestarting = true
+ stopTor()
+ }
+ }
+
+ // TorEventsBootstrapStateChangeListener -> (lastKnowStatus, TorEvents)
+ // Handle events from GeckoView TorAndroidIntegration and map to TorEvents based events
+ // and state for firefox-android (designed for tor-android-service)
+ // fun onTorConnecting()
+ // fun onTorConnected()
+ // fun onTorStatusUpdate(entry: String?, status: String?)
+ // fun onTorStopped()
+
+ // TorEventsBootstrapStateChangeListener
+ override fun onBootstrapStateChange(newStateVal: String?) {
+ Log.d(TAG, "onBootstrapStateChange($newStateVal)")
+ val newState: TorConnectState = TorConnectState.valueOf(newStateVal ?: "Error")
+
+ if (newState.isError() && wasTorBootstrapped) {
+ stopTor()
+ }
+
+ if (newState.isStarted()) {
+ wasTorBootstrapped = true
+ onTorConnected()
+ }
+
+ if (wasTorBootstrapped && newState == TorConnectState.Configuring) {
+ wasTorBootstrapped = false
+ if (isTorRestarting) {
+ initiateTorBootstrap()
+ } else {
+ onTorStopped()
+ }
+ }
+
+ if (lastKnownStatus.isOff() && newState.isStarting()) {
+ isTorRestarting = false
+ }
+
+ lastKnownStatus = newState
+
+ }
+
+ // TorEventsBootstrapStateChangeListener
+ override fun onBootstrapProgress(progress: Double, status: String?, hasWarnings: Boolean) {
+ Log.d(TAG, "onBootstrapProgress($progress, $status, $hasWarnings)")
+ if (progress == 100.0) {
+ lastKnownStatus = TorConnectState.Bootstrapped
+ wasTorBootstrapped = true
+ onTorConnected()
+ } else {
+ lastKnownStatus = TorConnectState.Bootstrapping
+ onTorConnecting()
+
+ }
+ entries.add(Pair(status, lastKnownStatus.toTorStatus().status))
+ onTorStatusUpdate(status, lastKnownStatus.toTorStatus().status)
+ }
+
+ // TorEventsBootstrapStateChangeListener
+ override fun onBootstrapComplete() {
+ lastKnownStatus = TorConnectState.Bootstrapped
+ this.onTorConnected()
+ }
+
+ // TorEventsBootstrapStateChangeListener
+ override fun onBootstrapError(message: String?, details: String?) {
+ lastKnownStatus = TorConnectState.Error
+ }
+
+ // TorEventsBootstrapStateChangeListener
+ override fun onSettingsRequested() {
+ // noop
+ }
+}
=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt
=====================================
@@ -0,0 +1,332 @@
+package org.mozilla.fenix.tor
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import androidx.lifecycle.LifecycleCoroutineScope
+import androidx.localbroadcastmanager.content.LocalBroadcastManager
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withTimeoutOrNull
+import org.mozilla.fenix.BuildConfig
+import org.torproject.android.service.TorService
+import org.torproject.android.service.TorServiceConstants
+import org.torproject.android.service.util.Prefs
+
+@SuppressWarnings("TooManyFunctions")
+class TorControllerTAS (private val context: Context): TorController {
+ private val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context)
+ private val entries = mutableListOf<Pair<String?, String?>>()
+ override val logEntries get() = entries
+
+ private var torListeners = mutableListOf<TorEvents>()
+
+ private var pendingRegisterChangeList = mutableListOf<Pair<TorEvents, Boolean>>()
+ private var lockTorListenersMutation = false
+
+ private var lastKnownStatus = TorStatus.OFF
+ private var wasTorBootstrapped = false
+ private var isTorRestarting = false
+
+ // This may be a lie
+ private var isTorBootstrapped = false
+ get() = ((lastKnownStatus == TorStatus.ON) && wasTorBootstrapped)
+
+ val isDebugLoggingEnabled get() =
+ context
+ .getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE)
+ .getBoolean("pref_enable_logging", false)
+
+ override val isStarting get() = lastKnownStatus.isStarting()
+ override val isRestarting get() = isTorRestarting
+ override val isBootstrapped get() = isTorBootstrapped
+ override val isConnected get() = (lastKnownStatus.isStarted() && !isTorRestarting)
+
+ override var bridgesEnabled: Boolean
+ get() = Prefs.bridgesEnabled()
+ set(value) { Prefs.putBridgesEnabled(value) }
+
+ override var bridgeTransport: TorBridgeTransportConfig
+ get() {
+ return TorBridgeTransportConfigUtil.getStringToBridgeTransport(
+ Prefs.getBridgesList()
+ )
+ }
+ set(value) {
+ if (value == TorBridgeTransportConfig.USER_PROVIDED) {
+ // Don't set the pref when the value is USER_PROVIDED because
+ // "user_provided" is not a valid bridge or transport type.
+ // This call should be followed by setting userProvidedBridges.
+ return
+ }
+ Prefs.setBridgesList(value.transportName)
+ }
+
+ override var userProvidedBridges: String?
+ get() {
+ val bridges = Prefs.getBridgesList()
+ val bridgeType =
+ TorBridgeTransportConfigUtil.getStringToBridgeTransport(bridges)
+ return when (bridgeType) {
+ TorBridgeTransportConfig.USER_PROVIDED -> bridges
+ else -> null
+ }
+ }
+ set(value) {
+ Prefs.setBridgesList(value)
+ }
+
+ override fun start() {
+ // Register receiver
+ lbm.registerReceiver(
+ persistentBroadcastReceiver,
+ IntentFilter(TorServiceConstants.ACTION_STATUS)
+ )
+ lbm.registerReceiver(
+ persistentBroadcastReceiver,
+ IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)
+ )
+ }
+
+ override fun stop() {
+ lbm.unregisterReceiver(persistentBroadcastReceiver)
+ }
+
+ private val persistentBroadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ if (intent.action == null ||
+ (intent.action != TorServiceConstants.ACTION_STATUS &&
+ intent.action != TorServiceConstants.LOCAL_ACTION_LOG)
+ ) {
+ return
+ }
+ val action = intent.action
+
+ val logentry: String?
+ val status: String?
+ if (action == TorServiceConstants.LOCAL_ACTION_LOG) {
+ logentry = intent.getExtras()
+ ?.getCharSequence(TorServiceConstants.LOCAL_EXTRA_LOG) as? String?
+ } else {
+ logentry = null
+ }
+
+ status = intent.getExtras()
+ ?.getCharSequence(TorServiceConstants.EXTRA_STATUS) as? String?
+
+ if (logentry == null && status == null) {
+ return
+ }
+
+ onTorStatusUpdate(logentry, status)
+
+ if (status == null) {
+ return
+ }
+
+ val newStatus = TorStatus.fromString(status)
+
+ if (newStatus.isUnknown() && wasTorBootstrapped) {
+ stopTor()
+ }
+
+ entries.add(Pair(logentry, status))
+
+ if (logentry != null && logentry.contains(TorServiceConstants.TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)) {
+ wasTorBootstrapped = true
+ onTorConnected()
+ }
+
+ if (lastKnownStatus.isStopping() && newStatus.isOff()) {
+ if (isTorRestarting) {
+ initiateTorBootstrap()
+ } else {
+ onTorStopped()
+ }
+ }
+
+ if (lastKnownStatus.isOff() && newStatus.isStarting()) {
+ isTorRestarting = false
+ }
+
+ lastKnownStatus = newStatus
+ }
+ }
+
+ override fun onTorConnecting() {
+ lockTorListenersMutation = true
+ torListeners.forEach { it.onTorConnecting() }
+ lockTorListenersMutation = false
+
+ handlePendingRegistrationChanges()
+ }
+
+ override fun onTorConnected() {
+ lockTorListenersMutation = true
+ torListeners.forEach { it.onTorConnected() }
+ lockTorListenersMutation = false
+
+ handlePendingRegistrationChanges()
+ }
+
+ override fun onTorStatusUpdate(entry: String?, status: String?) {
+ lockTorListenersMutation = true
+ torListeners.forEach { it.onTorStatusUpdate(entry, status) }
+ lockTorListenersMutation = false
+
+ handlePendingRegistrationChanges()
+ }
+
+ override fun onTorStopped() {
+ lockTorListenersMutation = true
+ torListeners.forEach { it.onTorStopped() }
+ lockTorListenersMutation = false
+
+ handlePendingRegistrationChanges()
+ }
+
+ override fun registerTorListener(l: TorEvents) {
+ if (torListeners.contains(l)) {
+ return
+ }
+
+ if (lockTorListenersMutation) {
+ pendingRegisterChangeList.add(Pair(l, true))
+ } else {
+ torListeners.add(l)
+ }
+ }
+
+ override fun unregisterTorListener(l: TorEvents) {
+ if (!torListeners.contains(l)) {
+ return
+ }
+
+ if (lockTorListenersMutation) {
+ pendingRegisterChangeList.add(Pair(l, false))
+ } else {
+ torListeners.remove(l)
+ }
+ }
+
+ private fun handlePendingRegistrationChanges() {
+ pendingRegisterChangeList.forEach {
+ if (it.second) {
+ registerTorListener(it.first)
+ } else {
+ unregisterTorListener(it.first)
+ }
+ }
+
+ pendingRegisterChangeList.clear()
+ }
+
+ /**
+ * Receive the current Tor status.
+ *
+ * Send a request for the current status and receive the response.
+ * Returns true if Tor is running, false otherwise.
+ *
+ */
+ private suspend fun checkTorIsStarted(): Boolean {
+ val channel = Channel<Boolean>()
+
+ // Register receiver
+ val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context)
+ val localBroadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val action = intent.action ?: return
+ // We only want ACTION_STATUS messages
+ if (action != TorServiceConstants.ACTION_STATUS) {
+ return
+ }
+ // The current status has the EXTRA_STATUS key
+ val currentStatus =
+ intent.getStringExtra(TorServiceConstants.EXTRA_STATUS)
+ channel.trySend(currentStatus === TorServiceConstants.STATUS_ON)
+ }
+ }
+ lbm.registerReceiver(
+ localBroadcastReceiver,
+ IntentFilter(TorServiceConstants.ACTION_STATUS)
+ )
+
+ // Request service status
+ sendServiceAction(TorServiceConstants.ACTION_STATUS)
+
+ // Wait for response and unregister receiver
+ var torIsStarted = false
+ withTimeoutOrNull(torServiceResponseTimeout) {
+ torIsStarted = channel.receive()
+ }
+ lbm.unregisterReceiver(localBroadcastReceiver)
+ return torIsStarted
+ }
+
+ override fun initiateTorBootstrap(lifecycleScope: LifecycleCoroutineScope?, withDebugLogging: Boolean) {
+ if (BuildConfig.DISABLE_TOR) {
+ return
+ }
+
+ context.getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE)
+ .edit().putBoolean("pref_enable_logging", withDebugLogging).apply()
+
+ if (lifecycleScope == null) {
+ sendServiceAction(TorServiceConstants.ACTION_START)
+ } else {
+ lifecycleScope.launch {
+ val torNeedsStart = !checkTorIsStarted()
+ if (torNeedsStart) {
+ sendServiceAction(TorServiceConstants.ACTION_START)
+ }
+ }
+ }
+ }
+
+ override fun stopTor() {
+ if (BuildConfig.DISABLE_TOR) {
+ return
+ }
+
+ val torService = Intent(context, TorService::class.java)
+ context.stopService(torService)
+ }
+
+ override fun setTorStopped() {
+ lastKnownStatus = TorStatus.OFF
+ onTorStopped()
+ }
+
+ override fun restartTor() {
+ // tor-android-service doesn't dynamically update the torrc file,
+ // and it doesn't use SETCONF, so we completely restart the service.
+ // However, don't restart if we aren't started and we weren't
+ // previously started.
+ if (!lastKnownStatus.isStarted() && !wasTorBootstrapped) {
+ return
+ }
+
+ if (!lastKnownStatus.isStarted() && wasTorBootstrapped) {
+ // If we aren't started, but we were previously bootstrapped,
+ // then we handle a "restart" request as a "start" restart
+ initiateTorBootstrap()
+ } else {
+ // |isTorRestarting| tracks the state of restart. When we receive an |OFF| state
+ // from TorService in persistentBroadcastReceiver::onReceive we restart the Tor
+ // service.
+ isTorRestarting = true
+ stopTor()
+ }
+ }
+
+ private fun sendServiceAction(action: String) {
+ val torServiceStatus = Intent(context, TorService::class.java)
+ torServiceStatus.action = action
+ context.startService(torServiceStatus)
+ }
+
+ companion object {
+ const val torServiceResponseTimeout = 5000L
+ }
+}
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/6d0…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/6d0…
You're receiving this email because of your account on gitlab.torproject.org.
1
0
[Git][tpo/applications/tor-browser][tor-browser-115.7.0esr-13.5-1] 2 commits: fixup! Bug 40597: Implement TorSettings module
by Pier Angelo Vendrame (@pierov) 25 Jan '24
by Pier Angelo Vendrame (@pierov) 25 Jan '24
25 Jan '24
Pier Angelo Vendrame pushed to branch tor-browser-115.7.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
f49834e2 by Dan Ballard at 2024-01-25T17:05:18+00:00
fixup! Bug 40597: Implement TorSettings module
Bug 42252: Fix typo in documents
- - - - -
db59cb25 by Dan Ballard at 2024-01-25T17:05:18+00:00
fixup! Bug 42247: Android helpers for the TorProvider
Bug 42252: Add support for TorController in firefox-android
- - - - -
4 changed files:
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java
- toolkit/modules/TorSettings.sys.mjs
Changes:
=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
=====================================
@@ -82,6 +82,10 @@ public class TorIntegrationAndroid implements BundleEventListener {
private final HashMap<Integer, MeekTransport> mMeeks = new HashMap<>();
private int mMeekCounter;
+ // mSettings is a java side copy of the authoritative settings in the JS code.
+ // it's useful to maintain as the ui may be fetching these options often and
+ // we don't watch each fetch to be a passthrough to JS with JSON serialization and
+ // deserialization each time
private TorSettings mSettings = null;
/* package */ TorIntegrationAndroid(Context context) {
@@ -557,11 +561,38 @@ public class TorIntegrationAndroid implements BundleEventListener {
void onSettingsRequested();
}
- public @NonNull GeckoResult<GeckoBundle> getSettings() {
- return EventDispatcher.getInstance().queryBundle(EVENT_SETTINGS_GET);
+ private @NonNull void reloadSettings() {
+ EventDispatcher.getInstance().queryBundle(EVENT_SETTINGS_GET).then( new GeckoResult.OnValueListener<GeckoBundle, Void>() {
+ public GeckoResult<Void> onValue(final GeckoBundle bundle) {
+ mSettings = new TorSettings(bundle);
+ return new GeckoResult<Void>();
+ }
+ });
+ }
+
+ public TorSettings getSettings() {
+ return mSettings;
+ }
+
+ public void setSettings(final TorSettings settings, boolean save, boolean apply) {
+ mSettings = settings;
+
+ emitSetSettings(settings, save, apply).then(
+ new GeckoResult.OnValueListener<Void, Void>() {
+ public GeckoResult<Void> onValue(Void v) {
+ return new GeckoResult<Void>();
+ }
+ },
+ new GeckoResult.OnExceptionListener<Void>() {
+ public GeckoResult<Void> onException(final Throwable e) {
+ Log.e(TAG, "Failed to set settings", e);
+ reloadSettings();
+ return new GeckoResult<Void>();
+ }
+ });
}
- public @NonNull GeckoResult<Void> setSettings(final TorSettings settings, boolean save, boolean apply) {
+ private @NonNull GeckoResult<Void> emitSetSettings(final TorSettings settings, boolean save, boolean apply) {
GeckoBundle bundle = new GeckoBundle(3);
bundle.putBoolean("save", save);
bundle.putBoolean("apply", apply);
=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java
=====================================
@@ -2,24 +2,8 @@ package org.mozilla.geckoview;
import android.util.Log;
-import org.json.JSONArray;
-import org.json.JSONObject;
import org.mozilla.gecko.util.GeckoBundle;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.io.SequenceInputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-import java.util.stream.Collectors;
-
public class TorSettings {
public enum BridgeSource {
@@ -76,6 +60,35 @@ public class TorSettings {
}
}
+ public enum BridgeBuiltinType {
+ /* TorSettings.sys.mjs ~ln43: string: obfs4|meek-azure|snowflake|etc */
+ Invalid("invalid"),
+ Obfs4("obfs4"),
+ MeekAzure("meek-azure"),
+ Snowflake("snowflake");
+
+
+ private String type;
+
+ BridgeBuiltinType(String type) {
+ this.type = type;
+ }
+
+ public String toString() {
+ return type;
+ }
+
+ public static BridgeBuiltinType fromString(String s) {
+ switch (s) {
+ case "obfs4": return Obfs4;
+ case "meek-azure": return MeekAzure;
+ case "snowflake": return Snowflake;
+ }
+ return Invalid;
+ }
+
+ }
+
private boolean loaded = false;
public boolean enabled = true;
@@ -85,7 +98,7 @@ public class TorSettings {
// bridges section
public boolean bridgesEnabled = false;
public BridgeSource bridgesSource = BridgeSource.Invalid;
- public String bridgesBuiltinType = "";
+ public BridgeBuiltinType bridgesBuiltinType = BridgeBuiltinType.Invalid;
public String[] bridgeBridgeStrings;
// proxy section
@@ -112,7 +125,7 @@ public class TorSettings {
bridgesEnabled = bridges.getBoolean("enabled");
bridgesSource = BridgeSource.fromInt(bridges.getInt("source"));
- bridgesBuiltinType = bridges.getString("builtin_type");
+ bridgesBuiltinType = BridgeBuiltinType.fromString(bridges.getString("builtin_type"));
bridgeBridgeStrings = bridges.getStringArray("bridge_strings");
quickstart = qs.getBoolean("enabled");
@@ -143,7 +156,7 @@ public class TorSettings {
bridges.putBoolean("enabled", bridgesEnabled);
bridges.putInt("source", bridgesSource.toInt());
- bridges.putString("builtin_type", bridgesBuiltinType);
+ bridges.putString("builtin_type", bridgesBuiltinType.toString());
bridges.putStringArray("bridge_strings", bridgeBridgeStrings);
qs.putBoolean("enabled", quickstart);
=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java
=====================================
@@ -1,11 +1,5 @@
package org.mozilla.geckoview.androidlegacysettings;
-import java.io.IOException;
-
-import android.content.SharedPreferences;
-
-import org.mozilla.gecko.GeckoAppShell;
-
import org.mozilla.geckoview.TorSettings;
public class TorLegacyAndroidSettings {
@@ -54,10 +48,10 @@ public class TorLegacyAndroidSettings {
switch (userDefinedBridgeList) {
case "obfs4":
case "snowflake":
- settings.bridgesBuiltinType = userDefinedBridgeList;
+ settings.bridgesBuiltinType = TorSettings.BridgeBuiltinType.fromString(userDefinedBridgeList);
break;
case "meek":
- settings.bridgesBuiltinType = "meek-azure";
+ settings.bridgesBuiltinType = TorSettings.BridgeBuiltinType.MeekAzure;
break;
default:
settings.bridgesSource = TorSettings.BridgeSource.Invalid;
=====================================
toolkit/modules/TorSettings.sys.mjs
=====================================
@@ -40,7 +40,7 @@ const TorSettingsPrefs = Object.freeze({
enabled: "torbrowser.settings.bridges.enabled",
/* int: See TorBridgeSource */
source: "torbrowser.settings.bridges.source",
- /* string: obfs4|meek_azure|snowflake|etc */
+ /* string: obfs4|meek-azure|snowflake|etc */
builtin_type: "torbrowser.settings.bridges.builtin_type",
/* preference branch: each child branch should be a bridge string */
bridge_strings: "torbrowser.settings.bridges.bridge_strings",
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/308d6a…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/308d6a…
You're receiving this email because of your account on gitlab.torproject.org.
1
0
[Git][tpo/applications/tor-browser][tor-browser-115.7.0esr-13.5-1] fixup! Bug 42247: Android helpers for the TorProvider
by Pier Angelo Vendrame (@pierov) 25 Jan '24
by Pier Angelo Vendrame (@pierov) 25 Jan '24
25 Jan '24
Pier Angelo Vendrame pushed to branch tor-browser-115.7.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
308d6a64 by Pier Angelo Vendrame at 2024-01-25T17:44:22+01:00
fixup! Bug 42247: Android helpers for the TorProvider
Bug 42368: Do not use API26+ java.nio features
- - - - -
1 changed file:
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
Changes:
=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
=====================================
@@ -16,15 +16,10 @@ import androidx.annotation.Nullable;
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.nio.file.attribute.PosixFilePermission;
-import java.nio.file.attribute.PosixFilePermissions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -69,9 +64,9 @@ public class TorIntegrationAndroid implements BundleEventListener {
private static final String COOKIE_AUTH_FILE = "/auth-file";
private final String mLibraryDir;
- private final Path mCacheDir;
+ private final String mCacheDir;
private final String mIpcDirectory;
- private final String mDataDir;
+ private final File mDataDir;
private TorProcess mTorProcess = null;
/**
@@ -91,9 +86,9 @@ public class TorIntegrationAndroid implements BundleEventListener {
/* package */ TorIntegrationAndroid(Context context) {
mLibraryDir = context.getApplicationInfo().nativeLibraryDir;
- mCacheDir = context.getCacheDir().toPath();
+ mCacheDir = context.getCacheDir().getAbsolutePath();
mIpcDirectory = mCacheDir + "/tor-private";
- mDataDir = context.getDataDir().getAbsolutePath() + "/tor";
+ mDataDir = new File(context.getFilesDir(), "tor");
registerListener();
}
@@ -260,7 +255,7 @@ public class TorIntegrationAndroid implements BundleEventListener {
args.add("CookieAuthFile");
args.add(ipcDir + COOKIE_AUTH_FILE);
args.add("DataDirectory");
- args.add(mDataDir);
+ args.add(mDataDir.getAbsolutePath());
boolean copied = true;
try {
copyAndUseConfigFile("--defaults-torrc", "torrc-defaults", args);
@@ -322,15 +317,19 @@ public class TorIntegrationAndroid implements BundleEventListener {
private void cleanIpcDirectory() {
File directory = new File(TorIntegrationAndroid.this.mIpcDirectory);
- if (!Files.isDirectory(directory.toPath())) {
+ if (!directory.isDirectory()) {
if (!directory.mkdirs()) {
Log.e(TAG, "Failed to create the IPC directory.");
return;
}
try {
- Set<PosixFilePermission> chmod = PosixFilePermissions.fromString("rwx------");
- Files.setPosixFilePermissions(directory.toPath(), chmod);
- } catch (IOException e) {
+ directory.setReadable(false, false);
+ directory.setReadable(true, true);
+ directory.setWritable(false, false);
+ directory.setWritable(true, true);
+ directory.setExecutable(false, false);
+ directory.setExecutable(true, true);
+ } catch (SecurityException e) {
Log.e(TAG, "Could not set the permissions to the IPC directory.", e);
}
return;
@@ -347,15 +346,46 @@ public class TorIntegrationAndroid implements BundleEventListener {
}
private void copyAndUseConfigFile(String option, String name, ArrayList<String> args) throws IOException {
- final Path path = Paths.get(mCacheDir.toFile().getAbsolutePath(), name);
- if (!mCopiedConfigFiles || !path.toFile().exists()) {
- final Context context = GeckoAppShell.getApplicationContext();
- final InputStream in = context.getAssets().open("common/" + name);
- Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);
+ File file = copyConfigFile(name);
+ args.add(option);
+ args.add(file.getAbsolutePath());
+ }
+
+ private File copyConfigFile(String name) throws IOException {
+ final File file = new File(mCacheDir, name);
+ if (mCopiedConfigFiles && file.exists()) {
+ return file;
+ }
+
+ final Context context = GeckoAppShell.getApplicationContext();
+ final InputStream in = context.getAssets().open("common/" + name);
+ // Files.copy is API 26+, so use java.io and a loop for now.
+ FileOutputStream out = null;
+ try {
+ out = new FileOutputStream(file);
+ } catch (IOException e) {
in.close();
+ throw e;
}
- args.add(option);
- args.add(path.toString());
+ try {
+ byte buffer[] = new byte[4096];
+ int read;
+ while ((read = in.read(buffer)) >= 0) {
+ out.write(buffer, 0, read);
+ }
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Cannot close the input stream for " + name);
+ }
+ try {
+ out.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Cannot close the output stream for " + name);
+ }
+ }
+ return file;
}
public void shutdown() {
@@ -406,9 +436,10 @@ public class TorIntegrationAndroid implements BundleEventListener {
setName("meek-" + id);
final ProcessBuilder builder = new ProcessBuilder(mLibraryDir + "/libObfs4proxy.so");
{
+ File ptStateDir = new File(mDataDir, "pt_state");
final Map<String, String> env = builder.environment();
env.put("TOR_PT_MANAGED_TRANSPORT_VER", "1");
- env.put("TOR_PT_STATE_LOCATION", mDataDir + "/pt_state");
+ env.put("TOR_PT_STATE_LOCATION", ptStateDir.getAbsolutePath());
env.put("TOR_PT_EXIT_ON_STDIN_CLOSE", "1");
env.put("TOR_PT_CLIENT_TRANSPORTS", TRANSPORT);
}
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/308d6a6…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/308d6a6…
You're receiving this email because of your account on gitlab.torproject.org.
1
0
[Git][tpo/applications/rbm][main] Bug 40068: Use Capture::Tiny instead of IO::CaptureOutput
by richard (@richard) 25 Jan '24
by richard (@richard) 25 Jan '24
25 Jan '24
richard pushed to branch main at The Tor Project / Applications / RBM
Commits:
9336d42f by Nicolas Vigier at 2024-01-25T11:42:58+01:00
Bug 40068: Use Capture::Tiny instead of IO::CaptureOutput
The IO::CaptureOutput perl module is deprecated, so we switch to
Capture::Tiny.
The Capture::Tiny module does not provide a capture_exec function
similar to the one from IO::CaptureOutput, so we implement one using the
same name, which avoids changing all the places where we were using it.
- - - - -
2 changed files:
- lib/RBM.pm
- lib/RBM/DefaultConfig.pm
Changes:
=====================================
lib/RBM.pm
=====================================
@@ -10,7 +10,7 @@ use YAML::XS qw(LoadFile);
use Template;
use File::Basename;
use IO::Handle;
-use IO::CaptureOutput qw(capture_exec);
+use Capture::Tiny qw(capture);
use File::Temp;
use File::Copy;
use File::Copy::Recursive qw(fcopy);
@@ -29,7 +29,7 @@ use feature "state";
BEGIN {
require Exporter;
our @ISA = qw(Exporter);
- our @EXPORT = qw(exit_error);
+ our @EXPORT = qw(exit_error capture_exec);
}
our $config;
@@ -308,6 +308,15 @@ sub exit_error {
exit (exists $_[1] ? $_[1] : 1);
}
+sub capture_exec {
+ my @cmd = @_;
+ my ($stdout, $stderr, $exit) = capture {
+ system(@cmd);
+ };
+ return ($stdout, $stderr, $exit == 0, $exit) if wantarray();
+ return $stdout;
+}
+
sub set_git_gpg_wrapper {
my ($project) = @_;
my $w = project_config($project, 'gpg_wrapper');
=====================================
lib/RBM/DefaultConfig.pm
=====================================
@@ -10,9 +10,8 @@ BEGIN {
}
use File::Basename;
-use RBM;
+use RBM qw(capture_exec);
use Cwd qw(getcwd);
-use IO::CaptureOutput qw(capture_exec);
use File::Temp;
use File::Path qw(make_path);
View it on GitLab: https://gitlab.torproject.org/tpo/applications/rbm/-/commit/9336d42fdd669af…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/rbm/-/commit/9336d42fdd669af…
You're receiving this email because of your account on gitlab.torproject.org.
1
0
[Git][tpo/applications/tor-browser-build][maint-13.0] Update rbm for rbm#40067
by boklm (@boklm) 25 Jan '24
by boklm (@boklm) 25 Jan '24
25 Jan '24
boklm pushed to branch maint-13.0 at The Tor Project / Applications / tor-browser-build
Commits:
af1c78b5 by Nicolas Vigier at 2024-01-25T11:19:16+01:00
Update rbm for rbm#40067
- - - - -
1 changed file:
- rbm
Changes:
=====================================
rbm
=====================================
@@ -1 +1 @@
-Subproject commit 40acf540fe75055df2eb78454f070f57d0804729
+Subproject commit b5e5b04aaf677c4bacfb5ace45598313286bfdf6
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/a…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/a…
You're receiving this email because of your account on gitlab.torproject.org.
1
0
[Git][tpo/applications/tor-browser-build][main] Update rbm for rbm#40067
by boklm (@boklm) 25 Jan '24
by boklm (@boklm) 25 Jan '24
25 Jan '24
boklm pushed to branch main at The Tor Project / Applications / tor-browser-build
Commits:
83a1a381 by Nicolas Vigier at 2024-01-25T11:17:52+01:00
Update rbm for rbm#40067
- - - - -
1 changed file:
- rbm
Changes:
=====================================
rbm
=====================================
@@ -1 +1 @@
-Subproject commit 40acf540fe75055df2eb78454f070f57d0804729
+Subproject commit b5e5b04aaf677c4bacfb5ace45598313286bfdf6
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/8…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/8…
You're receiving this email because of your account on gitlab.torproject.org.
1
0
[Git][tpo/applications/tor-browser][tor-browser-115.7.0esr-13.0-1] fixup! Bug 41668: Tweaks to the Base Browser updater for Tor Browser
by boklm (@boklm) 25 Jan '24
by boklm (@boklm) 25 Jan '24
25 Jan '24
boklm pushed to branch tor-browser-115.7.0esr-13.0-1 at The Tor Project / Applications / Tor Browser
Commits:
6292bbc9 by Nicolas Vigier at 2024-01-25T10:26:11+01:00
fixup! Bug 41668: Tweaks to the Base Browser updater for Tor Browser
Bug 42293: Don't disable updater when run by torbrowser-launcher flatpak
When the TORBROWSER_LAUNCHER environment variable is set (which
is set by torbrowser-launcher since version 0.3.7) we assume that Tor
Browser is not installed by a Flatkpak. Although torbrowser-launcher
itself can be installed by a Flatpak, this should not prevent the
updater from working.
- - - - -
1 changed file:
- widget/gtk/WidgetUtilsGtk.cpp
Changes:
=====================================
widget/gtk/WidgetUtilsGtk.cpp
=====================================
@@ -138,6 +138,11 @@ void SetLastMousePressEvent(GdkEvent* aEvent) {
bool IsRunningUnderSnap() { return !!GetSnapInstanceName(); }
bool IsRunningUnderFlatpak() {
+ // tor-browser#42293: Don't disable updater when run by torbrowser-launcher flatpak
+ const char* torbrowserLauncher = g_getenv("TORBROWSER_LAUNCHER");
+ if (torbrowserLauncher) {
+ return false;
+ }
// https://gitlab.gnome.org/GNOME/gtk/-/blob/4300a5c609306ce77cbc8a3580c19201d…
static bool sRunning = [] {
return g_file_test("/.flatpak-info", G_FILE_TEST_EXISTS);
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/6292bbc…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/6292bbc…
You're receiving this email because of your account on gitlab.torproject.org.
1
0
[Git][tpo/applications/tor-browser][tor-browser-115.7.0esr-13.5-1] fixup! Bug 41668: Tweaks to the Base Browser updater for Tor Browser
by boklm (@boklm) 25 Jan '24
by boklm (@boklm) 25 Jan '24
25 Jan '24
boklm pushed to branch tor-browser-115.7.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
5898a9ab by Nicolas Vigier at 2024-01-25T10:21:48+01:00
fixup! Bug 41668: Tweaks to the Base Browser updater for Tor Browser
Bug 42293: Don't disable updater when run by torbrowser-launcher flatpak
When the TORBROWSER_LAUNCHER environment variable is set (which
is set by torbrowser-launcher since version 0.3.7) we assume that Tor
Browser is not installed by a Flatkpak. Although torbrowser-launcher
itself can be installed by a Flatpak, this should not prevent the
updater from working.
- - - - -
1 changed file:
- widget/gtk/WidgetUtilsGtk.cpp
Changes:
=====================================
widget/gtk/WidgetUtilsGtk.cpp
=====================================
@@ -138,6 +138,11 @@ void SetLastMousePressEvent(GdkEvent* aEvent) {
bool IsRunningUnderSnap() { return !!GetSnapInstanceName(); }
bool IsRunningUnderFlatpak() {
+ // tor-browser#42293: Don't disable updater when run by torbrowser-launcher flatpak
+ const char* torbrowserLauncher = g_getenv("TORBROWSER_LAUNCHER");
+ if (torbrowserLauncher) {
+ return false;
+ }
// https://gitlab.gnome.org/GNOME/gtk/-/blob/4300a5c609306ce77cbc8a3580c19201d…
static bool sRunning = [] {
return g_file_test("/.flatpak-info", G_FILE_TEST_EXISTS);
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/5898a9a…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/5898a9a…
You're receiving this email because of your account on gitlab.torproject.org.
1
0
[Git][tpo/applications/tor-browser][tor-browser-115.7.0esr-13.5-1] 3 commits: fixup! Bug 31286: Implementation of bridge, proxy, and firewall settings in...
by richard (@richard) 24 Jan '24
by richard (@richard) 24 Jan '24
24 Jan '24
richard pushed to branch tor-browser-115.7.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
47afbf56 by Henry Wilkes at 2024-01-23T20:27:35+00:00
fixup! Bug 31286: Implementation of bridge, proxy, and firewall settings in about:preferences#connection
Bug 42036: Replace replace/add bridges section with new design, ready
for Lox.
- - - - -
0021e3f3 by Henry Wilkes at 2024-01-23T20:27:36+00:00
fixup! Tor Browser strings
Bug 42036: Add strings for adding/replacing bridges.
- - - - -
c1bcea9d by Henry Wilkes at 2024-01-23T20:27:36+00:00
fixup! Add TorStrings module for localization
Bug 42036: Remove old strings for replacing bridges.
- - - - -
11 changed files:
- + browser/components/torpreferences/content/bridge-bot.svg
- browser/components/torpreferences/content/connectionPane.js
- browser/components/torpreferences/content/connectionPane.xhtml
- browser/components/torpreferences/content/provideBridgeDialog.js
- browser/components/torpreferences/content/provideBridgeDialog.xhtml
- + browser/components/torpreferences/content/telegram-logo.svg
- browser/components/torpreferences/content/torPreferences.css
- browser/components/torpreferences/jar.mn
- browser/locales/en-US/browser/tor-browser.ftl
- toolkit/modules/TorStrings.sys.mjs
- toolkit/torbutton/chrome/locale/en-US/settings.properties
Changes:
=====================================
browser/components/torpreferences/content/bridge-bot.svg
=====================================
@@ -0,0 +1,13 @@
+<svg width="40" height="44" viewBox="0 0 40 44" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M37.1877 22.7584C38.7409 25.1504 38.9178 27.7923 37.5828 28.6591C36.2478 29.5259 33.9065 28.2895 32.3533 25.8975C30.8001 23.5055 30.6232 20.8637 31.9582 19.9969C33.2932 19.13 35.6345 20.3664 37.1877 22.7584Z" fill="#C069FF"/>
+<path d="M2.81234 22.7584C1.25915 25.1504 1.08224 27.7923 2.41721 28.6591C3.75217 29.5259 6.09349 28.2895 7.64668 25.8975C9.19987 23.5055 9.37678 20.8637 8.04181 19.9969C6.70685 19.13 4.36553 20.3664 2.81234 22.7584Z" fill="#C069FF"/>
+<path d="M32.2002 19.4754C33.9149 19.4754 35.3181 20.8678 35.1823 22.5772C34.7579 27.9186 33.2458 32.9181 30.8541 36.7668C28.0043 41.3527 24.1391 43.9291 20.1088 43.9291C16.0785 43.9291 12.2133 41.3527 9.36344 36.7668C6.97177 32.9181 5.45965 27.9186 5.03525 22.5772C4.89944 20.8678 6.30265 19.4754 8.0174 19.4754L32.2002 19.4754Z" fill="#C069FF"/>
+<path d="M28.4375 32.1121C28.4375 27.4522 24.6599 23.6746 20 23.6746C15.3401 23.6746 11.5625 27.4522 11.5625 32.1121V33.5139H12.8809V32.1121C12.8809 28.1803 16.0682 24.9929 20 24.9929C23.9318 24.9929 27.1191 28.1803 27.1191 32.1121V33.5139H28.4375V32.1121Z" fill="#15141A"/>
+<path d="M25.9062 32.1121C25.9062 28.8501 23.2619 26.2058 20 26.2058C16.7381 26.2058 14.0937 28.8501 14.0937 32.1121L14.0936 33.5139H15.412L15.4121 32.1121C15.4121 29.5782 17.4662 27.5242 20 27.5242C22.5338 27.5242 24.5879 29.5782 24.5879 32.1121L24.588 33.5139H25.9064L25.9062 32.1121Z" fill="#15141A"/>
+<path d="M20 28.7371C21.864 28.7371 23.375 30.2481 23.375 32.1121L23.3753 33.5139H22.0569L22.0566 32.1121C22.0566 30.9762 21.1359 30.0554 20 30.0554C18.8642 30.0554 17.9434 30.9762 17.9434 32.1121L17.9431 33.5139H16.6247V32.1121C16.6247 30.2481 18.136 28.7371 20 28.7371Z" fill="#15141A"/>
+<path d="M8.9145 17.8162C7.19975 17.8162 5.78665 16.4193 6.02668 14.7215C6.53221 11.1456 7.9061 7.82078 9.99195 5.21826C12.6698 1.87706 16.3018 -1.07451e-07 20.0889 0C23.8759 1.07451e-07 27.5079 1.87706 30.1858 5.21826C32.2716 7.82078 33.6455 11.1456 34.151 14.7215C34.3911 16.4193 32.978 17.8162 31.2632 17.8162H8.9145Z" fill="#C069FF"/>
+<path d="M13.1064 15.1091C11.3916 15.1091 9.96814 13.7048 10.3139 12.0252C10.7578 9.86855 11.6634 7.87853 12.956 6.27814C14.8477 3.93602 17.4134 2.62024 20.0887 2.62024C22.7639 2.62024 25.3296 3.93602 27.2213 6.27814C28.514 7.87853 29.4195 9.86855 29.8635 12.0252C30.2092 13.7048 28.7857 15.1091 27.071 15.1091H13.1064Z" fill="#EBD0FF"/>
+<path d="M17.5125 6.81215C17.5125 7.58388 16.9065 8.2095 16.1589 8.2095C15.4112 8.2095 14.8052 7.58388 14.8052 6.81215C14.8052 6.04041 15.4112 5.41479 16.1589 5.41479C16.9065 5.41479 17.5125 6.04041 17.5125 6.81215Z" fill="#15141A"/>
+<path d="M25.1981 6.81215C25.1981 7.58388 24.592 8.2095 23.8444 8.2095C23.0968 8.2095 22.4907 7.58388 22.4907 6.81215C22.4907 6.04041 23.0968 5.41479 23.8444 5.41479C24.592 5.41479 25.1981 6.04041 25.1981 6.81215Z" fill="#15141A"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M22.4395 9.01993L22.4044 9.11353C21.5971 11.2673 18.526 11.1951 17.8208 9.0058L18.427 8.81052C18.9472 10.4254 21.2125 10.4787 21.808 8.88998L21.8431 8.79639L22.4395 9.01993Z" fill="#15141A"/>
+</svg>
=====================================
browser/components/torpreferences/content/connectionPane.js
=====================================
@@ -1316,6 +1316,18 @@ const gBridgeSettings = {
* @type {Element?}
*/
_noBridgesEl: null,
+ /**
+ * The heading element for changing bridges.
+ *
+ * @type {Element?}
+ */
+ _changeHeadingEl: null,
+ /**
+ * The button for user to provide a bridge address or share code.
+ *
+ * @type {Element?}
+ */
+ _userProvideButton: null,
/**
* Initialize the bridge settings.
@@ -1345,6 +1357,47 @@ const gBridgeSettings = {
});
});
+ this._changeHeadingEl = document.getElementById(
+ "tor-bridges-change-heading"
+ );
+ this._userProvideButton = document.getElementById(
+ "tor-bridges-open-user-provide-dialog-button"
+ );
+
+ document.l10n.setAttributes(
+ document.getElementById("tor-bridges-user-provide-description"),
+ // TODO: Set a different string if we have Lox enabled.
+ "tor-bridges-add-addresses-description"
+ );
+
+ // TODO: Change to GetLoxBridges if Lox enabled, and the account is set up.
+ const telegramUserName = "GetBridgesBot";
+ const telegramInstruction = document.getElementById(
+ "tor-bridges-provider-instruction-telegram"
+ );
+ telegramInstruction.querySelector(
+ "a"
+ ).href = `https://t.me/${telegramUserName}`;
+ document.l10n.setAttributes(
+ telegramInstruction,
+ "tor-bridges-provider-telegram-instruction",
+ { telegramUserName }
+ );
+
+ document
+ .getElementById("tor-bridges-open-built-in-dialog-button")
+ .addEventListener("click", () => {
+ this._openBuiltinDialog();
+ });
+ this._userProvideButton.addEventListener("click", () => {
+ this._openUserProvideDialog(this._haveBridges ? "replace" : "add");
+ });
+ document
+ .getElementById("tor-bridges-open-request-dialog-button")
+ .addEventListener("click", () => {
+ this._openRequestDialog();
+ });
+
Services.obs.addObserver(this, TorSettingsTopics.SettingsChanged);
gBridgeGrid.init();
@@ -1488,6 +1541,17 @@ const gBridgeSettings = {
// and hidden.
this._groupEl.classList.toggle("no-bridges", !haveBridges);
this._groupEl.classList.toggle("have-bridges", haveBridges);
+
+ document.l10n.setAttributes(
+ this._changeHeadingEl,
+ haveBridges
+ ? "tor-bridges-replace-bridges-heading"
+ : "tor-bridges-add-bridges-heading"
+ );
+ document.l10n.setAttributes(
+ this._userProvideButton,
+ haveBridges ? "tor-bridges-replace-button" : "tor-bridges-add-new-button"
+ );
},
/**
@@ -1615,9 +1679,7 @@ const gBridgeSettings = {
"tor-bridges-options-edit-all-menu-item"
);
editItem.addEventListener("click", () => {
- // TODO: move to gBridgeSettings.
- // TODO: Change dialog title. Do not allow Lox invite.
- gConnectionPane.onAddBridgeManually();
+ this._openUserProvideDialog("edit");
});
// TODO: Do we want a different item for built-in bridges, rather than
@@ -1687,6 +1749,138 @@ const gBridgeSettings = {
_forceCloseBridgesMenu() {
this._bridgesMenu.hide(null, { force: true });
},
+
+ /**
+ * Open a bridge dialog that will change the users bridges.
+ *
+ * @param {string} url - The url of the dialog to open.
+ * @param {object?} inputData - The input data to send to the dialog window.
+ * @param {Function} onAccept - The method to call if the bridge dialog was
+ * accepted by the user. This will be passed a "result" object containing
+ * data set by the dialog. This should return a promise that resolves once
+ * the bridge settings have been set, or null if the settings have not
+ * been applied.
+ */
+ _openDialog(url, inputData, onAccept) {
+ const result = { accepted: false, connect: false };
+ let savedSettings = null;
+ gSubDialog.open(
+ url,
+ {
+ features: "resizable=yes",
+ closingCallback: () => {
+ if (!result.accepted) {
+ return;
+ }
+ savedSettings = onAccept(result);
+ if (!savedSettings) {
+ // No change in settings.
+ return;
+ }
+ if (!result.connect) {
+ // Do not open about:torconnect.
+ return;
+ }
+
+ // Wait until the settings are applied before bootstrapping.
+ savedSettings.then(() => {
+ // The bridge dialog button is "connect" when Tor is not
+ // bootstrapped, so do the connect.
+
+ // Start Bootstrapping, which should use the configured bridges.
+ // NOTE: We do this regardless of any previous TorConnect Error.
+ if (TorConnect.canBeginBootstrap) {
+ TorConnect.beginBootstrap();
+ }
+ // Open "about:torconnect".
+ // FIXME: If there has been a previous bootstrapping error then
+ // "about:torconnect" will be trying to get the user to use
+ // AutoBootstrapping. It is not set up to handle a forced direct
+ // entry to plain Bootstrapping from this dialog so the UI will
+ // not be aligned. In particular the
+ // AboutTorConnect.uiState.bootstrapCause will be aligned to
+ // whatever was shown previously in "about:torconnect" instead.
+ TorConnect.openTorConnect();
+ });
+ },
+ // closedCallback should be called after gSubDialog has already
+ // re-assigned focus back to the document.
+ closedCallback: () => {
+ if (!savedSettings) {
+ return;
+ }
+ // Wait until the settings have changed, so that the UI could
+ // respond, then move focus.
+ savedSettings.then(() => gBridgeSettings.takeFocus());
+ },
+ },
+ result,
+ inputData
+ );
+ },
+
+ /**
+ * Open the built-in bridge dialog.
+ */
+ _openBuiltinDialog() {
+ this._openDialog(
+ "chrome://browser/content/torpreferences/builtinBridgeDialog.xhtml",
+ null,
+ result => {
+ if (!result.type) {
+ return null;
+ }
+ return setTorSettings(() => {
+ TorSettings.bridges.enabled = true;
+ TorSettings.bridges.source = TorBridgeSource.BuiltIn;
+ TorSettings.bridges.builtin_type = result.type;
+ });
+ }
+ );
+ },
+
+ /*
+ * Open the request bridge dialog.
+ */
+ _openRequestDialog() {
+ this._openDialog(
+ "chrome://browser/content/torpreferences/requestBridgeDialog.xhtml",
+ null,
+ result => {
+ if (!result.bridges?.length) {
+ return null;
+ }
+ return setTorSettings(() => {
+ TorSettings.bridges.enabled = true;
+ TorSettings.bridges.source = TorBridgeSource.BridgeDB;
+ TorSettings.bridges.bridge_strings = result.bridges.join("\n");
+ });
+ }
+ );
+ },
+
+ /**
+ * Open the user provide dialog.
+ *
+ * @param {string} mode - The mode to open the dialog in: "add", "replace" or
+ * "edit".
+ */
+ _openUserProvideDialog(mode) {
+ this._openDialog(
+ "chrome://browser/content/torpreferences/provideBridgeDialog.xhtml",
+ { mode },
+ result => {
+ if (!result.bridgeStrings) {
+ return null;
+ }
+ return setTorSettings(() => {
+ TorSettings.bridges.enabled = true;
+ TorSettings.bridges.source = TorBridgeSource.UserProvided;
+ TorSettings.bridges.bridge_strings = result.bridgeStrings;
+ });
+ }
+ );
+ },
};
/*
@@ -1719,13 +1913,6 @@ const gConnectionPane = (function () {
location: "#torPreferences-bridges-location",
locationEntries: "#torPreferences-bridges-locationEntries",
chooseForMe: "#torPreferences-bridges-buttonChooseBridgeForMe",
- addHeader: "#torPreferences-addBridge-header",
- addBuiltinLabel: "#torPreferences-addBridge-labelBuiltinBridge",
- addBuiltinButton: "#torPreferences-addBridge-buttonBuiltinBridge",
- requestLabel: "#torPreferences-addBridge-labelRequestBridge",
- requestButton: "#torPreferences-addBridge-buttonRequestBridge",
- enterLabel: "#torPreferences-addBridge-labelEnterBridge",
- enterButton: "#torPreferences-addBridge-buttonEnterBridge",
},
advanced: {
header: "h1#torPreferences-advanced-header",
@@ -1985,39 +2172,6 @@ const gConnectionPane = (function () {
this._showAutoconfiguration();
}
- // Add a new bridge
- prefpane.querySelector(selectors.bridges.addHeader).textContent =
- TorStrings.settings.bridgeAdd;
- prefpane.querySelector(selectors.bridges.addBuiltinLabel).textContent =
- TorStrings.settings.bridgeSelectBrowserBuiltin;
- {
- const button = prefpane.querySelector(
- selectors.bridges.addBuiltinButton
- );
- button.setAttribute("label", TorStrings.settings.bridgeSelectBuiltin);
- button.addEventListener("command", e => {
- this.onAddBuiltinBridge();
- });
- }
- prefpane.querySelector(selectors.bridges.requestLabel).textContent =
- TorStrings.settings.bridgeRequestFromTorProject;
- {
- const button = prefpane.querySelector(selectors.bridges.requestButton);
- button.setAttribute("label", TorStrings.settings.bridgeRequest);
- button.addEventListener("command", e => {
- this.onRequestBridge();
- });
- }
- prefpane.querySelector(selectors.bridges.enterLabel).textContent =
- TorStrings.settings.bridgeEnterKnown;
- {
- const button = prefpane.querySelector(selectors.bridges.enterButton);
- button.setAttribute("label", TorStrings.settings.bridgeAddManually);
- button.addEventListener("command", e => {
- this.onAddBridgeManually();
- });
- }
-
// Advanced setup
prefpane.querySelector(selectors.advanced.header).innerText =
TorStrings.settings.advancedHeading;
@@ -2122,122 +2276,6 @@ const gConnectionPane = (function () {
this._showAutoconfiguration();
},
- /**
- * Open a bridge dialog that will change the users bridges.
- *
- * @param {string} url - The url of the dialog to open.
- * @param {Function} onAccept - The method to call if the bridge dialog was
- * accepted by the user. This will be passed a "result" object containing
- * data set by the dialog. This should return a promise that resolves once
- * the bridge settings have been set, or null if the settings have not
- * been applied.
- */
- openBridgeDialog(url, onAccept) {
- const result = { accepted: false, connect: false };
- let savedSettings = null;
- gSubDialog.open(
- url,
- {
- features: "resizable=yes",
- closingCallback: () => {
- if (!result.accepted) {
- return;
- }
- savedSettings = onAccept(result);
- if (!savedSettings) {
- // No change in settings.
- return;
- }
- if (!result.connect) {
- // Do not open about:torconnect.
- return;
- }
-
- // Wait until the settings are applied before bootstrapping.
- savedSettings.then(() => {
- // The bridge dialog button is "connect" when Tor is not
- // bootstrapped, so do the connect.
-
- // Start Bootstrapping, which should use the configured bridges.
- // NOTE: We do this regardless of any previous TorConnect Error.
- if (TorConnect.canBeginBootstrap) {
- TorConnect.beginBootstrap();
- }
- // Open "about:torconnect".
- // FIXME: If there has been a previous bootstrapping error then
- // "about:torconnect" will be trying to get the user to use
- // AutoBootstrapping. It is not set up to handle a forced direct
- // entry to plain Bootstrapping from this dialog so the UI will
- // not be aligned. In particular the
- // AboutTorConnect.uiState.bootstrapCause will be aligned to
- // whatever was shown previously in "about:torconnect" instead.
- TorConnect.openTorConnect();
- });
- },
- // closedCallback should be called after gSubDialog has already
- // re-assigned focus back to the document.
- closedCallback: () => {
- if (!savedSettings) {
- return;
- }
- // Wait until the settings have changed, so that the UI could
- // respond, then move focus.
- savedSettings.then(() => gCurrentBridgesArea.takeFocus());
- },
- },
- result
- );
- },
-
- onAddBuiltinBridge() {
- this.openBridgeDialog(
- "chrome://browser/content/torpreferences/builtinBridgeDialog.xhtml",
- result => {
- if (!result.type) {
- return null;
- }
- return setTorSettings(() => {
- TorSettings.bridges.enabled = true;
- TorSettings.bridges.source = TorBridgeSource.BuiltIn;
- TorSettings.bridges.builtin_type = result.type;
- });
- }
- );
- },
-
- // called when the request bridge button is activated
- onRequestBridge() {
- this.openBridgeDialog(
- "chrome://browser/content/torpreferences/requestBridgeDialog.xhtml",
- result => {
- if (!result.bridges?.length) {
- return null;
- }
- return setTorSettings(() => {
- TorSettings.bridges.enabled = true;
- TorSettings.bridges.source = TorBridgeSource.BridgeDB;
- TorSettings.bridges.bridge_strings = result.bridges.join("\n");
- });
- }
- );
- },
-
- onAddBridgeManually() {
- this.openBridgeDialog(
- "chrome://browser/content/torpreferences/provideBridgeDialog.xhtml",
- result => {
- if (!result.bridgeStrings) {
- return null;
- }
- return setTorSettings(() => {
- TorSettings.bridges.enabled = true;
- TorSettings.bridges.source = TorBridgeSource.UserProvided;
- TorSettings.bridges.bridge_strings = result.bridgeStrings;
- });
- }
- );
- },
-
onAdvancedSettings() {
gSubDialog.open(
"chrome://browser/content/torpreferences/connectionSettingsDialog.xhtml",
=====================================
browser/components/torpreferences/content/connectionPane.xhtml
=====================================
@@ -293,28 +293,102 @@
></html:button>
</html:div>
</html:div>
- <html:h2 id="torPreferences-addBridge-header"></html:h2>
+ <html:h2 id="tor-bridges-change-heading"></html:h2>
<hbox align="center">
- <label id="torPreferences-addBridge-labelBuiltinBridge" flex="1" />
- <button
- id="torPreferences-addBridge-buttonBuiltinBridge"
- class="accessory-button"
+ <description
+ flex="1"
+ data-l10n-id="tor-bridges-select-built-in-description"
/>
- </hbox>
- <hbox align="center">
- <label id="torPreferences-addBridge-labelRequestBridge" flex="1" />
- <button
- id="torPreferences-addBridge-buttonRequestBridge"
+ <html:button
+ id="tor-bridges-open-built-in-dialog-button"
class="accessory-button"
- />
+ data-l10n-id="tor-bridges-select-built-in-button"
+ ></html:button>
</hbox>
<hbox align="center">
- <label id="torPreferences-addBridge-labelEnterBridge" flex="1" />
- <button
- id="torPreferences-addBridge-buttonEnterBridge"
+ <description id="tor-bridges-user-provide-description" flex="1" />
+ <html:button
+ id="tor-bridges-open-user-provide-dialog-button"
class="accessory-button"
- />
+ ></html:button>
</hbox>
+ <html:h3
+ id="tor-bridges-provider-heading"
+ data-l10n-id="tor-bridges-find-more-heading"
+ ></html:h3>
+ <description data-l10n-id="tor-bridges-find-more-description" />
+ <html:div id="tor-bridges-provider-area">
+ <html:ul id="tor-bridges-provider-list">
+ <html:li class="tor-bridges-provider-item">
+ <html:img
+ id="tor-bridges-provider-icon-telegram"
+ class="tor-bridges-provider-icon"
+ alt=""
+ />
+ <html:div
+ class="tor-bridges-provider-name"
+ data-l10n-id="tor-bridges-provider-telegram-name"
+ ></html:div>
+ <html:div
+ id="tor-bridges-provider-instruction-telegram"
+ class="tor-bridges-provider-instruction"
+ >
+ <html:a data-l10n-name="user"></html:a>
+ </html:div>
+ </html:li>
+ <html:li class="tor-bridges-provider-item">
+ <html:img
+ id="tor-bridges-provider-icon-web"
+ class="tor-bridges-provider-icon"
+ alt=""
+ />
+ <html:div
+ class="tor-bridges-provider-name"
+ data-l10n-id="tor-bridges-provider-web-name"
+ ></html:div>
+ <html:div
+ class="tor-bridges-provider-instruction"
+ data-l10n-id="tor-bridges-provider-web-instruction"
+ data-l10n-args='{ "url": "bridges.torproject.org" }'
+ >
+ <html:a
+ href="https://bridges.torproject.org"
+ data-l10n-name="url"
+ ></html:a>
+ </html:div>
+ </html:li>
+ <html:li class="tor-bridges-provider-item">
+ <html:img
+ id="tor-bridges-provider-icon-email"
+ class="tor-bridges-provider-icon"
+ alt=""
+ />
+ <html:div
+ class="tor-bridges-provider-name"
+ data-l10n-id="tor-bridges-provider-email-name"
+ ></html:div>
+ <html:div
+ class="tor-bridges-provider-instruction"
+ data-l10n-id="tor-bridges-provider-email-instruction"
+ data-l10n-args='{ "address": "bridges(a)torproject.org" }'
+ ></html:div>
+ </html:li>
+ </html:ul>
+ <html:div id="tor-bridges-request-box">
+ <html:img
+ alt=""
+ src="chrome://browser/content/torpreferences/bridge-bot.svg"
+ ></html:img>
+ <html:div
+ id="tor-bridges-request-description"
+ data-l10n-id="tor-bridges-request-from-browser"
+ ></html:div>
+ <html:button
+ id="tor-bridges-open-request-dialog-button"
+ data-l10n-id="tor-bridges-request-button"
+ ></html:button>
+ </html:div>
+ </html:div>
</groupbox>
<!-- Advanced -->
=====================================
browser/components/torpreferences/content/provideBridgeDialog.js
=====================================
@@ -15,11 +15,24 @@ const { TorConnect, TorConnectTopics } = ChromeUtils.importESModule(
const gProvideBridgeDialog = {
init() {
this._result = window.arguments[0];
+ const mode = window.arguments[1].mode;
+
+ let titleId;
+ switch (mode) {
+ case "edit":
+ titleId = "user-provide-bridge-dialog-edit-title";
+ break;
+ case "add":
+ titleId = "user-provide-bridge-dialog-add-title";
+ break;
+ case "replace":
+ default:
+ titleId = "user-provide-bridge-dialog-replace-title";
+ break;
+ }
+
+ document.l10n.setAttributes(document.documentElement, titleId);
- document.documentElement.setAttribute(
- "title",
- TorStrings.settings.provideBridgeTitleAdd
- );
const learnMore = document.createXULElement("label");
learnMore.className = "learnMore text-link";
learnMore.setAttribute("is", "text-link");
=====================================
browser/components/torpreferences/content/provideBridgeDialog.xhtml
=====================================
@@ -9,6 +9,10 @@
xmlns:html="http://www.w3.org/1999/xhtml"
>
<dialog id="torPreferences-provideBridge-dialog" buttons="accept,cancel">
+ <linkset>
+ <html:link rel="localization" href="browser/tor-browser.ftl" />
+ </linkset>
+
<script src="chrome://browser/content/torpreferences/provideBridgeDialog.js" />
<description>
=====================================
browser/components/torpreferences/content/telegram-logo.svg
=====================================
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="context-fill" xmlns="http://www.w3.org/2000/svg">
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M13.5527 3.74072C13.6057 3.44502 13.3069 3.21007 13.0321 3.33143L2.46222 7.99865L5.04818 8.60316L10.1001 5.29184C10.8373 4.80861 11.6593 5.7727 11.0656 6.42426L7.88895 9.91029L11.9093 12.8968L13.5527 3.74072ZM12.5272 2.18794C13.7181 1.66208 15.013 2.68016 14.783 3.96155L13.104 13.3162C12.9564 14.1382 11.9962 14.5186 11.3258 14.0205L7.03263 10.8313C6.49819 10.4343 6.42353 9.66259 6.87195 9.17049L7.47872 8.50462L5.68862 9.67797C5.4311 9.84676 5.11564 9.90263 4.81582 9.83254L1.81371 9.13075C0.762034 8.8849 0.627375 7.4424 1.61537 7.00614L12.5272 2.18794Z"/>
+</svg>
=====================================
browser/components/torpreferences/content/torPreferences.css
=====================================
@@ -447,6 +447,91 @@
fill: currentColor;
}
+#tor-bridges-provider-heading {
+ font-size: 1.14em;
+ margin-block: 48px 8px;
+}
+
+#tor-bridges-provider-area {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 16px;
+ align-items: start;
+ line-height: 1.8;
+ margin-block-start: 24px;
+}
+
+#tor-bridges-provider-list {
+ display: grid;
+ grid-template-columns: max-content max-content;
+ /* 16px gap between items. */
+ gap: 16px 12px;
+ margin-block: 16px;
+}
+
+.tor-bridges-provider-item {
+ grid-column: 1 / -1;
+ display: grid;
+ grid-template-columns: subgrid;
+ align-items: center;
+ justify-items: start;
+ /* No gap between the name and instruction. */
+ gap: 0 12px;
+}
+
+.tor-bridges-provider-icon {
+ width: 16px;
+ height: 16px;
+ -moz-context-properties: fill;
+ fill: var(--in-content-icon-color);
+}
+
+#tor-bridges-provider-icon-telegram {
+ content: url("chrome://browser/content/torpreferences/telegram-logo.svg");
+}
+
+#tor-bridges-provider-icon-web {
+ content: url("chrome://browser/content/torpreferences/network.svg");
+}
+
+#tor-bridges-provider-icon-email {
+ content: url("chrome://browser/skin/mail.svg");
+}
+
+.tor-bridges-provider-name {
+ font-weight: 600;
+ font-size: 0.85em;
+}
+
+.tor-bridges-provider-instruction {
+ grid-column: 2 / 3;
+}
+
+#tor-bridges-request-box {
+ /* Take up the full height in the container. */
+ align-self: stretch;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+ padding: 16px;
+ background: var(--in-content-box-info-background);
+ border-radius: 4px;
+}
+
+#tor-bridges-request-box > * {
+ flex: 0 0 auto;
+}
+
+#tor-bridges-request-description {
+ margin-block: 12px 16px;
+}
+
+#tor-bridges-open-request-dialog-button {
+ margin: 0;
+ line-height: 1;
+}
+
#torPreferences-bridges-location {
width: 280px;
}
=====================================
browser/components/torpreferences/jar.mn
=====================================
@@ -1,6 +1,8 @@
browser.jar:
content/browser/torpreferences/bridge.svg (content/bridge.svg)
content/browser/torpreferences/bridge-qr.svg (content/bridge-qr.svg)
+ content/browser/torpreferences/telegram-logo.svg (content/telegram-logo.svg)
+ content/browser/torpreferences/bridge-bot.svg (content/bridge-bot.svg)
content/browser/torpreferences/bridgeQrDialog.xhtml (content/bridgeQrDialog.xhtml)
content/browser/torpreferences/bridgeQrDialog.js (content/bridgeQrDialog.js)
content/browser/torpreferences/builtinBridgeDialog.xhtml (content/builtinBridgeDialog.xhtml)
=====================================
browser/locales/en-US/browser/tor-browser.ftl
=====================================
@@ -121,3 +121,58 @@ tor-bridges-share-description = Share your bridges with trusted contacts.
tor-bridges-copy-addresses-button = Copy addresses
tor-bridges-qr-addresses-button =
.title = Show QR code
+
+# Shown as a heading when the user has no current bridges.
+tor-bridges-add-bridges-heading = Add bridges
+# Shown as a heading when the user has existing bridges that can be replaced.
+tor-bridges-replace-bridges-heading = Replace your bridges
+
+tor-bridges-select-built-in-description = Choose from one of { -brand-short-name }’s built-in bridges
+tor-bridges-select-built-in-button = Select a built-in bridge…
+
+tor-bridges-add-addresses-description = Enter bridge addresses you already know
+# Shown when the user has no current bridges.
+# Opens a dialog where the user can provide a new bridge address or share code.
+tor-bridges-add-new-button = Add new bridges…
+# Shown when the user has existing bridges.
+# Opens a dialog where the user can provide a new bridge address or share code to replace their current bridges.
+tor-bridges-replace-button = Replace bridges…
+
+tor-bridges-find-more-heading = Find more bridges
+# "Tor Project" is the organisation name.
+tor-bridges-find-more-description = Since many bridge addresses aren’t public, you may need to request some from the Tor Project.
+
+# "Telegram" is the common brand name of the Telegram Messenger application
+tor-bridges-provider-telegram-name = Telegram
+# Here "Message" is a verb, short for "Send a message to". This is an instruction to send a message to the given Telegram Messenger user to receive a new bridge.
+# $telegramUserName (String) - The Telegram Messenger user name that should receive messages. Should be wrapped in '<a data-l10n-name="user">' and '</a>'.
+# E.g. in English, "Message GetBridgesBot".
+tor-bridges-provider-telegram-instruction = Message <a data-l10n-name="user">{ $telegramUserName }</a>
+
+# "Web" is the proper noun for the "World Wide Web".
+tor-bridges-provider-web-name = Web
+# Instructions to visit the given website.
+# $url (String) - The URL for Tor Project bridges. Should be wrapped in '<a data-l10n-name"url">' and '</a>'.
+tor-bridges-provider-web-instruction = Visit <a data-l10n-name="url">{ $url }</a>
+
+# "Gmail" is the Google brand name. "Riseup" refers to the Riseup organisation at riseup.net.
+tor-bridges-provider-email-name = Gmail or Riseup
+# Here "Email" is a verb, short for "Send an email to". This is an instruction to send an email to the given address to receive a new bridge.
+# $address (String) - The email address that should receive the email.
+# E.g. in English, "Email bridges(a)torproject.org".
+tor-bridges-provider-email-instruction = Email { $address }
+
+tor-bridges-request-from-browser = You can also get bridges from the bridge bot without leaving { -brand-short-name }.
+tor-bridges-request-button = Request bridges…
+
+## User provided bridge dialog.
+
+# Used when the user is editing their existing bridge addresses.
+user-provide-bridge-dialog-edit-title =
+ .title = Edit your bridges
+# Used when the user has no existing bridges.
+user-provide-bridge-dialog-add-title =
+ .title = Add new bridges
+# Used when the user is replacing their existing bridges with new ones.
+user-provide-bridge-dialog-replace-title =
+ .title = Replace your bridges
=====================================
toolkit/modules/TorStrings.sys.mjs
=====================================
@@ -105,14 +105,6 @@ const Loader = {
bridgeRemoveAllDialogTitle: "Remove all bridges?",
bridgeRemoveAllDialogDescription:
"If these bridges were received from torproject.org or added manually, this action cannot be undone",
- bridgeAdd: "Add a New Bridge",
- bridgeSelectBrowserBuiltin:
- "Choose from one of Tor Browser’s built-in bridges",
- bridgeSelectBuiltin: "Select a Built-In Bridge…",
- bridgeRequestFromTorProject: "Request a bridge from torproject.org",
- bridgeRequest: "Request a Bridge…",
- bridgeEnterKnown: "Enter a bridge address you already know",
- bridgeAddManually: "Add a Bridge Manually…",
// Advanced settings
advancedHeading: "Advanced",
advancedLabel: "Configure how Tor Browser connects to the internet",
@@ -148,7 +140,6 @@ const Loader = {
captchaTextboxPlaceholder: "Enter the characters from the image",
incorrectCaptcha: "The solution is not correct. Please try again.",
// Provide bridge dialog
- provideBridgeTitleAdd: "Add a Bridge Manually",
provideBridgeDescription:
"Add a bridge provided by a trusted organization or someone you know. If you don’t have a bridge, you can request one from the Tor Project. %S",
provideBridgePlaceholder: "type address:port (one per line)",
=====================================
toolkit/torbutton/chrome/locale/en-US/settings.properties
=====================================
@@ -39,13 +39,6 @@ settings.bridgeDisableBuiltIn=Disable built-in bridges
settings.copied=Copied!
settings.bridgeRemoveAllDialogTitle=Remove all bridges?
settings.bridgeRemoveAllDialogDescription=If these bridges were received from torproject.org or added manually, this action cannot be undone
-settings.bridgeAdd=Add a New Bridge
-settings.bridgeSelectBrowserBuiltin=Choose from one of Tor Browser’s built-in bridges
-settings.bridgeSelectBuiltin=Select a Built-In Bridge…
-settings.bridgeRequestFromTorProject=Request a bridge from torproject.org
-settings.bridgeRequest=Request a Bridge…
-settings.bridgeEnterKnown=Enter a bridge address you already know
-settings.bridgeAddManually=Add a Bridge Manually…
# Advanced settings
settings.advancedHeading=Advanced
@@ -82,8 +75,6 @@ settings.solveTheCaptcha=Solve the CAPTCHA to request a bridge.
settings.captchaTextboxPlaceholder=Enter the characters from the image
settings.incorrectCaptcha=The solution is not correct. Please try again.
-# Provide bridge dialog
-settings.provideBridgeTitleAdd=Add a Bridge Manually
# Translation note: %S is a Learn more link.
settings.provideBridgeDescription=Add a bridge provided by a trusted organization or someone you know. If you don’t have a bridge, you can request one from the Tor Project. %S
settings.provideBridgePlaceholder=type address:port (one per line)
@@ -125,3 +116,13 @@ settings.bridgeShowAll=Show All Bridges
settings.bridgeShowFewer=Show Fewer Bridges
settings.allBridgesEnabled=Use current bridges
settings.bridgeRemoveAll=Remove All Bridges
+settings.bridgeAdd=Add a New Bridge
+settings.bridgeSelectBrowserBuiltin=Choose from one of Tor Browser’s built-in bridges
+settings.bridgeSelectBuiltin=Select a Built-In Bridge…
+settings.bridgeRequestFromTorProject=Request a bridge from torproject.org
+settings.bridgeRequest=Request a Bridge…
+settings.bridgeEnterKnown=Enter a bridge address you already know
+settings.bridgeAddManually=Add a Bridge Manually…
+
+# Provide bridge dialog
+settings.provideBridgeTitleAdd=Add a Bridge Manually
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/6211ed…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/6211ed…
You're receiving this email because of your account on gitlab.torproject.org.
1
0
[Git][tpo/applications/tor-browser-build][main] Bug 41066: Compress the APKs more
by Pier Angelo Vendrame (@pierov) 24 Jan '24
by Pier Angelo Vendrame (@pierov) 24 Jan '24
24 Jan '24
Pier Angelo Vendrame pushed to branch main at The Tor Project / Applications / tor-browser-build
Commits:
23474930 by Pier Angelo Vendrame at 2024-01-24T17:08:30+01:00
Bug 41066: Compress the APKs more
Our APK was refused by the Play Store as too big.
As a workaround, for this release we can try to compress the APK more,
by extracting it and repacking it with 7-zip.
The preferred and long-term solution would be to switch to Android App
Bundles, but this might require some changes to our signing scripts.
- - - - -
2 changed files:
- projects/browser/build.android
- projects/browser/config
Changes:
=====================================
projects/browser/build.android
=====================================
@@ -46,13 +46,19 @@ mv $rootdir/[% c('input_files_by_name/noscript') %] "$noscript_path"
mv $rootdir/allowed_addons.json $assets_dir/allowed_addons.json
-[% c('zip', {
- zip_src => [ '$assets_dir' ],
- zip_args => '$apk',
- }) %]
+mkdir apk
+pushd apk
+7zz x "$apk"
+cp -R ../assets ./
+find -type f -exec touch -m -t '[% USE date; date.format(pc("firefox-android", "timestamp"), format = "%Y%m%d%H%M") %]' {} \;
+find -type f ! -name resources.arsc -printf '%P\n' | sort > ../files.txt
+7zz a -tzip -mx9 -mtc- -spf ../repacked.apk @../files.txt
+# resources.arsc must not be compressed as per the APK specifications
+7zz a -tzip -mm=Copy -mtc- ../repacked.apk resources.arsc
+popd
aligned_apk=$(basename $apk .apk)_aligned.apk
-zipalign -vp 4 $apk $aligned_apk
+zipalign -vp 4 repacked.apk $aligned_apk
# Sign a QA build. This .apk is not a debug version and doesn't contain a debug
# flag in the manifest.
=====================================
projects/browser/config
=====================================
@@ -46,7 +46,13 @@ targets:
var:
verify_allowed_addons: 1
arch_deps:
- - openjdk-11-jdk-headless
+ - 7zip
+ - openjdk-17-jdk-headless
+ container:
+ # 7zip is in backports in bullseye, and we can already use Java 17 for
+ # apksigner.
+ suite: bookworm
+ arch: amd64
torbrowser:
var:
prefs_file: 000-tor-browser.js
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/2…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/2…
You're receiving this email because of your account on gitlab.torproject.org.
1
0