Dan Ballard pushed to branch tor-browser-140.1.0esr-15.0-1 at The Tor Project / Applications / Tor Browser
Commits:
-
4fba4d54
by Dan Ballard at 2025-08-04T23:24:21-05:00
-
a04605ca
by Dan Ballard at 2025-08-04T23:24:21-05:00
-
c563c43e
by Dan Ballard at 2025-08-04T23:24:22-05:00
-
e9ac372c
by Dan Ballard at 2025-08-04T23:30:59-05:00
-
579ade4c
by Dan Ballard at 2025-08-04T23:31:02-05:00
13 changed files:
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/TorBrowserFeatures.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TorBridgeConfigFragment.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapProgressViewModel.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistViewModel.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorLogsViewModel.kt
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorAndroidIntegration.java
- + mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorConnectError.java
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorConnectStage.java
- toolkit/modules/TorAndroidIntegration.sys.mjs
Changes:
... | ... | @@ -101,7 +101,6 @@ import org.mozilla.fenix.browser.browsingmode.BrowsingMode |
101 | 101 | import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
|
102 | 102 | import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager
|
103 | 103 | import org.mozilla.fenix.components.appstate.AppAction
|
104 | -import org.mozilla.fenix.components.appstate.AppAction.ShareAction
|
|
105 | 104 | import org.mozilla.fenix.components.appstate.OrientationMode
|
106 | 105 | import org.mozilla.fenix.components.metrics.BreadcrumbsRecorder
|
107 | 106 | import org.mozilla.fenix.components.metrics.GrowthDataWorker
|
... | ... | @@ -137,7 +136,6 @@ import org.mozilla.fenix.home.intent.OpenBrowserIntentProcessor |
137 | 136 | import org.mozilla.fenix.home.intent.OpenPasswordManagerIntentProcessor
|
138 | 137 | import org.mozilla.fenix.home.intent.OpenRecentlyClosedIntentProcessor
|
139 | 138 | import org.mozilla.fenix.home.intent.OpenSpecificTabIntentProcessor
|
140 | -import org.mozilla.fenix.home.intent.ReEngagementIntentProcessor
|
|
141 | 139 | import org.mozilla.fenix.home.intent.SpeechProcessingIntentProcessor
|
142 | 140 | import org.mozilla.fenix.home.intent.StartSearchIntentProcessor
|
143 | 141 | import org.mozilla.fenix.library.bookmarks.DesktopFolders
|
... | ... | @@ -167,19 +165,18 @@ import org.mozilla.fenix.theme.DefaultThemeManager |
167 | 165 | import org.mozilla.fenix.theme.StatusBarColorManager
|
168 | 166 | import org.mozilla.fenix.theme.ThemeManager
|
169 | 167 | import org.mozilla.fenix.tor.TorConnectionAssistFragmentDirections
|
170 | -import org.mozilla.fenix.tor.TorEvents
|
|
171 | 168 | import org.mozilla.fenix.utils.Settings
|
172 | 169 | import org.mozilla.fenix.utils.changeAppLauncherIcon
|
173 | 170 | import java.lang.ref.WeakReference
|
174 | 171 | import java.util.Locale
|
175 | 172 | |
176 | -import androidx.compose.material.SnackbarDuration
|
|
177 | 173 | import mozilla.components.browser.engine.gecko.GeckoEngine
|
178 | 174 | import org.mozilla.fenix.compose.core.Action
|
179 | 175 | import org.mozilla.fenix.compose.snackbar.SnackbarState
|
180 | 176 | import org.mozilla.fenix.compose.snackbar.Snackbar
|
181 | 177 | import org.mozilla.fenix.tor.UrlQuickLoadViewModel
|
182 | 178 | import org.mozilla.geckoview.TorAndroidIntegration
|
179 | +import org.mozilla.geckoview.TorAndroidIntegration.BootstrapStateChangeListener
|
|
183 | 180 | import org.mozilla.geckoview.TorConnectStage
|
184 | 181 | import kotlin.system.exitProcess
|
185 | 182 | |
... | ... | @@ -915,19 +912,25 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, TorAn |
915 | 912 | */
|
916 | 913 | @SuppressLint("MissingSuperCall") // super.onNewIntent is called in [onNewIntentInternal(intent)]
|
917 | 914 | final override fun onNewIntent(intent: Intent) {
|
918 | - if (intent.action == ACTION_MAIN || components.torController.isConnected) {
|
|
915 | + if (intent.action == ACTION_MAIN || components.torController.isBootstrapped) {
|
|
919 | 916 | onNewIntentInternal(intent)
|
920 | 917 | } else {
|
921 | 918 | // Wait until Tor is connected to handle intents from external apps for links, search, etc.
|
922 | - components.torController.registerTorListener(object : TorEvents {
|
|
923 | - override fun onTorConnected() {
|
|
924 | - components.torController.unregisterTorListener(this)
|
|
925 | - onNewIntentInternal(intent)
|
|
919 | + val torIntegration = (components.core.engine as GeckoEngine).getTorIntegrationController()
|
|
920 | + torIntegration.registerBootstrapStateChangeListener(
|
|
921 | + object : BootstrapStateChangeListener {
|
|
922 | + |
|
923 | + override fun onBootstrapStageChange(stage: TorConnectStage) {
|
|
924 | + if (stage.isBootstrapped) {
|
|
925 | + torIntegration.unregisterBootstrapStateChangeListener(this)
|
|
926 | + onNewIntentInternal(intent)
|
|
927 | + }
|
|
928 | + }
|
|
929 | + |
|
930 | + override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) {}
|
|
926 | 931 | }
|
927 | - override fun onTorConnecting() { /* no-op */ }
|
|
928 | - override fun onTorStopped() { /* no-op */ }
|
|
929 | - override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { /* no-op */ }
|
|
930 | - })
|
|
932 | + )
|
|
933 | + |
|
931 | 934 | return
|
932 | 935 | }
|
933 | 936 | }
|
... | ... | @@ -1516,7 +1519,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, TorAn |
1516 | 1519 | // we want to ignore other cases when the app gets open by users clicking on links,
|
1517 | 1520 | // unless Tor is not yet connected.
|
1518 | 1521 | getSettings().shouldStartOnHome() && (intent?.action == ACTION_MAIN ||
|
1519 | - !components.torController.isConnected)
|
|
1522 | + !components.torController.isBootstrapped)
|
|
1520 | 1523 | }
|
1521 | 1524 | }
|
1522 | 1525 | |
... | ... | @@ -1606,14 +1609,13 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, TorAn |
1606 | 1609 | exitProcess(0)
|
1607 | 1610 | }
|
1608 | 1611 | |
1609 | - override fun onBootstrapStateChange(state: String) = Unit
|
|
1610 | - override fun onBootstrapStageChange(stage: TorConnectStage) = Unit
|
|
1611 | - override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) = Unit
|
|
1612 | - override fun onBootstrapComplete() {
|
|
1613 | - if (settings().useHtmlConnectionUi) {
|
|
1614 | - components.useCases.tabsUseCases.removeAllTabs()
|
|
1615 | - navHost.navController.navigate(NavGraphDirections.actionStartupHome())
|
|
1612 | + override fun onBootstrapStageChange(stage: TorConnectStage) {
|
|
1613 | + if (stage.isBootstrapped) {
|
|
1614 | + if (settings().useHtmlConnectionUi) {
|
|
1615 | + components.useCases.tabsUseCases.removeAllTabs()
|
|
1616 | + navHost.navController.navigate(NavGraphDirections.actionStartupHome())
|
|
1617 | + }
|
|
1616 | 1618 | }
|
1617 | 1619 | }
|
1618 | - override fun onBootstrapError(code: String?, message: String?, phase: String?, reason: String?) = Unit
|
|
1620 | + override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) = Unit
|
|
1619 | 1621 | } |
... | ... | @@ -13,6 +13,7 @@ import android.os.Build |
13 | 13 | import android.os.Bundle
|
14 | 14 | import android.os.StrictMode
|
15 | 15 | import androidx.annotation.VisibleForTesting
|
16 | +import mozilla.components.browser.engine.gecko.GeckoEngine
|
|
16 | 17 | import mozilla.components.feature.intent.ext.sanitize
|
17 | 18 | import mozilla.components.feature.intent.processing.IntentProcessor
|
18 | 19 | import mozilla.components.support.base.log.logger.Logger
|
... | ... | @@ -31,7 +32,8 @@ import org.mozilla.fenix.ext.settings |
31 | 32 | import org.mozilla.fenix.perf.MarkersActivityLifecycleCallbacks
|
32 | 33 | import org.mozilla.fenix.perf.StartupTimeline
|
33 | 34 | import org.mozilla.fenix.shortcut.NewTabShortcutIntentProcessor
|
34 | -import org.mozilla.fenix.tor.TorEvents
|
|
35 | +import org.mozilla.geckoview.TorAndroidIntegration.BootstrapStateChangeListener
|
|
36 | +import org.mozilla.geckoview.TorConnectStage
|
|
35 | 37 | |
36 | 38 | /**
|
37 | 39 | * Processes incoming intents and sends them to the corresponding activity.
|
... | ... | @@ -55,19 +57,24 @@ class IntentReceiverActivity : Activity() { |
55 | 57 | // the HomeActivity.
|
56 | 58 | val intent = intent?.let { Intent(it) } ?: Intent()
|
57 | 59 | intent.sanitize().stripUnwantedFlags()
|
58 | - if (intent.action == ACTION_MAIN || components.torController.isConnected) {
|
|
60 | + if (intent.action == ACTION_MAIN || components.torController.isBootstrapped) {
|
|
59 | 61 | processIntent(intent)
|
60 | 62 | } else {
|
61 | 63 | // Wait until Tor is connected to handle intents from external apps for links, search, etc.
|
62 | - components.torController.registerTorListener(object : TorEvents {
|
|
63 | - override fun onTorConnected() {
|
|
64 | - components.torController.unregisterTorListener(this)
|
|
65 | - processIntent(intent)
|
|
66 | - }
|
|
67 | - override fun onTorConnecting() { /* no-op */ }
|
|
68 | - override fun onTorStopped() { /* no-op */ }
|
|
69 | - override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) { /* no-op */ }
|
|
70 | - })
|
|
64 | + val engine = components.core.engine as GeckoEngine
|
|
65 | + engine.getTorIntegrationController().registerBootstrapStateChangeListener(
|
|
66 | + object : BootstrapStateChangeListener {
|
|
67 | + |
|
68 | + override fun onBootstrapStageChange(stage: TorConnectStage) {
|
|
69 | + if (stage.isBootstrapped) {
|
|
70 | + engine.getTorIntegrationController().unregisterBootstrapStateChangeListener(this)
|
|
71 | + processIntent(intent)
|
|
72 | + }
|
|
73 | + }
|
|
74 | + |
|
75 | + override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) {}
|
|
76 | + })
|
|
77 | + |
|
71 | 78 | |
72 | 79 | // In the meantime, open the HomeActivity so the user can get connected.
|
73 | 80 | processIntent(Intent())
|
... | ... | @@ -20,7 +20,7 @@ import mozilla.components.support.webextensions.WebExtensionSupport |
20 | 20 | import mozilla.components.support.base.log.logger.Logger
|
21 | 21 | import org.mozilla.fenix.ext.components
|
22 | 22 | import org.mozilla.fenix.ext.settings
|
23 | -import org.mozilla.fenix.tor.TorEvents
|
|
23 | +import org.mozilla.fenix.tor.RunOnceBootstrapped
|
|
24 | 24 | |
25 | 25 | object TorBrowserFeatures {
|
26 | 26 | private val logger = Logger("torbrowser-features")
|
... | ... | @@ -142,9 +142,8 @@ object TorBrowserFeatures { |
142 | 142 | * causing automatic update checks failures (components.addonUpdater being a lazy prop).
|
143 | 143 | * The extension, from then on, should behave as if the user had installed it manually.
|
144 | 144 | */
|
145 | - context.components.torController.registerTorListener(object : TorEvents {
|
|
146 | - override fun onTorConnected() {
|
|
147 | - context.components.torController.unregisterTorListener(this)
|
|
145 | + context.components.torController.registerRunOnceBootstrapped(object : RunOnceBootstrapped {
|
|
146 | + override fun onBootstrapped() {
|
|
148 | 147 | // Enable automatic updates. This must be done on every startup (tor-browser#42353)
|
149 | 148 | context.components.addonUpdater.registerForFutureUpdates(NOSCRIPT_ID)
|
150 | 149 | // Force a one-time immediate update check for older installations
|
... | ... | @@ -153,18 +152,6 @@ object TorBrowserFeatures { |
153 | 152 | settings.noscriptUpdated = 2
|
154 | 153 | }
|
155 | 154 | }
|
156 | - |
|
157 | - @SuppressWarnings("EmptyFunctionBlock")
|
|
158 | - override fun onTorConnecting() {
|
|
159 | - }
|
|
160 | - |
|
161 | - @SuppressWarnings("EmptyFunctionBlock")
|
|
162 | - override fun onTorStopped() {
|
|
163 | - }
|
|
164 | - |
|
165 | - @SuppressWarnings("EmptyFunctionBlock")
|
|
166 | - override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) {
|
|
167 | - }
|
|
168 | 155 | })
|
169 | 156 | }
|
170 | 157 |
... | ... | @@ -56,7 +56,6 @@ class TorBridgeConfigFragment : PreferenceFragmentCompat() { |
56 | 56 | setOnPreferenceChangeListener<Boolean> { preference, enabled ->
|
57 | 57 | preference.context.components.torController.bridgesEnabled = enabled
|
58 | 58 | updateCurrentConfiguredBridgePref(preference)
|
59 | - preference.context.components.torController.restartTor()
|
|
60 | 59 | true
|
61 | 60 | }
|
62 | 61 | }
|
... | ... | @@ -71,7 +70,6 @@ class TorBridgeConfigFragment : PreferenceFragmentCompat() { |
71 | 70 | preference.context.components.torController.bridgeTransport = TorBridgeTransportConfig.USER_PROVIDED
|
72 | 71 | preference.context.components.torController.userProvidedBridges = userProvidedBridge
|
73 | 72 | updateCurrentConfiguredBridgePref(preference)
|
74 | - preference.context.components.torController.restartTor()
|
|
75 | 73 | true
|
76 | 74 | }
|
77 | 75 | val userProvidedBridge: String? = context.components.torController.userProvidedBridges
|
... | ... | @@ -103,7 +101,6 @@ class TorBridgeConfigFragment : PreferenceFragmentCompat() { |
103 | 101 | preference.context.components.torController.bridgeTransport = bridge
|
104 | 102 | previousTransportConfig = bridge
|
105 | 103 | updateCurrentConfiguredBridgePref(preference)
|
106 | - preference.context.components.torController.restartTor()
|
|
107 | 104 | }
|
108 | 105 | true
|
109 | 106 | }
|
... | ... | @@ -27,20 +27,9 @@ class TorBootstrapProgressViewModel( |
27 | 27 | super.onCleared()
|
28 | 28 | }
|
29 | 29 | |
30 | - override fun onBootstrapStateChange(state: String?) {}
|
|
31 | 30 | override fun onBootstrapStageChange(stage: TorConnectStage) = Unit
|
32 | 31 | |
33 | 32 | override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) {
|
34 | 33 | this.progress.value = progress.toInt()
|
35 | 34 | }
|
36 | - |
|
37 | - override fun onBootstrapComplete() {}
|
|
38 | - |
|
39 | - override fun onBootstrapError(
|
|
40 | - code: String?,
|
|
41 | - message: String?,
|
|
42 | - phase: String?,
|
|
43 | - reason: String?,
|
|
44 | - ) {
|
|
45 | - }
|
|
46 | 35 | } |
... | ... | @@ -154,23 +154,12 @@ class TorConnectionAssistViewModel( |
154 | 154 | }
|
155 | 155 | }
|
156 | 156 | |
157 | - override fun onBootstrapStateChange(state: String?) {}
|
|
158 | - |
|
159 | - override fun onBootstrapStageChange(stage: TorConnectStage?) {
|
|
157 | + override fun onBootstrapStageChange(stage: TorConnectStage) {
|
|
160 | 158 | torConnectStage.value = stage
|
161 | 159 | }
|
162 | 160 | |
163 | 161 | override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) {}
|
164 | 162 | |
165 | - override fun onBootstrapComplete() {}
|
|
166 | - |
|
167 | - override fun onBootstrapError(
|
|
168 | - code: String?,
|
|
169 | - message: String?,
|
|
170 | - phase: String?,
|
|
171 | - reason: String?,
|
|
172 | - ) {}
|
|
173 | - |
|
174 | 163 | fun button1ShouldBeDisabled(screen: ConnectAssistUiState): Boolean {
|
175 | 164 | return selectedCountryCode.value == "automatic" && screen.regionDropDownDefaultItem == R.string.connection_assist_select_country_or_region
|
176 | 165 | }
|
... | ... | @@ -6,37 +6,14 @@ package org.mozilla.fenix.tor |
6 | 6 | |
7 | 7 | import androidx.lifecycle.LifecycleCoroutineScope
|
8 | 8 | |
9 | -interface TorEvents {
|
|
10 | - fun onTorConnecting()
|
|
11 | - fun onTorConnected()
|
|
12 | - fun onTorStatusUpdate(entry: String?, status: String?, progress: Double? = 0.0)
|
|
13 | - fun onTorStopped()
|
|
9 | +// Callback for function to be run one time when the system is bootstrapped and then disregarded
|
|
10 | +interface RunOnceBootstrapped {
|
|
11 | + fun onBootstrapped()
|
|
14 | 12 | }
|
15 | -class TorError(
|
|
16 | - var message: String,
|
|
17 | - var details: String,
|
|
18 | - var phase: String,
|
|
19 | - var reason: String,
|
|
20 | -) { }
|
|
21 | 13 | |
22 | -interface TorLogs {
|
|
23 | - fun onLog(type: String?, message: String?, timestamp: String?)
|
|
24 | -}
|
|
25 | - |
|
26 | -internal enum class TorStatus(val status: String) {
|
|
27 | - OFF("OFF"),
|
|
28 | - STARTING("STARTING"),
|
|
29 | - ON("ON"),
|
|
30 | - STOPPING("STOPPING"),
|
|
31 | - UNKNOWN("UNKNOWN");
|
|
32 | -}
|
|
33 | - |
|
34 | -interface TorController: TorEvents {
|
|
14 | +interface TorController {
|
|
35 | 15 | val logEntries: MutableList<TorLog>
|
36 | - val isStarting: Boolean
|
|
37 | - val isRestarting: Boolean
|
|
38 | 16 | val isBootstrapped: Boolean
|
39 | - val isConnected: Boolean
|
|
40 | 17 | var bridgesEnabled: Boolean
|
41 | 18 | var bridgeTransport: TorBridgeTransportConfig
|
42 | 19 | var userProvidedBridges: String?
|
... | ... | @@ -44,21 +21,21 @@ interface TorController: TorEvents { |
44 | 21 | fun start()
|
45 | 22 | fun stop()
|
46 | 23 | |
47 | - override fun onTorConnecting()
|
|
48 | - override fun onTorConnected()
|
|
49 | - override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?)
|
|
50 | - override fun onTorStopped()
|
|
51 | - |
|
52 | - fun getLastErrorState() : TorError?
|
|
53 | - |
|
54 | - fun registerTorListener(l: TorEvents)
|
|
55 | - fun unregisterTorListener(l: TorEvents)
|
|
56 | - |
|
57 | - fun registerTorLogListener(l: TorLogs)
|
|
58 | - fun unregisterTorLogListener(l: TorLogs)
|
|
24 | + // TorBrowserFeatures.install wants to register a callback for when tor bootstraps the first time
|
|
25 | + // so it can then check for noscript updates.
|
|
26 | + // Currently it needs to register it before TorAndroidIntegration is fully loaded, so this way
|
|
27 | + // they can register with TorController which will start streaming events from TAS when available
|
|
28 | + // and call them one time when the system is bootstrapped
|
|
29 | + // TODO: rewire the noscript update call in TorBrowserFeatures.install
|
|
30 | + // a) call TorBrowserFeatures.install from somewhere else (ex: move from Core.GeckoEngine.also
|
|
31 | + // to maybe FenixApplication.setupInMainProcessOnly
|
|
32 | + // dan: had trouble with this first time:
|
|
33 | + // https://gitlab.torproject.org/tpo/applications/tor-browser/-/merge_requests/1423#note_3191590
|
|
34 | + // b) just move the call to `context.components.addonUpdater.update(NOSCRIPT_ID)` somewhere else
|
|
35 | + // that can use TorAndroidIntegration.BootstrapListener
|
|
36 | + fun registerRunOnceBootstrapped(rob: RunOnceBootstrapped)
|
|
37 | + fun unregisterRunOnceBootstrapped(rob: RunOnceBootstrapped)
|
|
59 | 38 | |
60 | 39 | fun initiateTorBootstrap(lifecycleScope: LifecycleCoroutineScope? = null, withDebugLogging: Boolean = false)
|
61 | 40 | fun stopTor()
|
62 | - fun setTorStopped()
|
|
63 | - fun restartTor()
|
|
64 | 41 | } |
... | ... | @@ -4,75 +4,30 @@ package org.mozilla.fenix.tor |
4 | 4 | import android.content.Context
|
5 | 5 | import android.util.Log
|
6 | 6 | import androidx.lifecycle.LifecycleCoroutineScope
|
7 | -import kotlinx.coroutines.flow.MutableStateFlow
|
|
8 | -import kotlinx.coroutines.flow.StateFlow
|
|
9 | 7 | import mozilla.components.browser.engine.gecko.GeckoEngine
|
10 | 8 | import org.mozilla.fenix.ext.components
|
11 | 9 | import org.mozilla.geckoview.TorAndroidIntegration
|
12 | 10 | import org.mozilla.geckoview.TorAndroidIntegration.BootstrapStateChangeListener
|
13 | 11 | import org.mozilla.geckoview.TorAndroidIntegration.TorLogListener
|
14 | 12 | import org.mozilla.geckoview.TorConnectStage
|
13 | +import org.mozilla.geckoview.TorConnectStageName
|
|
15 | 14 | import org.mozilla.geckoview.TorSettings
|
16 | 15 | import org.mozilla.geckoview.TorSettings.BridgeBuiltinType
|
17 | 16 | import org.mozilla.geckoview.TorSettings.BridgeSource
|
18 | 17 | |
19 | -// Enum matching TorConnectState from TorConnect.sys.mjs that we get from onBootstrapStateChange
|
|
20 | -internal enum class TorConnectState(val state: String) {
|
|
21 | - Initial("Initial"),
|
|
22 | - Configuring("Configuring"),
|
|
23 | - AutoBootstrapping("AutoBootstrapping"),
|
|
24 | - Bootstrapping("Bootstrapping"),
|
|
25 | - Error("Error"),
|
|
26 | - Bootstrapped("Bootstrapped"),
|
|
27 | - Disabled("Disabled");
|
|
28 | - |
|
29 | - fun isStarting() = this == Bootstrapping || this == AutoBootstrapping
|
|
30 | - fun isError() = this == Error
|
|
31 | - |
|
32 | - fun isStarted() = this == Bootstrapped
|
|
33 | - |
|
34 | - fun isOff() = this == Initial || this == Configuring || this == Disabled || this == Error
|
|
35 | - |
|
36 | - |
|
37 | - // Convert to TorStatus that firefox-android uses based on tor-android-service
|
|
38 | - fun toTorStatus(): TorStatus {
|
|
39 | - return when (this) {
|
|
40 | - Initial -> TorStatus.OFF
|
|
41 | - Configuring -> TorStatus.OFF
|
|
42 | - AutoBootstrapping -> TorStatus.STARTING
|
|
43 | - Bootstrapping -> TorStatus.STARTING
|
|
44 | - Error -> TorStatus.UNKNOWN
|
|
45 | - Bootstrapped -> TorStatus.ON
|
|
46 | - Disabled -> TorStatus.OFF
|
|
47 | - }
|
|
48 | - }
|
|
49 | -}
|
|
50 | - |
|
51 | 18 | class TorControllerGV(
|
52 | 19 | private val context: Context,
|
53 | -) : TorController, TorEvents, BootstrapStateChangeListener, TorLogListener {
|
|
20 | +) : TorController, BootstrapStateChangeListener, TorLogListener {
|
|
54 | 21 | |
55 | 22 | private val TAG = "TorControllerGV"
|
56 | 23 | |
57 | - private var torListeners = mutableListOf<TorEvents>()
|
|
58 | - private var torLogListeners = mutableListOf<TorLogs>()
|
|
59 | - |
|
60 | - private val _lastKnownStatus = MutableStateFlow(TorConnectState.Initial)
|
|
61 | - internal val lastKnownStatus: StateFlow<TorConnectState> = _lastKnownStatus
|
|
24 | + private var runOnceBootstrappedHandlers = mutableListOf<RunOnceBootstrapped>()
|
|
62 | 25 | |
63 | - internal var lastKnownError: TorError? = null
|
|
64 | - private var wasTorBootstrapped = false
|
|
65 | - private var isTorRestarting = false
|
|
66 | - |
|
67 | - private var isTorBootstrapped = false
|
|
68 | - get() = ((_lastKnownStatus.value.isStarted()) && wasTorBootstrapped)
|
|
26 | + override val isBootstrapped get() =
|
|
27 | + getTorIntegration().lastKnowStage.value?.name?.isBootstrapped ?: false
|
|
69 | 28 | |
70 | 29 | private val entries = mutableListOf<TorLog>()
|
71 | 30 | override val logEntries get() = entries
|
72 | - override val isStarting get() = _lastKnownStatus.value.isStarting()
|
|
73 | - override val isRestarting get() = isTorRestarting
|
|
74 | - override val isBootstrapped get() = isTorBootstrapped
|
|
75 | - override val isConnected get() = (_lastKnownStatus.value.isStarted() && !isTorRestarting)
|
|
76 | 31 | |
77 | 32 | private fun getTorIntegration(): TorAndroidIntegration {
|
78 | 33 | return (context.components.core.engine as GeckoEngine).getTorIntegrationController()
|
... | ... | @@ -82,8 +37,7 @@ class TorControllerGV( |
82 | 37 | return getTorIntegration().getSettings()
|
83 | 38 | }
|
84 | 39 | |
85 | - |
|
86 | - // On a fresh install bridgeEnagled can be set to true without a valid bridgeSource
|
|
40 | + // On a fresh install bridgeEnabled can be set to true without a valid bridgeSource
|
|
87 | 41 | // having been selected. After first use this will not happen because last selected bridge
|
88 | 42 | // will be remembered and reused.
|
89 | 43 | // However, on first use, submitting this to TorSettings is an invalid state.
|
... | ... | @@ -105,7 +59,6 @@ class TorControllerGV( |
105 | 59 | }
|
106 | 60 | }
|
107 | 61 | |
108 | - |
|
109 | 62 | override var bridgeTransport: TorBridgeTransportConfig
|
110 | 63 | get() {
|
111 | 64 | return when (getTorSettings()?.bridgesSource) {
|
... | ... | @@ -144,7 +97,6 @@ class TorControllerGV( |
144 | 97 | }
|
145 | 98 | }
|
146 | 99 | |
147 | - |
|
148 | 100 | // Currently the UI takes a user provided string and sets this in one step so there is where we
|
149 | 101 | // actually set it.bridgesSource = BridgeSource.UserProvided, not above,
|
150 | 102 | // as TorSettings.sys.mjs #cleanupSettings could reject BridgeSource.UserProvided
|
... | ... | @@ -179,73 +131,37 @@ class TorControllerGV( |
179 | 131 | getTorIntegration().unregisterLogListener(this)
|
180 | 132 | }
|
181 | 133 | |
182 | - // TorEvents
|
|
183 | - override fun onTorConnecting() {
|
|
184 | - synchronized(torListeners) {
|
|
185 | - torListeners.toList().forEach { it.onTorConnecting() }
|
|
186 | - }
|
|
187 | - }
|
|
188 | - |
|
189 | - // TorEvents
|
|
190 | - override fun onTorConnected() {
|
|
191 | - synchronized(torListeners) {
|
|
192 | - torListeners.toList().forEach { it.onTorConnected() }
|
|
193 | - }
|
|
194 | - }
|
|
195 | - |
|
196 | - // TorEvents
|
|
197 | - override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) {
|
|
198 | - synchronized(torListeners) {
|
|
199 | - torListeners.toList().forEach { it.onTorStatusUpdate(entry, status, progress) }
|
|
200 | - }
|
|
201 | - }
|
|
202 | - |
|
203 | - // TorEvents
|
|
204 | - override fun onTorStopped() {
|
|
205 | - synchronized(torListeners) {
|
|
206 | - torListeners.toList().forEach { it.onTorStopped() }
|
|
207 | - }
|
|
208 | - }
|
|
209 | - |
|
210 | 134 | override fun onLog(type: String?, message: String?, timestamp: String?) {
|
211 | - synchronized(torLogListeners) {
|
|
135 | + synchronized(entries) {
|
|
212 | 136 | entries.add(TorLog(type ?: "null", message ?: "null", timestamp ?: "null"))
|
213 | - torLogListeners.toList().forEach { it.onLog(type ?: "null", message ?: "null", timestamp) }
|
|
214 | - }
|
|
215 | - }
|
|
216 | - |
|
217 | - override fun registerTorListener(l: TorEvents) {
|
|
218 | - synchronized(torListeners) {
|
|
219 | - if (torListeners.contains(l)) {
|
|
220 | - return
|
|
221 | - }
|
|
222 | - torListeners.add(l)
|
|
223 | 137 | }
|
224 | 138 | }
|
225 | 139 | |
226 | - override fun unregisterTorListener(l: TorEvents) {
|
|
227 | - synchronized(torListeners) {
|
|
228 | - if (!torListeners.contains(l)) {
|
|
140 | + override fun registerRunOnceBootstrapped(rob: RunOnceBootstrapped) {
|
|
141 | + // TODO Remove need for this with tb-44002
|
|
142 | + // it would be nice to have a short circuit run and don't add if already bootstrapped
|
|
143 | + // however this calls context.components.core.engine which tries to lazy load engine
|
|
144 | + // which causes a recursive loop. instead we should do the work in tb-44002
|
|
145 | + // this is currently fine as there is a single use case for this called in
|
|
146 | + // TorBrowserFeatures that is at startup
|
|
147 | + //if (isBootstrapped) {
|
|
148 | + // rob.onBootstrapped()
|
|
149 | + // return
|
|
150 | + //}
|
|
151 | + synchronized(runOnceBootstrappedHandlers) {
|
|
152 | + if (runOnceBootstrappedHandlers.contains(rob)) {
|
|
229 | 153 | return
|
230 | 154 | }
|
231 | - torListeners.remove(l)
|
|
155 | + runOnceBootstrappedHandlers.add(rob)
|
|
232 | 156 | }
|
233 | 157 | }
|
234 | 158 | |
235 | - override fun registerTorLogListener(l: TorLogs) {
|
|
236 | - synchronized(torLogListeners) {
|
|
237 | - if (torLogListeners.contains(l)) {
|
|
238 | - return
|
|
239 | - }
|
|
240 | - torLogListeners.add(l)
|
|
241 | - }
|
|
242 | - }
|
|
243 | - override fun unregisterTorLogListener(l: TorLogs) {
|
|
244 | - synchronized(torLogListeners) {
|
|
245 | - if (!torLogListeners.contains(l)) {
|
|
159 | + override fun unregisterRunOnceBootstrapped(rob: RunOnceBootstrapped) {
|
|
160 | + synchronized(runOnceBootstrappedHandlers) {
|
|
161 | + if (!runOnceBootstrappedHandlers.contains(rob)) {
|
|
246 | 162 | return
|
247 | 163 | }
|
248 | - torLogListeners.remove(l)
|
|
164 | + runOnceBootstrappedHandlers.remove(rob)
|
|
249 | 165 | }
|
250 | 166 | }
|
251 | 167 | |
... | ... | @@ -260,82 +176,22 @@ class TorControllerGV( |
260 | 176 | getTorIntegration().cancelBootstrap()
|
261 | 177 | }
|
262 | 178 | |
263 | - override fun setTorStopped() {
|
|
264 | - _lastKnownStatus.value = TorConnectState.Configuring
|
|
265 | - onTorStatusUpdate(null, lastKnownStatus.toString(), 0.0)
|
|
266 | - onTorStopped()
|
|
267 | - }
|
|
268 | - |
|
269 | - override fun restartTor() {
|
|
270 | - if (!_lastKnownStatus.value.isStarted() && wasTorBootstrapped) {
|
|
271 | - // If we aren't started, but we were previously bootstrapped,
|
|
272 | - // then we handle a "restart" request as a "start" restart
|
|
273 | - initiateTorBootstrap()
|
|
274 | - } else {
|
|
275 | - // |isTorRestarting| tracks the state of restart. When we receive an |OFF| state
|
|
276 | - // from TorService in persistentBroadcastReceiver::onReceive we restart the Tor
|
|
277 | - // service.
|
|
278 | - isTorRestarting = true
|
|
279 | - stopTor()
|
|
280 | - }
|
|
281 | - }
|
|
282 | - |
|
283 | - override fun getLastErrorState() : TorError? {
|
|
284 | - return lastKnownError
|
|
285 | - }
|
|
286 | - |
|
287 | - // TorEventsBootstrapStateChangeListener -> (lastKnowStatus, TorEvents)
|
|
288 | - // Handle events from GeckoView TorAndroidIntegration and map to TorEvents based events
|
|
289 | - // and state for firefox-android (designed for tor-android-service)
|
|
290 | - // fun onTorConnecting()
|
|
291 | - // fun onTorConnected()
|
|
292 | - // fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?)
|
|
293 | - // fun onTorStopped()
|
|
294 | - |
|
295 | 179 | // TorEventsBootstrapStateChangeListener
|
296 | - override fun onBootstrapStateChange(newStateVal: String?) {
|
|
297 | - Log.d(TAG, "onBootstrapStateChange(newStateVal = $newStateVal)")
|
|
298 | - val newState: TorConnectState = TorConnectState.valueOf(newStateVal ?: "Error")
|
|
299 | - |
|
300 | - if (newState.isError() && wasTorBootstrapped) {
|
|
301 | - stopTor()
|
|
302 | - }
|
|
303 | - |
|
304 | - if (newState.isStarted()) {
|
|
305 | - wasTorBootstrapped = true
|
|
306 | - onTorConnected()
|
|
307 | - }
|
|
308 | - |
|
309 | - if (wasTorBootstrapped && newState == TorConnectState.Configuring) {
|
|
310 | - wasTorBootstrapped = false
|
|
311 | - if (isTorRestarting) {
|
|
312 | - initiateTorBootstrap()
|
|
313 | - } else {
|
|
314 | - setTorStopped()
|
|
180 | + override fun onBootstrapStageChange(stage: TorConnectStage) {
|
|
181 | + Log.d(TAG, "onBootstrapStageChange(stage = $stage)")
|
|
182 | + |
|
183 | + if (stage.name == TorConnectStageName.Bootstrapped) {
|
|
184 | + synchronized(runOnceBootstrappedHandlers) {
|
|
185 | + runOnceBootstrappedHandlers.toList().forEach {
|
|
186 | + it.onBootstrapped()
|
|
187 | + runOnceBootstrappedHandlers.remove(it)
|
|
188 | + }
|
|
315 | 189 | }
|
316 | 190 | }
|
317 | - |
|
318 | - if (_lastKnownStatus.value.isOff() && newState.isStarting()) {
|
|
319 | - isTorRestarting = false
|
|
320 | - }
|
|
321 | - |
|
322 | - _lastKnownStatus.value = newState
|
|
323 | - onTorStatusUpdate(null, newStateVal, null)
|
|
324 | 191 | }
|
325 | 192 | |
326 | - override fun onBootstrapStageChange(stage: TorConnectStage) = Unit
|
|
327 | - |
|
328 | 193 | // TorEventsBootstrapStateChangeListener
|
329 | 194 | override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) {
|
330 | 195 | Log.d(TAG, "onBootstrapProgress(progress = $progress, hasWarnings = $hasWarnings)")
|
331 | - onTorStatusUpdate("", _lastKnownStatus.value.toTorStatus().status, progress)
|
|
332 | - }
|
|
333 | - |
|
334 | - // TorEventsBootstrapStateChangeListener
|
|
335 | - override fun onBootstrapComplete() = Unit
|
|
336 | - |
|
337 | - // TorEventsBootstrapStateChangeListener
|
|
338 | - override fun onBootstrapError(code: String?, message: String?, phase: String?, reason: String?) {
|
|
339 | - lastKnownError = TorError(code ?: "", message ?: "", phase ?: "", reason ?: "")
|
|
340 | 196 | }
|
341 | 197 | } |
... | ... | @@ -13,11 +13,15 @@ import android.widget.Toast |
13 | 13 | import androidx.lifecycle.AndroidViewModel
|
14 | 14 | import androidx.lifecycle.LiveData
|
15 | 15 | import androidx.lifecycle.MutableLiveData
|
16 | +import mozilla.components.browser.engine.gecko.GeckoEngine
|
|
16 | 17 | import org.mozilla.fenix.R
|
17 | 18 | import org.mozilla.fenix.ext.components
|
19 | +import org.mozilla.geckoview.TorAndroidIntegration.TorLogListener
|
|
18 | 20 | |
19 | -class TorLogsViewModel(application: Application) : AndroidViewModel(application), TorLogs {
|
|
21 | +class TorLogsViewModel(application: Application) : AndroidViewModel(application), TorLogListener {
|
|
20 | 22 | private val torController = application.components.torController
|
23 | + private val engine = application.components.core.engine as GeckoEngine
|
|
24 | + private val torAndroidIntegration = engine.getTorIntegrationController()
|
|
21 | 25 | private val clipboardManager =
|
22 | 26 | application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
23 | 27 | |
... | ... | @@ -33,7 +37,7 @@ class TorLogsViewModel(application: Application) : AndroidViewModel(application) |
33 | 37 | |
34 | 38 | init {
|
35 | 39 | setupClipboardListener()
|
36 | - torController.registerTorLogListener(this)
|
|
40 | + torAndroidIntegration.registerLogListener(this)
|
|
37 | 41 | val currentEntries = torController.logEntries
|
38 | 42 | for (log in currentEntries) {
|
39 | 43 | addLog(log)
|
... | ... | @@ -46,7 +50,7 @@ class TorLogsViewModel(application: Application) : AndroidViewModel(application) |
46 | 50 | |
47 | 51 | override fun onCleared() {
|
48 | 52 | super.onCleared()
|
49 | - torController.unregisterTorLogListener(this)
|
|
53 | + torAndroidIntegration.unregisterLogListener(this)
|
|
50 | 54 | }
|
51 | 55 | |
52 | 56 | private fun setupClipboardListener() {
|
... | ... | @@ -39,11 +39,8 @@ public class TorAndroidIntegration implements BundleEventListener { |
39 | 39 | private static final String EVENT_TOR_STOP = "GeckoView:Tor:StopTor";
|
40 | 40 | private static final String EVENT_MEEK_START = "GeckoView:Tor:StartMeek";
|
41 | 41 | private static final String EVENT_MEEK_STOP = "GeckoView:Tor:StopMeek";
|
42 | - private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged"; // deprecation path
|
|
43 | - private static final String EVENT_CONNECT_STAGE_CHANGED = "GeckoView:Tor:ConnectStageChanged"; // replacement path
|
|
44 | - private static final String EVENT_CONNECT_ERROR = "GeckoView:Tor:ConnectError";
|
|
42 | + private static final String EVENT_CONNECT_STAGE_CHANGED = "GeckoView:Tor:ConnectStageChanged";
|
|
45 | 43 | private static final String EVENT_BOOTSTRAP_PROGRESS = "GeckoView:Tor:BootstrapProgress";
|
46 | - private static final String EVENT_BOOTSTRAP_COMPLETE = "GeckoView:Tor:BootstrapComplete";
|
|
47 | 44 | private static final String EVENT_TOR_LOGS = "GeckoView:Tor:Logs";
|
48 | 45 | private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady";
|
49 | 46 | private static final String EVENT_SETTINGS_CHANGED = "GeckoView:Tor:SettingsChanged";
|
... | ... | @@ -62,6 +59,7 @@ public class TorAndroidIntegration implements BundleEventListener { |
62 | 59 | private static final String EVENT_QUICKSTART_GET = "GeckoView:Tor:QuickstartGet";
|
63 | 60 | private static final String EVENT_QUICKSTART_SET = "GeckoView:Tor:QuickstartSet";
|
64 | 61 | private static final String EVENT_REGION_NAMES_GET = "GeckoView:Tor:RegionNamesGet";
|
62 | + private static final String EVENT_SHOULD_SHOW_TOR_CONNECT = "GeckoView:Tor:ShouldShowTorConnect";
|
|
65 | 63 | |
66 | 64 | private static final String CONTROL_PORT_FILE = "/control-ipc";
|
67 | 65 | private static final String SOCKS_FILE = "/socks-ipc";
|
... | ... | @@ -124,11 +122,8 @@ public class TorAndroidIntegration implements BundleEventListener { |
124 | 122 | EVENT_MEEK_STOP,
|
125 | 123 | EVENT_SETTINGS_READY,
|
126 | 124 | EVENT_SETTINGS_CHANGED,
|
127 | - EVENT_CONNECT_STATE_CHANGED,
|
|
128 | 125 | EVENT_CONNECT_STAGE_CHANGED,
|
129 | - EVENT_CONNECT_ERROR,
|
|
130 | 126 | EVENT_BOOTSTRAP_PROGRESS,
|
131 | - EVENT_BOOTSTRAP_COMPLETE,
|
|
132 | 127 | EVENT_TOR_LOGS);
|
133 | 128 | }
|
134 | 129 | |
... | ... | @@ -157,35 +152,18 @@ public class TorAndroidIntegration implements BundleEventListener { |
157 | 152 | } else {
|
158 | 153 | Log.w(TAG, "Ignoring a settings changed event that did not have the new settings.");
|
159 | 154 | }
|
160 | - } else if (EVENT_CONNECT_STATE_CHANGED.equals(event)) {
|
|
161 | - String state = message.getString("state");
|
|
162 | - for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
|
|
163 | - listener.onBootstrapStateChange(state);
|
|
164 | - }
|
|
165 | 155 | } else if (EVENT_CONNECT_STAGE_CHANGED.equals(event)) {
|
166 | 156 | TorConnectStage stage = new TorConnectStage(message.getBundle("stage"));
|
167 | 157 | _lastKnownStage.setValue(stage);
|
168 | 158 | for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
|
169 | 159 | listener.onBootstrapStageChange(stage);
|
170 | 160 | }
|
171 | - } else if (EVENT_CONNECT_ERROR.equals(event)) {
|
|
172 | - String code = message.getString("code");
|
|
173 | - String msg = message.getString("message");
|
|
174 | - String phase = message.getString("phase");
|
|
175 | - String reason = message.getString("reason");
|
|
176 | - for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
|
|
177 | - listener.onBootstrapError(code, msg, phase, reason);
|
|
178 | - }
|
|
179 | 161 | } else if (EVENT_BOOTSTRAP_PROGRESS.equals(event)) {
|
180 | 162 | double progress = message.getDouble("progress");
|
181 | 163 | boolean hasWarnings = message.getBoolean("hasWarnings");
|
182 | 164 | for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
|
183 | 165 | listener.onBootstrapProgress(progress, hasWarnings);
|
184 | 166 | }
|
185 | - } else if (EVENT_BOOTSTRAP_COMPLETE.equals(event)) {
|
|
186 | - for (BootstrapStateChangeListener listener : mBootstrapStateListeners) {
|
|
187 | - listener.onBootstrapComplete();
|
|
188 | - }
|
|
189 | 167 | } else if (EVENT_TOR_LOGS.equals(event)) {
|
190 | 168 | String msg = message.getString("message");
|
191 | 169 | String type = message.getString("logType");
|
... | ... | @@ -647,15 +625,9 @@ public class TorAndroidIntegration implements BundleEventListener { |
647 | 625 | }
|
648 | 626 | |
649 | 627 | public interface BootstrapStateChangeListener {
|
650 | - void onBootstrapStateChange(String state); // depreaction path
|
|
651 | - |
|
652 | - void onBootstrapStageChange(TorConnectStage stage); // new upgrade
|
|
628 | + void onBootstrapStageChange(@NonNull TorConnectStage stage); // new upgrade
|
|
653 | 629 | |
654 | 630 | void onBootstrapProgress(double progress, boolean hasWarnings);
|
655 | - |
|
656 | - void onBootstrapComplete();
|
|
657 | - |
|
658 | - void onBootstrapError(String code, String message, String phase, String reason);
|
|
659 | 631 | }
|
660 | 632 | |
661 | 633 | public interface TorLogListener {
|
... | ... | @@ -736,6 +708,17 @@ public class TorAndroidIntegration implements BundleEventListener { |
736 | 708 | });
|
737 | 709 | }
|
738 | 710 | |
711 | + public interface ShouldShowTorConnectGetter {
|
|
712 | + void onValue(Boolean shouldShowTorConnect);
|
|
713 | + }
|
|
714 | + |
|
715 | + public void shouldShowTorConnectGet(ShouldShowTorConnectGetter shouldShowTorConnectGetter) {
|
|
716 | + EventDispatcher.getInstance().queryBoolean(EVENT_SHOULD_SHOW_TOR_CONNECT).then(shouldShowTorConnect -> {
|
|
717 | + shouldShowTorConnectGetter.onValue(shouldShowTorConnect);
|
|
718 | + return new GeckoResult<Void>();
|
|
719 | + });
|
|
720 | + }
|
|
721 | + |
|
739 | 722 | public @NonNull GeckoResult<Void> beginBootstrap() {
|
740 | 723 | return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN);
|
741 | 724 | }
|
... | ... | @@ -754,21 +737,21 @@ public class TorAndroidIntegration implements BundleEventListener { |
754 | 737 | return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_CANCEL);
|
755 | 738 | }
|
756 | 739 | |
757 | - public void registerBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
|
|
740 | + public synchronized void registerBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
|
|
758 | 741 | mBootstrapStateListeners.add(listener);
|
759 | 742 | }
|
760 | 743 | |
761 | - public void unregisterBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
|
|
744 | + public synchronized void unregisterBootstrapStateChangeListener(BootstrapStateChangeListener listener) {
|
|
762 | 745 | mBootstrapStateListeners.remove(listener);
|
763 | 746 | }
|
764 | 747 | |
765 | 748 | private final HashSet<BootstrapStateChangeListener> mBootstrapStateListeners = new HashSet<>();
|
766 | 749 | |
767 | - public void registerLogListener(TorLogListener listener) {
|
|
750 | + public synchronized void registerLogListener(TorLogListener listener) {
|
|
768 | 751 | mLogListeners.add(listener);
|
769 | 752 | }
|
770 | 753 | |
771 | - public void unregisterLogListener(TorLogListener listener) {
|
|
754 | + public synchronized void unregisterLogListener(TorLogListener listener) {
|
|
772 | 755 | mLogListeners.remove(listener);
|
773 | 756 | }
|
774 | 757 |
1 | +package org.mozilla.geckoview;
|
|
2 | + |
|
3 | +import org.mozilla.gecko.util.GeckoBundle;
|
|
4 | + |
|
5 | +public class TorConnectError {
|
|
6 | + public String code;
|
|
7 | + public String message;
|
|
8 | + public String phase;
|
|
9 | + public String reason;
|
|
10 | + |
|
11 | + public TorConnectError(GeckoBundle bundle) {
|
|
12 | + code = bundle.getString("code");
|
|
13 | + message = bundle.getString("message");
|
|
14 | + phase = bundle.getString("phase");
|
|
15 | + reason = bundle.getString("reason");
|
|
16 | + }
|
|
17 | + |
|
18 | + public TorConnectError(String code, String message, String phase, String reason) {
|
|
19 | + this.code = code;
|
|
20 | + this.message = message;
|
|
21 | + this.phase = phase;
|
|
22 | + this.reason = reason;
|
|
23 | + }
|
|
24 | +} |
... | ... | @@ -5,24 +5,10 @@ import org.mozilla.gecko.util.GeckoBundle; |
5 | 5 | // Class to receive ConnectStage object from TorConnect.sys.mjs ~ln677
|
6 | 6 | public class TorConnectStage {
|
7 | 7 | |
8 | - public class Error {
|
|
9 | - public String code;
|
|
10 | - public String message;
|
|
11 | - public String phase;
|
|
12 | - public String reason;
|
|
13 | - |
|
14 | - public Error(GeckoBundle bundle) {
|
|
15 | - code = bundle.getString("code");
|
|
16 | - message = bundle.getString("message");
|
|
17 | - phase = bundle.getString("phase");
|
|
18 | - reason = bundle.getString("reason");
|
|
19 | - }
|
|
20 | - }
|
|
21 | - |
|
22 | 8 | public TorConnectStageName name;
|
23 | 9 | // The TorConnectStage prior to this bootstrap attempt. Only set during the "Bootstrapping" stage.
|
24 | 10 | public TorConnectStageName bootstrapTrigger;
|
25 | - public Error error;
|
|
11 | + public TorConnectError error;
|
|
26 | 12 | public String defaultRegion;
|
27 | 13 | public Boolean potentiallyBlocked;
|
28 | 14 | public Boolean tryAgain;
|
... | ... | @@ -37,7 +23,7 @@ public class TorConnectStage { |
37 | 23 | potentiallyBlocked = bundle.getBoolean("potentiallyBlocked");
|
38 | 24 | tryAgain = bundle.getBoolean("tryAgain");
|
39 | 25 | if (bundle.getBundle("error") != null) {
|
40 | - error = new Error(bundle.getBundle("error"));
|
|
26 | + error = new TorConnectError(bundle.getBundle("error"));
|
|
41 | 27 | }
|
42 | 28 | bootstrappingStatus = new TorBootstrappingStatus(bundle.getBundle("bootstrappingStatus"));
|
43 | 29 | }
|
... | ... | @@ -28,7 +28,6 @@ const EmittedEvents = Object.freeze({ |
28 | 28 | settingsChanged: "GeckoView:Tor:SettingsChanged",
|
29 | 29 | connectStateChanged: "GeckoView:Tor:ConnectStateChanged", // deprecation path
|
30 | 30 | connectStageChanged: "GeckoView:Tor:ConnectStageChanged", // new replacement path
|
31 | - connectError: "GeckoView:Tor:ConnectError",
|
|
32 | 31 | bootstrapProgress: "GeckoView:Tor:BootstrapProgress",
|
33 | 32 | bootstrapComplete: "GeckoView:Tor:BootstrapComplete",
|
34 | 33 | torLogs: "GeckoView:Tor:Logs",
|
... | ... | @@ -49,6 +48,7 @@ const ListenedEvents = Object.freeze({ |
49 | 48 | quickstartGet: "GeckoView:Tor:QuickstartGet",
|
50 | 49 | quickstartSet: "GeckoView:Tor:QuickstartSet",
|
51 | 50 | regionNamesGet: "GeckoView:Tor:RegionNamesGet",
|
51 | + shouldShowTorConnectGet: "GeckoView:Tor:ShouldShowTorConnect",
|
|
52 | 52 | });
|
53 | 53 | |
54 | 54 | class TorAndroidIntegrationImpl {
|
... | ... | @@ -134,16 +134,6 @@ class TorAndroidIntegrationImpl { |
134 | 134 | type: EmittedEvents.bootstrapComplete,
|
135 | 135 | });
|
136 | 136 | break;
|
137 | - // TODO: Replace with StageChange stage.error.
|
|
138 | - case lazy.TorConnectTopics.Error:
|
|
139 | - lazy.EventDispatcher.instance.sendRequest({
|
|
140 | - type: EmittedEvents.connectError,
|
|
141 | - code: subj.wrappedJSObject.code ?? "",
|
|
142 | - message: subj.wrappedJSObject.message ?? "",
|
|
143 | - phase: subj.wrappedJSObject.cause?.phase ?? "",
|
|
144 | - reason: subj.wrappedJSObject.cause?.reason ?? "",
|
|
145 | - });
|
|
146 | - break;
|
|
147 | 137 | case lazy.TorProviderTopics.TorLog:
|
148 | 138 | lazy.EventDispatcher.instance.sendRequest({
|
149 | 139 | type: EmittedEvents.torLogs,
|
... | ... | @@ -225,6 +215,9 @@ class TorAndroidIntegrationImpl { |
225 | 215 | case ListenedEvents.regionNamesGet:
|
226 | 216 | callback?.onSuccess(lazy.TorConnect.getRegionNames());
|
227 | 217 | return;
|
218 | + case ListenedEvents.shouldShowTorConnectGet:
|
|
219 | + callback?.onSuccess(lazy.TorConnect.shouldShowTorConnect());
|
|
220 | + return;
|
|
228 | 221 | }
|
229 | 222 | callback?.onSuccess();
|
230 | 223 | } catch (e) {
|