Dan Ballard pushed to branch tor-browser-153.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
-
fe45b5e3
by Henry Wilkes at 2026-08-05T12:12:42-06:00
-
80e2704f
by Henry Wilkes at 2026-08-05T12:12:43-06:00
-
48c8f5a9
by clairehurst at 2026-08-05T12:12:43-06:00
-
ec776e7f
by clairehurst at 2026-08-05T12:12:43-06:00
-
45aace81
by clairehurst at 2026-08-05T12:12:44-06:00
-
1efdc3dc
by clairehurst at 2026-08-05T12:12:44-06:00
-
5b194faf
by clairehurst at 2026-08-05T12:13:48-06:00
21 changed files:
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/ConnectAssistUiState.kt
- + mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/ProviderStoppedViewModel.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistViewModel.kt
- + mobile/android/fenix/app/src/main/res/drawable/bullet_point.xml
- + mobile/android/fenix/app/src/main/res/drawable/loading_wheel.xml
- + mobile/android/fenix/app/src/main/res/drawable/onion_broken.xml
- mobile/android/fenix/app/src/main/res/layout/fragment_tor_connection_assist.xml
- mobile/android/fenix/app/src/main/res/navigation/nav_graph.xml
- mobile/android/fenix/app/src/main/res/values/preference_keys.xml
- mobile/android/fenix/app/src/main/res/values/torbrowser_strings.xml
- mobile/android/fenix/app/src/main/res/xml/secret_settings_preferences.xml
- + mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ProviderStatus.java
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorAndroidIntegration.java
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorConnectStage.java
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorConnectStageName.java
- toolkit/components/tor-launcher/TorProcessAndroid.sys.mjs
- toolkit/modules/TorAndroidIntegration.sys.mjs
- toolkit/modules/TorConnect.sys.mjs
Changes:
| ... | ... | @@ -7,6 +7,7 @@ package org.mozilla.fenix |
| 7 | 7 | import android.annotation.SuppressLint
|
| 8 | 8 | import android.app.assist.AssistContent
|
| 9 | 9 | import android.app.PendingIntent
|
| 10 | +import android.content.ActivityNotFoundException
|
|
| 10 | 11 | import android.content.ComponentName
|
| 11 | 12 | import android.content.Context
|
| 12 | 13 | import android.content.Intent
|
| ... | ... | @@ -19,6 +20,7 @@ import android.os.Bundle |
| 19 | 20 | import android.os.StrictMode
|
| 20 | 21 | import android.text.format.DateUtils
|
| 21 | 22 | import android.util.AttributeSet
|
| 23 | +import android.util.Log
|
|
| 22 | 24 | import android.view.ActionMode
|
| 23 | 25 | import android.view.KeyEvent
|
| 24 | 26 | import android.view.LayoutInflater
|
| ... | ... | @@ -40,7 +42,9 @@ import androidx.core.net.toUri |
| 40 | 42 | import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
| 41 | 43 | import androidx.core.text.layoutDirection
|
| 42 | 44 | import androidx.core.view.doOnLayout
|
| 45 | +import androidx.lifecycle.Lifecycle
|
|
| 43 | 46 | import androidx.lifecycle.lifecycleScope
|
| 47 | +import androidx.lifecycle.repeatOnLifecycle
|
|
| 44 | 48 | import androidx.navigation.NavController
|
| 45 | 49 | import androidx.navigation.NavDirections
|
| 46 | 50 | import androidx.navigation.fragment.NavHostFragment
|
| ... | ... | @@ -203,6 +207,7 @@ import org.mozilla.fenix.compose.snackbar.SnackbarState |
| 203 | 207 | import org.mozilla.fenix.compose.snackbar.Snackbar
|
| 204 | 208 | import org.mozilla.fenix.tor.CustomSecurityLevelViewModel
|
| 205 | 209 | import org.mozilla.fenix.tor.TorController
|
| 210 | +import org.mozilla.fenix.tor.ProviderStoppedViewModel
|
|
| 206 | 211 | import org.mozilla.fenix.tor.UrlQuickLoadViewModel
|
| 207 | 212 | import org.mozilla.geckoview.TorAndroidIntegration.BootstrapStateChangeListener
|
| 208 | 213 | import org.mozilla.geckoview.TorConnectStage
|
| ... | ... | @@ -436,6 +441,8 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, Crash |
| 436 | 441 | |
| 437 | 442 | private var dialog: RedirectDialogFragment? = null
|
| 438 | 443 | |
| 444 | + private val providerStoppedViewModel: ProviderStoppedViewModel by viewModels()
|
|
| 445 | + |
|
| 439 | 446 | private val urlQuickLoadViewModel: UrlQuickLoadViewModel by viewModels()
|
| 440 | 447 | |
| 441 | 448 | private val customSecurityLevelViewModel: CustomSecurityLevelViewModel by viewModels()
|
| ... | ... | @@ -445,6 +452,18 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, Crash |
| 445 | 452 | // DO NOT MOVE ANYTHING ABOVE THIS getProfilerTime CALL.
|
| 446 | 453 | val startTimeProfiler = components.core.engine.profiler?.getProfilerTime()
|
| 447 | 454 | |
| 455 | + lifecycleScope.launch {
|
|
| 456 | + repeatOnLifecycle(Lifecycle.State.STARTED) {
|
|
| 457 | + providerStoppedViewModel.providerStoppedStateFlow.collect { isStopped ->
|
|
| 458 | + Log.d("providerStoppedViewModel", "isStopped = $isStopped")
|
|
| 459 | + if (isStopped) {
|
|
| 460 | + navHost.navController.navigate(NavGraphDirections.actionNavigateToConnectionAssistFromAnywhere())
|
|
| 461 | + providerStoppedViewModel.providerStoppedStateFlow.value = false
|
|
| 462 | + }
|
|
| 463 | + }
|
|
| 464 | + }
|
|
| 465 | + }
|
|
| 466 | + |
|
| 448 | 467 | // Setup nimbus-cli tooling. This is a NOOP when launching normally.
|
| 449 | 468 | components.nimbus.sdk.initializeTooling(applicationContext, intent)
|
| 450 | 469 | components.strictMode.attachListenerToDisablePenaltyDeath(supportFragmentManager)
|
| ... | ... | @@ -1788,4 +1807,14 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, Crash |
| 1788 | 1807 | components.torController.shutdown()
|
| 1789 | 1808 | exitProcess(0)
|
| 1790 | 1809 | }
|
| 1810 | + |
|
| 1811 | + fun openBatterySaverSettings() {
|
|
| 1812 | + try {
|
|
| 1813 | + startActivity(
|
|
| 1814 | + Intent(android.provider.Settings.ACTION_BATTERY_SAVER_SETTINGS)
|
|
| 1815 | + )
|
|
| 1816 | + } catch (e: ActivityNotFoundException) {
|
|
| 1817 | + e.printStackTrace()
|
|
| 1818 | + }
|
|
| 1819 | + }
|
|
| 1791 | 1820 | } |
| ... | ... | @@ -265,6 +265,13 @@ class SecretSettingsFragment : PreferenceFragmentCompat(), SystemInsetsPaddedFra |
| 265 | 265 | }
|
| 266 | 266 | }
|
| 267 | 267 | |
| 268 | + requirePreference<Preference>(R.string.pref_key_test_kill_tor).apply {
|
|
| 269 | + setOnPreferenceClickListener {
|
|
| 270 | + requireContext().components.core.geckoRuntime.torIntegrationController.shutdown()
|
|
| 271 | + true
|
|
| 272 | + }
|
|
| 273 | + }
|
|
| 274 | + |
|
| 268 | 275 | requirePreference<SwitchPreferenceCompat>(R.string.pref_key_enable_fxsuggest).apply {
|
| 269 | 276 | isVisible = FeatureFlags.FX_SUGGEST
|
| 270 | 277 | isChecked = settings.enableFxSuggest
|
| ... | ... | @@ -3,8 +3,8 @@ package org.mozilla.fenix.tor |
| 3 | 3 | import androidx.annotation.ColorRes
|
| 4 | 4 | import androidx.annotation.DrawableRes
|
| 5 | 5 | import androidx.annotation.StringRes
|
| 6 | -import mozilla.components.lib.crash.R as crashR
|
|
| 7 | 6 | import org.mozilla.fenix.R
|
| 7 | +import mozilla.components.lib.crash.R as crashR
|
|
| 8 | 8 | |
| 9 | 9 | enum class ConnectAssistUiState(
|
| 10 | 10 | val progressBarVisible: Boolean,
|
| ... | ... | @@ -33,6 +33,7 @@ enum class ConnectAssistUiState( |
| 33 | 33 | val torBootstrapButton2ShouldOpenSettings: Boolean = true,
|
| 34 | 34 | val wordmarkLogoVisible: Boolean = false,
|
| 35 | 35 | val torBootstrapButton2ShouldRestartApp: Boolean = false,
|
| 36 | + val torBootstrapButton1ShouldRestartTor: Boolean = false,
|
|
| 36 | 37 | ) {
|
| 37 | 38 | Loading(
|
| 38 | 39 | progressBarVisible = false,
|
| ... | ... | @@ -298,5 +299,30 @@ enum class ConnectAssistUiState( |
| 298 | 299 | torBootstrapButton2TextStringResource = crashR.string.mozac_lib_crash_dialog_button_restart,
|
| 299 | 300 | torBootstrapButton2ShouldOpenSettings = false,
|
| 300 | 301 | torBootstrapButton2ShouldRestartApp = true,
|
| 301 | - )
|
|
| 302 | + ),
|
|
| 303 | + ProviderStopped(
|
|
| 304 | + progressBarVisible = false,
|
|
| 305 | + backButtonVisible = false,
|
|
| 306 | + settingsButtonVisible = true,
|
|
| 307 | + torConnectImageVisible = true,
|
|
| 308 | + torConnectImageResource = R.drawable.onion_broken,
|
|
| 309 | + titleLargeTextViewVisible = true,
|
|
| 310 | + titleLargeTextViewTextStringResource = R.string.connection_assist_provider_stopped_title,
|
|
| 311 | + titleDescriptionVisible = true,
|
|
| 312 | + learnMoreStringResource = R.string.connection_assist_final_error_learn_more_link,
|
|
| 313 | + internetErrorDescription = R.string.connection_assist_provider_stopped_description1,
|
|
| 314 | + internetErrorDescription1 = R.string.connection_assist_provider_stopped_description2,
|
|
| 315 | + internetErrorDescription2 = R.string.connection_assist_provider_stopped_description3,
|
|
| 316 | + titleDescriptionTextStringResource = null,
|
|
| 317 | + quickstartSwitchVisible = false,
|
|
| 318 | + regionDropDownVisible = false,
|
|
| 319 | + torBootstrapButton1Visible = true,
|
|
| 320 | + torBootstrapButton1TextStringResource = R.string.connection_assist_restart_connection_button,
|
|
| 321 | + torBootstrapButton1ShouldOpenSettings = false,
|
|
| 322 | + torBootstrapButton1ShouldRestartTor = true,
|
|
| 323 | + torBootstrapButton2Visible = false,
|
|
| 324 | + torBootstrapButton2TextStringResource = null,
|
|
| 325 | + torBootstrapButton2ShouldOpenSettings = false,
|
|
| 326 | + torBootstrapButton2ShouldRestartApp = false,
|
|
| 327 | + ),
|
|
| 302 | 328 | } |
| 1 | +package org.mozilla.fenix.tor
|
|
| 2 | + |
|
| 3 | +import android.app.Application
|
|
| 4 | +import android.util.Log
|
|
| 5 | +import androidx.lifecycle.AndroidViewModel
|
|
| 6 | +import kotlinx.coroutines.flow.MutableStateFlow
|
|
| 7 | +import kotlinx.coroutines.flow.StateFlow
|
|
| 8 | +import org.mozilla.fenix.ext.components
|
|
| 9 | +import org.mozilla.geckoview.TorAndroidIntegration
|
|
| 10 | +import org.mozilla.geckoview.TorConnectStage
|
|
| 11 | +import org.mozilla.geckoview.TorConnectStageName
|
|
| 12 | + |
|
| 13 | +class ProviderStoppedViewModel(
|
|
| 14 | + application: Application,
|
|
| 15 | +) : AndroidViewModel(application), TorAndroidIntegration.BootstrapStateChangeListener {
|
|
| 16 | + |
|
| 17 | + private val TAG = "ProviderStoppedViewModel"
|
|
| 18 | + |
|
| 19 | + internal val providerStoppedStateFlow: MutableStateFlow<Boolean> by lazy { MutableStateFlow(false) }
|
|
| 20 | + |
|
| 21 | + private val _maybeConfigIssue = MutableStateFlow(false)
|
|
| 22 | + internal val maybeConfigIssue: StateFlow<Boolean> = _maybeConfigIssue
|
|
| 23 | + |
|
| 24 | + override fun onBootstrapStageChange(stage: TorConnectStage) {
|
|
| 25 | + when (stage.name) {
|
|
| 26 | + TorConnectStageName.ProviderStopped -> {
|
|
| 27 | + Log.d(TAG, "ProviderStopped detected")
|
|
| 28 | + providerStoppedStateFlow.value = true
|
|
| 29 | + }
|
|
| 30 | + |
|
| 31 | + else -> {
|
|
| 32 | + providerStoppedStateFlow.value = false
|
|
| 33 | + }
|
|
| 34 | + }
|
|
| 35 | + |
|
| 36 | + _maybeConfigIssue.value = stage.providerStatus.maybeConfigIssue
|
|
| 37 | + }
|
|
| 38 | + |
|
| 39 | + init {
|
|
| 40 | + getApplication<Application>().components.core.geckoRuntime.torIntegrationController.registerBootstrapStateChangeListener(this)
|
|
| 41 | + }
|
|
| 42 | + |
|
| 43 | + override fun onCleared() {
|
|
| 44 | + getApplication<Application>().components.core.geckoRuntime.torIntegrationController.unregisterBootstrapStateChangeListener(this)
|
|
| 45 | + }
|
|
| 46 | + |
|
| 47 | + override fun onBootstrapProgress(progress: Double, hasWarnings: Boolean) {}
|
|
| 48 | + |
|
| 49 | +} |
| ... | ... | @@ -8,6 +8,7 @@ import android.graphics.Color |
| 8 | 8 | import android.graphics.Typeface
|
| 9 | 9 | import android.os.Build
|
| 10 | 10 | import android.os.Bundle
|
| 11 | +import android.os.PowerManager
|
|
| 11 | 12 | import android.text.SpannableString
|
| 12 | 13 | import android.text.Spanned
|
| 13 | 14 | import android.text.TextPaint
|
| ... | ... | @@ -17,9 +18,11 @@ import android.util.Log |
| 17 | 18 | import android.view.LayoutInflater
|
| 18 | 19 | import android.view.View
|
| 19 | 20 | import android.view.ViewGroup
|
| 21 | +import androidx.annotation.StringRes
|
|
| 20 | 22 | import androidx.appcompat.content.res.AppCompatResources
|
| 21 | 23 | import androidx.compose.foundation.Image
|
| 22 | 24 | import androidx.compose.foundation.background
|
| 25 | +import androidx.compose.foundation.layout.Arrangement
|
|
| 23 | 26 | import androidx.compose.foundation.layout.Box
|
| 24 | 27 | import androidx.compose.foundation.layout.Column
|
| 25 | 28 | import androidx.compose.foundation.layout.Row
|
| ... | ... | @@ -43,14 +46,22 @@ import androidx.compose.runtime.getValue |
| 43 | 46 | import androidx.compose.runtime.mutableStateOf
|
| 44 | 47 | import androidx.compose.runtime.saveable.rememberSaveable
|
| 45 | 48 | import androidx.compose.runtime.setValue
|
| 49 | +import androidx.compose.ui.Alignment
|
|
| 46 | 50 | import androidx.compose.ui.Modifier
|
| 47 | 51 | import androidx.compose.ui.platform.ViewCompositionStrategy
|
| 48 | 52 | import androidx.compose.ui.res.painterResource
|
| 53 | +import androidx.compose.ui.res.stringResource
|
|
| 54 | +import androidx.compose.ui.text.LinkAnnotation
|
|
| 55 | +import androidx.compose.ui.text.TextLinkStyles
|
|
| 49 | 56 | import androidx.compose.ui.text.TextStyle
|
| 57 | +import androidx.compose.ui.text.buildAnnotatedString
|
|
| 50 | 58 | import androidx.compose.ui.text.font.FontWeight
|
| 59 | +import androidx.compose.ui.text.style.TextDecoration
|
|
| 60 | +import androidx.compose.ui.tooling.preview.Preview
|
|
| 51 | 61 | import androidx.compose.ui.unit.DpOffset
|
| 52 | 62 | import androidx.compose.ui.unit.dp
|
| 53 | 63 | import androidx.compose.ui.unit.sp
|
| 64 | +import androidx.core.content.getSystemService
|
|
| 54 | 65 | import androidx.core.view.isEmpty
|
| 55 | 66 | import androidx.fragment.app.Fragment
|
| 56 | 67 | import androidx.fragment.app.activityViewModels
|
| ... | ... | @@ -68,6 +79,7 @@ import org.mozilla.fenix.HomeActivity |
| 68 | 79 | import org.mozilla.fenix.R
|
| 69 | 80 | import org.mozilla.fenix.databinding.FragmentTorConnectionAssistBinding
|
| 70 | 81 | import org.mozilla.fenix.e2e.SystemInsetsPaddedFragment
|
| 82 | +import org.mozilla.fenix.ext.components
|
|
| 71 | 83 | import org.mozilla.fenix.ext.hideToolbar
|
| 72 | 84 | |
| 73 | 85 | class TorConnectionAssistFragment : Fragment(), UserInteractionHandler, SystemInsetsPaddedFragment {
|
| ... | ... | @@ -76,6 +88,7 @@ class TorConnectionAssistFragment : Fragment(), UserInteractionHandler, SystemIn |
| 76 | 88 | private val progressViewModel: TorBootstrapProgressViewModel by viewModels()
|
| 77 | 89 | private val quickstartViewModel: QuickstartViewModel by activityViewModels()
|
| 78 | 90 | private val torConnectionAssistViewModel : TorConnectionAssistViewModel by viewModels()
|
| 91 | + private val providerStoppedViewModel : ProviderStoppedViewModel by activityViewModels()
|
|
| 79 | 92 | |
| 80 | 93 | private var _binding: FragmentTorConnectionAssistBinding? = null
|
| 81 | 94 | private val binding get() = _binding!!
|
| ... | ... | @@ -103,6 +116,7 @@ class TorConnectionAssistFragment : Fragment(), UserInteractionHandler, SystemIn |
| 103 | 116 | Log.d(TAG, "shouldOpenHome = $it")
|
| 104 | 117 | if (it) {
|
| 105 | 118 | openHome()
|
| 119 | + torConnectionAssistViewModel.shouldOpenHome.value = false
|
|
| 106 | 120 | }
|
| 107 | 121 | }
|
| 108 | 122 | |
| ... | ... | @@ -200,13 +214,142 @@ class TorConnectionAssistFragment : Fragment(), UserInteractionHandler, SystemIn |
| 200 | 214 | binding.torConnectImage.setImageResource(screen.torConnectImageResource)
|
| 201 | 215 | }
|
| 202 | 216 | |
| 217 | + @Composable
|
|
| 218 | + fun TextWithClickable(
|
|
| 219 | + @StringRes mainTextRes: Int,
|
|
| 220 | + @StringRes clickableTextRes: Int,
|
|
| 221 | + onClick: () -> Unit,
|
|
| 222 | + style: TextStyle,
|
|
| 223 | + tag: String,
|
|
| 224 | + ) {
|
|
| 225 | + Text(
|
|
| 226 | + text = buildAnnotatedString {
|
|
| 227 | + val clickableText = stringResource(clickableTextRes)
|
|
| 228 | + val plainText = stringResource(mainTextRes, clickableText)
|
|
| 229 | + append(plainText)
|
|
| 230 | + addLink(
|
|
| 231 | + clickable = LinkAnnotation.Clickable(
|
|
| 232 | + tag = tag,
|
|
| 233 | + styles = TextLinkStyles(
|
|
| 234 | + style = style.toSpanStyle().copy(textDecoration = TextDecoration.Underline),
|
|
| 235 | + pressedStyle = style.toSpanStyle(),
|
|
| 236 | + ),
|
|
| 237 | + linkInteractionListener = { onClick() }
|
|
| 238 | + ),
|
|
| 239 | + start = plainText.indexOf(clickableText),
|
|
| 240 | + end = plainText.indexOf(clickableText) + clickableText.length,
|
|
| 241 | + )
|
|
| 242 | + },
|
|
| 243 | + style = style,
|
|
| 244 | + )
|
|
| 245 | + }
|
|
| 246 | + |
|
| 247 | + @Preview
|
|
| 248 | + @Composable
|
|
| 249 | + fun DaemonFailedScreen(
|
|
| 250 | + isDeviceInPowerSaveMode: Boolean = false,
|
|
| 251 | + maybeConfigIssue: Boolean = false,
|
|
| 252 | + style: TextStyle = TextStyle(
|
|
| 253 | + fontSize = 16.sp,
|
|
| 254 | + lineHeight = 24.sp,
|
|
| 255 | + fontWeight = FontWeight(400),
|
|
| 256 | + color = PhotonColors.LightGrey05,
|
|
| 257 | + letterSpacing = 0.5.sp,
|
|
| 258 | + )
|
|
| 259 | + ) {
|
|
| 260 | + Column(
|
|
| 261 | + verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterVertically),
|
|
| 262 | + ) {
|
|
| 263 | + Text(
|
|
| 264 | + text = stringResource(R.string.connection_assist_provider_stopped_description1),
|
|
| 265 | + style = style,
|
|
| 266 | + )
|
|
| 267 | + Text(
|
|
| 268 | + text = stringResource(R.string.connection_assist_provider_stopped_description2),
|
|
| 269 | + style = style.copy(fontWeight = FontWeight.Bold),
|
|
| 270 | + )
|
|
| 271 | + if (isDeviceInPowerSaveMode && !maybeConfigIssue) {
|
|
| 272 | + Row {
|
|
| 273 | + Image(
|
|
| 274 | + painter = painterResource(R.drawable.bullet_point),
|
|
| 275 | + contentDescription = null,
|
|
| 276 | + modifier = Modifier.padding(6.dp)
|
|
| 277 | + )
|
|
| 278 | + Text(
|
|
| 279 | + style = style,
|
|
| 280 | + text = stringResource(R.string.connection_assist_provider_stopped_description_battery1),
|
|
| 281 | + )
|
|
| 282 | + }
|
|
| 283 | + }
|
|
| 284 | + Row {
|
|
| 285 | + Image(
|
|
| 286 | + painter = painterResource(R.drawable.bullet_point),
|
|
| 287 | + contentDescription = null,
|
|
| 288 | + modifier = Modifier.padding(6.dp)
|
|
| 289 | + )
|
|
| 290 | + Text(
|
|
| 291 | + style = style,
|
|
| 292 | + text = stringResource(R.string.connection_assist_provider_stopped_description3),
|
|
| 293 | + )
|
|
| 294 | + }
|
|
| 295 | + Text(
|
|
| 296 | + text = stringResource(R.string.connection_assist_provider_stopped_description4),
|
|
| 297 | + style = style.copy(fontWeight = FontWeight.Bold),
|
|
| 298 | + )
|
|
| 299 | + if (isDeviceInPowerSaveMode && !maybeConfigIssue) {
|
|
| 300 | + Row {
|
|
| 301 | + Image(
|
|
| 302 | + painter = painterResource(R.drawable.bullet_point),
|
|
| 303 | + contentDescription = null,
|
|
| 304 | + modifier = Modifier.padding(6.dp),
|
|
| 305 | + )
|
|
| 306 | + TextWithClickable(
|
|
| 307 | + mainTextRes = R.string.connection_assist_provider_stopped_description_turn_off_battery_saver2,
|
|
| 308 | + clickableTextRes = R.string.connection_assist_provider_stopped_description_turn_off_battery_saver_clickable,
|
|
| 309 | + onClick = { (requireActivity() as HomeActivity).openBatterySaverSettings() },
|
|
| 310 | + style = style,
|
|
| 311 | + tag = BATTERY_SETTINGS_TAG,
|
|
| 312 | + )
|
|
| 313 | + }
|
|
| 314 | + } else {
|
|
| 315 | + Row {
|
|
| 316 | + Image(
|
|
| 317 | + painter = painterResource(R.drawable.bullet_point),
|
|
| 318 | + contentDescription = null,
|
|
| 319 | + modifier = Modifier.padding(6.dp),
|
|
| 320 | + )
|
|
| 321 | + Text(
|
|
| 322 | + text = stringResource(R.string.connection_assist_provider_stopped_description5),
|
|
| 323 | + style = style,
|
|
| 324 | + )
|
|
| 325 | + }
|
|
| 326 | + }
|
|
| 327 | + Text(
|
|
| 328 | + text = stringResource(R.string.connection_assist_provider_stopped_description6,
|
|
| 329 | + stringResource(R.string.connection_assist_provider_stopped_description7)
|
|
| 330 | + ),
|
|
| 331 | + style = style,
|
|
| 332 | + )
|
|
| 333 | + }
|
|
| 334 | + }
|
|
| 335 | + |
|
| 203 | 336 | private fun setTitle(screen: ConnectAssistUiState) {
|
| 204 | 337 | binding.titleLargeTextView.visibility =
|
| 205 | 338 | if (screen.titleLargeTextViewVisible) View.VISIBLE else View.GONE
|
| 206 | 339 | binding.titleLargeTextView.text = getString(screen.titleLargeTextViewTextStringResource)
|
| 207 | 340 | binding.titleDescription.visibility =
|
| 208 | 341 | if (screen.titleDescriptionVisible) View.VISIBLE else View.GONE
|
| 209 | - if (screen.learnMoreStringResource != null && screen.internetErrorDescription != null) {
|
|
| 342 | + binding.daemonFailedDescription.visibility = View.GONE
|
|
| 343 | + if (screen == ConnectAssistUiState.ProviderStopped) {
|
|
| 344 | + binding.titleDescription.visibility = View.GONE
|
|
| 345 | + binding.daemonFailedDescription.setContent {
|
|
| 346 | + DaemonFailedScreen(
|
|
| 347 | + isDeviceInPowerSaveMode = requireContext().getSystemService<PowerManager>()?.isPowerSaveMode ?: false,
|
|
| 348 | + maybeConfigIssue = providerStoppedViewModel.maybeConfigIssue.collectAsState().value,
|
|
| 349 | + )
|
|
| 350 | + }
|
|
| 351 | + binding.daemonFailedDescription.visibility = View.VISIBLE
|
|
| 352 | + } else if (screen.learnMoreStringResource != null && screen.internetErrorDescription != null) {
|
|
| 210 | 353 | val learnMore: String = "" // getString(screen.learnMoreStringResource) tor-browser#43198 uncomment and add back once we have the "Learn more" screens for relevant pages
|
| 211 | 354 | val internetErrorDescription: String =
|
| 212 | 355 | if (screen.internetErrorDescription1 == null) {
|
| ... | ... | @@ -434,6 +577,13 @@ class TorConnectionAssistFragment : Fragment(), UserInteractionHandler, SystemIn |
| 434 | 577 | setOnClickListener {
|
| 435 | 578 | if (screen.torBootstrapButton1ShouldOpenSettings) {
|
| 436 | 579 | openTorConnectionSettings()
|
| 580 | + } else if (screen.torBootstrapButton1ShouldRestartTor) {
|
|
| 581 | + requireContext().components.core.geckoRuntime.torIntegrationController.restartProvider()
|
|
| 582 | + backgroundTintList = AppCompatResources.getColorStateList(
|
|
| 583 | + requireContext(),
|
|
| 584 | + R.color.disabled_connect_button_purple,
|
|
| 585 | + )
|
|
| 586 | + text = getString(R.string.connection_assist_restarting_connection_button)
|
|
| 437 | 587 | } else {
|
| 438 | 588 | torConnectionAssistViewModel.handleConnect(screen)
|
| 439 | 589 | }
|
| ... | ... | @@ -561,8 +711,11 @@ class TorConnectionAssistFragment : Fragment(), UserInteractionHandler, SystemIn |
| 561 | 711 | }
|
| 562 | 712 | |
| 563 | 713 | override fun onBackPressed(): Boolean {
|
| 564 | - torConnectionAssistViewModel.handleBackButtonPressed(requireActivity() as HomeActivity)
|
|
| 565 | - return true
|
|
| 714 | + return torConnectionAssistViewModel.handleBackButtonPressed(requireActivity() as HomeActivity)
|
|
| 715 | + }
|
|
| 716 | + |
|
| 717 | + companion object {
|
|
| 718 | + const val BATTERY_SETTINGS_TAG = "BATTERY_SETTINGS_TAG"
|
|
| 566 | 719 | }
|
| 567 | 720 | |
| 568 | 721 | } |
| ... | ... | @@ -138,17 +138,18 @@ class TorConnectionAssistViewModel( |
| 138 | 138 | torConnectStage.collect {
|
| 139 | 139 | Log.d(TAG, "torConnectStageName: ${it?.name}")
|
| 140 | 140 | when (it?.name) {
|
| 141 | - TorConnectStageName.Disabled -> shouldOpenHome.value = true // TODO use TorConnect.enabled instead to determine this
|
|
| 142 | - TorConnectStageName.Loading -> _torConnectScreen.value = ConnectAssistUiState.Loading
|
|
| 143 | - TorConnectStageName.Start -> _torConnectScreen.value = ConnectAssistUiState.Start
|
|
| 144 | - TorConnectStageName.Bootstrapping -> _torConnectScreen.value = handleBootstrapTrigger(it.bootstrapTrigger)
|
|
| 145 | - TorConnectStageName.Offline -> _torConnectScreen.value = ConnectAssistUiState.Offline
|
|
| 146 | - TorConnectStageName.ChooseRegion -> _torConnectScreen.value = ConnectAssistUiState.ChooseRegion
|
|
| 147 | - TorConnectStageName.RegionNotFound -> _torConnectScreen.value = ConnectAssistUiState.RegionNotFound
|
|
| 148 | - TorConnectStageName.ConfirmRegion -> _torConnectScreen.value = ConnectAssistUiState.ConfirmRegion
|
|
| 149 | - TorConnectStageName.FinalError -> _torConnectScreen.value = ConnectAssistUiState.FinalError
|
|
| 150 | - TorConnectStageName.Bootstrapped -> shouldOpenHome.value = true
|
|
| 151 | - null -> {}
|
|
| 141 | + TorConnectStageName.Disabled -> shouldOpenHome.value = true // TODO use TorConnect.enabled instead to determine this
|
|
| 142 | + TorConnectStageName.Loading -> _torConnectScreen.value = ConnectAssistUiState.Loading
|
|
| 143 | + TorConnectStageName.ProviderStopped -> _torConnectScreen.value = ConnectAssistUiState.ProviderStopped
|
|
| 144 | + TorConnectStageName.Start -> _torConnectScreen.value = ConnectAssistUiState.Start
|
|
| 145 | + TorConnectStageName.Bootstrapping -> _torConnectScreen.value = handleBootstrapTrigger(it.bootstrapTrigger)
|
|
| 146 | + TorConnectStageName.Offline -> _torConnectScreen.value = ConnectAssistUiState.Offline
|
|
| 147 | + TorConnectStageName.ChooseRegion -> _torConnectScreen.value = ConnectAssistUiState.ChooseRegion
|
|
| 148 | + TorConnectStageName.RegionNotFound -> _torConnectScreen.value = ConnectAssistUiState.RegionNotFound
|
|
| 149 | + TorConnectStageName.ConfirmRegion -> _torConnectScreen.value = ConnectAssistUiState.ConfirmRegion
|
|
| 150 | + TorConnectStageName.FinalError -> _torConnectScreen.value = ConnectAssistUiState.FinalError
|
|
| 151 | + TorConnectStageName.Bootstrapped -> shouldOpenHome.value = true
|
|
| 152 | + null -> {}
|
|
| 152 | 153 | }
|
| 153 | 154 | }
|
| 154 | 155 | }
|
| ... | ... | @@ -168,11 +169,12 @@ class TorConnectionAssistViewModel( |
| 168 | 169 | }
|
| 169 | 170 | }
|
| 170 | 171 | |
| 171 | - fun handleBackButtonPressed(homeActivity: HomeActivity) {
|
|
| 172 | - when (torConnectScreen.value) {
|
|
| 173 | - ConnectAssistUiState.Loading -> homeActivity.shutDown()
|
|
| 174 | - ConnectAssistUiState.Start -> homeActivity.shutDown()
|
|
| 175 | - else -> torAndroidIntegration.startAgain()
|
|
| 172 | + fun handleBackButtonPressed(homeActivity: HomeActivity): Boolean {
|
|
| 173 | + return when (torConnectScreen.value) {
|
|
| 174 | + ConnectAssistUiState.Loading -> homeActivity.shutDown()
|
|
| 175 | + ConnectAssistUiState.Start -> homeActivity.shutDown()
|
|
| 176 | + ConnectAssistUiState.ProviderStopped -> false
|
|
| 177 | + else -> torAndroidIntegration.startAgain().let { true }
|
|
| 176 | 178 | }
|
| 177 | 179 | }
|
| 178 | 180 |
| 1 | +<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
| 2 | + android:autoMirrored="true"
|
|
| 3 | + android:height="6dp"
|
|
| 4 | + android:viewportHeight="6"
|
|
| 5 | + android:viewportWidth="6"
|
|
| 6 | + android:width="6dp">
|
|
| 7 | + <path
|
|
| 8 | + android:fillColor="#FBFBFE"
|
|
| 9 | + android:pathData="M3,3m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0" />
|
|
| 10 | +</vector> |
| 1 | +<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
| 2 | + android:autoMirrored="true"
|
|
| 3 | + android:height="16dp"
|
|
| 4 | + android:viewportHeight="16"
|
|
| 5 | + android:viewportWidth="16"
|
|
| 6 | + android:width="16dp">
|
|
| 7 | + <path
|
|
| 8 | + android:fillAlpha="0.4"
|
|
| 9 | + android:fillColor="#FBFBFE"
|
|
| 10 | + android:fillType="evenOdd"
|
|
| 11 | + android:pathData="M8,15C8,14.448 7.549,14.009 7.004,13.918C4.164,13.443 2,10.974 2,8C2,4.686 4.686,2 8,2C10.974,2 13.443,4.164 13.918,7.004C14.009,7.549 14.448,8 15,8C15.552,8 16.007,7.55 15.938,7.002C15.447,3.055 12.08,0 8,0C3.582,0 0,3.582 0,8C0,12.08 3.055,15.447 7.002,15.938C7.55,16.007 8,15.552 8,15Z" />
|
|
| 12 | +</vector> |
| 1 | +<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="40dp" android:viewportHeight="40" android:viewportWidth="40" android:width="40dp">
|
|
| 2 | +
|
|
| 3 | + <path android:fillColor="#FBFBFE" android:pathData="M33.259,33.258C29.865,36.651 25.178,38.75 20,38.75C9.645,38.75 1.25,30.355 1.25,20C1.25,14.823 3.348,10.135 6.741,6.742L8.813,8.814C5.95,11.677 4.18,15.632 4.18,20C4.18,28.737 11.263,35.82 20,35.82C24.369,35.82 28.324,34.049 31.187,31.186L33.259,33.258Z"/>
|
|
| 4 | +
|
|
| 5 | + <path android:fillColor="#FBFBFE" android:pathData="M35.284,30.863C37.466,27.798 38.75,24.049 38.75,20C38.75,9.645 30.355,1.25 20,1.25C15.951,1.25 12.202,2.533 9.137,4.716L11.243,6.822C13.751,5.153 16.762,4.18 20,4.18C28.737,4.18 35.82,11.263 35.82,20C35.82,23.238 34.847,26.249 33.178,28.757L35.284,30.863Z"/>
|
|
| 6 | +
|
|
| 7 | + <path android:fillColor="#FBFBFE" android:pathData="M31.226,26.805C32.431,24.82 33.125,22.491 33.125,20C33.125,12.751 27.249,6.875 20,6.875C17.509,6.875 15.18,7.569 13.195,8.774L15.347,10.926C16.742,10.209 18.324,9.805 20,9.805C25.631,9.805 30.195,14.369 30.195,20C30.195,21.676 29.791,23.258 29.074,24.653L31.226,26.805Z"/>
|
|
| 8 | +
|
|
| 9 | + <path android:fillColor="#FBFBFE" android:pathData="M29.281,29.281L27.209,27.209C25.364,29.054 22.815,30.195 20,30.195C14.369,30.195 9.805,25.631 9.805,20C9.805,17.185 10.946,14.636 12.79,12.791L10.719,10.72C8.344,13.095 6.875,16.376 6.875,20C6.875,27.249 12.751,33.125 20,33.125C23.625,33.125 26.906,31.656 29.281,29.281Z"/>
|
|
| 10 | +
|
|
| 11 | + <path android:fillColor="#FBFBFE" android:pathData="M14.696,14.697C13.339,16.054 12.5,17.929 12.5,20C12.5,24.142 15.858,27.5 20,27.5C22.071,27.5 23.946,26.66 25.303,25.303L23.232,23.232C22.405,24.059 21.262,24.57 20,24.57C17.476,24.57 15.43,22.524 15.43,20C15.43,18.738 15.941,17.596 16.768,16.769L14.696,14.697Z"/>
|
|
| 12 | +
|
|
| 13 | + <path android:fillColor="#FBFBFE" android:pathData="M24.568,20.147C24.569,20.098 24.57,20.049 24.57,20C24.57,17.476 22.524,15.43 20,15.43C19.951,15.43 19.902,15.431 19.853,15.432L17.388,12.967C18.202,12.665 19.081,12.5 20,12.5C24.142,12.5 27.5,15.858 27.5,20C27.5,20.919 27.335,21.799 27.033,22.612L24.568,20.147Z"/>
|
|
| 14 | +
|
|
| 15 | + <path android:fillColor="#FBFBFE" android:pathData="M20,38.75C9.645,38.75 1.25,30.355 1.25,20C1.25,14.823 3.348,10.135 6.741,6.742L20,20V38.75Z"/>
|
|
| 16 | +
|
|
| 17 | + <path android:fillColor="#FBFBFE" android:pathData="M20,15.579V1.25C15.951,1.25 12.202,2.533 9.137,4.716L20,15.579Z"/>
|
|
| 18 | +
|
|
| 19 | + <path android:fillColor="#FF9AA2" android:pathData="M35.291,39.061C35.085,39.062 34.882,39.021 34.692,38.943C34.503,38.864 34.33,38.749 34.186,38.604L2.31,6.731C2.037,6.434 1.889,6.043 1.898,5.64C1.906,5.236 2.07,4.851 2.355,4.566C2.64,4.28 3.025,4.116 3.428,4.107C3.832,4.099 4.223,4.246 4.52,4.519L36.396,36.394C36.688,36.688 36.851,37.085 36.851,37.5C36.851,37.915 36.688,38.312 36.396,38.606C36.25,38.751 36.078,38.866 35.888,38.944C35.699,39.022 35.496,39.062 35.291,39.061Z"/>
|
|
| 20 | +
|
|
| 21 | +</vector> |
| ... | ... | @@ -99,6 +99,19 @@ |
| 99 | 99 | android:textSize="14sp"
|
| 100 | 100 | app:layout_constraintTop_toBottomOf="@id/title_large_text_view" />
|
| 101 | 101 | |
| 102 | + <androidx.compose.ui.platform.ComposeView
|
|
| 103 | + android:id="@+id/daemon_failed_description"
|
|
| 104 | + android:layout_width="match_parent"
|
|
| 105 | + android:layout_height="wrap_content"
|
|
| 106 | + android:visibility="gone"
|
|
| 107 | + android:paddingHorizontal="24dp"
|
|
| 108 | + android:paddingVertical="16dp"
|
|
| 109 | + app:layout_constraintBottom_toTopOf="@id/tor_bootstrap_button_1"
|
|
| 110 | + app:layout_constraintEnd_toEndOf="parent"
|
|
| 111 | + app:layout_constraintStart_toStartOf="parent"
|
|
| 112 | + app:layout_constraintTop_toBottomOf="@id/title_large_text_view"
|
|
| 113 | + app:layout_constraintVertical_bias="0" />
|
|
| 114 | + |
|
| 102 | 115 | <androidx.appcompat.widget.SwitchCompat
|
| 103 | 116 | android:id="@+id/quickstart_switch"
|
| 104 | 117 | android:layout_width="match_parent"
|
| ... | ... | @@ -27,6 +27,10 @@ |
| 27 | 27 | app:popUpTo="@id/torConnectionAssistFragment"
|
| 28 | 28 | app:popUpToInclusive="true"/>
|
| 29 | 29 | |
| 30 | + <action
|
|
| 31 | + android:id="@+id/action_navigate_to_connection_assist_from_anywhere"
|
|
| 32 | + app:destination="@id/torConnectionAssistFragment" />
|
|
| 33 | + |
|
| 30 | 34 | <action
|
| 31 | 35 | android:id="@+id/action_global_home"
|
| 32 | 36 | app:destination="@id/homeFragment"
|
| ... | ... | @@ -652,6 +652,7 @@ |
| 652 | 652 | <string name="pref_key_tor_network_settings_bridge_config" translatable="false">pref_key_tor_network_settings_bridge_config</string>
|
| 653 | 653 | <string name="pref_key_tor_logs" translatable="false">pref_key_tor_logs</string>
|
| 654 | 654 | <string name="pref_key_about_config_shortcut" translatable="false">pref_key_about_config_shortcut</string>
|
| 655 | + <string name="pref_key_test_kill_tor" translatable="false">pref_key_test_kill_tor</string>
|
|
| 655 | 656 | <string name="pref_key_tor_network_settings_bridge_config_explanation" translatable="false">pref_key_tor_network_settings_bridge_config_explanation</string>
|
| 656 | 657 | <string name="pref_key_tor_network_settings_bridge_config_toggle" translatable="false">pref_key_tor_network_settings_bridge_config_toggle</string>
|
| 657 | 658 | <string name="pref_key_tor_network_settings_bridge_config_builtin_bridge_obfs4" translatable="false">pref_key_tor_network_settings_bridge_config_builtin_bridge_obfs4</string>
|
| ... | ... | @@ -135,6 +135,32 @@ |
| 135 | 135 | <string name="connection_assist_back_button_content_description_start_again">Start again</string>
|
| 136 | 136 | <!-- Connection assist. This message is shown briefly after the connection to the Tor network completes. -->
|
| 137 | 137 | <string name="connection_assist_bootstrap_succeeded_toast_message">Connected to Tor</string>
|
| 138 | + <!-- Connection assist. Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network". -->
|
|
| 139 | + <string name="connection_assist_provider_stopped_title">The Tor process has stopped working</string>
|
|
| 140 | + <!-- Connection assist. Here "process" is a noun, referring to the execution of a computer program. -->
|
|
| 141 | + <string name="connection_assist_provider_stopped_description1">The underlying process that controls your connection to the Tor network has stopped working.</string>
|
|
| 142 | + <!-- Connection assist. -->
|
|
| 143 | + <string name="connection_assist_provider_stopped_description2">What could be causing this?</string>
|
|
| 144 | + <!-- Connection assist. Here "process" is a noun, referring to the execution of a computer program. -->
|
|
| 145 | + <string name="connection_assist_provider_stopped_description_battery1">Your device has quit the process to save battery.</string>
|
|
| 146 | + <!-- Connection assist. Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network". -->
|
|
| 147 | + <string name="connection_assist_provider_stopped_description3">The Tor process has stopped working due to a technical issue.</string>
|
|
| 148 | + <!-- Connection assist. -->
|
|
| 149 | + <string name="connection_assist_provider_stopped_description4">What can you do about it?</string>
|
|
| 150 | + <!-- Connection assist. Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network". -->
|
|
| 151 | + <string name="connection_assist_provider_stopped_description5">Try restarting the Tor process (this won’t close your browser tabs).</string>
|
|
| 152 | + <!-- Connection assist.-->
|
|
| 153 | + <string name="connection_assist_provider_stopped_description_turn_off_battery_saver_clickable">Turn off Battery Saver on your device</string>
|
|
| 154 | + <!-- Connection assist. "%1$s" will be replaced with connection_assist_provider_stopped_description_turn_off_battery_saver_clickable. Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network". -->
|
|
| 155 | + <string name="connection_assist_provider_stopped_description_turn_off_battery_saver2">%1$s and try restarting the Tor process (this won’t close your browser tabs).</string>
|
|
| 156 | + <!-- Connection assist. "%1$s" will be replaced with connection_assist_provider_stopped_description7. -->
|
|
| 157 | + <string name="connection_assist_provider_stopped_description6">If the problem remains, get in contact with us through one of our %1$s.</string>
|
|
| 158 | + <!-- Connection assist. -->
|
|
| 159 | + <string name="connection_assist_provider_stopped_description7">support channels</string>
|
|
| 160 | + <!-- Connection assist. Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network". -->
|
|
| 161 | + <string name="connection_assist_restart_connection_button">Restart Tor process</string>
|
|
| 162 | + <!-- Connection assist. Here "process" is a noun, referring to the execution of a computer program. "Tor process" specifically refers to the execution of the tor program, which is the program that handles the connection to the "Tor network". -->
|
|
| 163 | + <string name="connection_assist_restarting_connection_button">Restarting Tor process…</string>
|
|
| 138 | 164 | |
| 139 | 165 | <!-- Notification title for closing browser tabs. "%s" will be replaced with the localised application name, such as "Tor Browser". -->
|
| 140 | 166 | <string name="notification_close_tor_browser_tabs">Close %s’s tabs?</string>
|
| ... | ... | @@ -135,6 +135,10 @@ |
| 135 | 135 | android:key="@string/pref_key_enable_lna_tracker_blocking_enabled"
|
| 136 | 136 | android:title="@string/preferences_debug_settings_enable_lna_tracker_blocking"
|
| 137 | 137 | app:iconSpaceReserved="false" />
|
| 138 | + <Preference
|
|
| 139 | + android:key="@string/pref_key_test_kill_tor"
|
|
| 140 | + android:title="TEST kill tor daemon"
|
|
| 141 | + app:iconSpaceReserved="false" />
|
|
| 138 | 142 | </PreferenceCategory>
|
| 139 | 143 | |
| 140 | 144 | <PreferenceCategory
|
| 1 | +package org.mozilla.geckoview;
|
|
| 2 | + |
|
| 3 | +import org.mozilla.gecko.util.GeckoBundle;
|
|
| 4 | + |
|
| 5 | +public class ProviderStatus {
|
|
| 6 | + public Boolean maybeConfigIssue;
|
|
| 7 | + |
|
| 8 | + public ProviderStatus(GeckoBundle bundle) {
|
|
| 9 | + maybeConfigIssue = bundle.getBoolean("maybeConfigIssue");
|
|
| 10 | + }
|
|
| 11 | +} |
| ... | ... | @@ -57,6 +57,7 @@ public class TorAndroidIntegration implements BundleEventListener { |
| 57 | 57 | private static final String EVENT_BOOTSTRAP_BEGIN_AUTO = "GeckoView:Tor:BootstrapBeginAuto";
|
| 58 | 58 | private static final String EVENT_BOOTSTRAP_CANCEL = "GeckoView:Tor:BootstrapCancel";
|
| 59 | 59 | private static final String EVENT_START_AGAIN = "GeckoView:Tor:StartAgain";
|
| 60 | + private static final String EVENT_RESTART_PROVIDER = "GeckoView:Tor:RestartProvider";
|
|
| 60 | 61 | private static final String EVENT_QUICKSTART_GET = "GeckoView:Tor:QuickstartGet";
|
| 61 | 62 | private static final String EVENT_QUICKSTART_SET = "GeckoView:Tor:QuickstartSet";
|
| 62 | 63 | private static final String EVENT_REGION_NAMES_GET = "GeckoView:Tor:RegionNamesGet";
|
| ... | ... | @@ -706,6 +707,10 @@ public class TorAndroidIntegration implements BundleEventListener { |
| 706 | 707 | return EventDispatcher.getInstance().queryVoid(EVENT_START_AGAIN);
|
| 707 | 708 | }
|
| 708 | 709 | |
| 710 | + public @NonNull GeckoResult<Void> restartProvider() {
|
|
| 711 | + return EventDispatcher.getInstance().queryVoid(EVENT_RESTART_PROVIDER);
|
|
| 712 | + }
|
|
| 713 | + |
|
| 709 | 714 | public interface QuickstartGetter {
|
| 710 | 715 | void onValue(boolean enabled);
|
| 711 | 716 | }
|
| ... | ... | @@ -13,6 +13,7 @@ public class TorConnectStage { |
| 13 | 13 | public Boolean potentiallyBlocked;
|
| 14 | 14 | public Boolean tryAgain;
|
| 15 | 15 | public TorBootstrappingStatus bootstrappingStatus;
|
| 16 | + public ProviderStatus providerStatus;
|
|
| 16 | 17 | |
| 17 | 18 | public TorConnectStage(GeckoBundle bundle) {
|
| 18 | 19 | name = TorConnectStageName.fromString(bundle.getString("name"));
|
| ... | ... | @@ -26,6 +27,7 @@ public class TorConnectStage { |
| 26 | 27 | error = new TorConnectError(bundle.getBundle("error"));
|
| 27 | 28 | }
|
| 28 | 29 | bootstrappingStatus = new TorBootstrappingStatus(bundle.getBundle("bootstrappingStatus"));
|
| 30 | + providerStatus = new ProviderStatus(bundle.getBundle("providerStatus"));
|
|
| 29 | 31 | }
|
| 30 | 32 | |
| 31 | 33 | public Boolean isBootstrapped() {
|
| ... | ... | @@ -3,9 +3,10 @@ package org.mozilla.geckoview; |
| 3 | 3 | import java.security.InvalidParameterException;
|
| 4 | 4 | |
| 5 | 5 | public enum TorConnectStageName {
|
| 6 | - // These names should match entries from TorConnectStage in TorConnect.sys.mjs at ~ln163.
|
|
| 6 | + // These names should match entries from TorConnectStage in TorConnect.sys.mjs at ~ln674.
|
|
| 7 | 7 | Disabled("Disabled"),
|
| 8 | 8 | Loading("Loading"),
|
| 9 | + ProviderStopped("ProviderStopped"),
|
|
| 9 | 10 | Start("Start"),
|
| 10 | 11 | Bootstrapping("Bootstrapping"),
|
| 11 | 12 | Offline("Offline"),
|
| ... | ... | @@ -51,6 +51,11 @@ export class TorProcessAndroid { |
| 51 | 51 | * it failed to start tor.
|
| 52 | 52 | */
|
| 53 | 53 | #startReject = null;
|
| 54 | + /**
|
|
| 55 | + * Tells whether we ever registered ourself as the listener to the various
|
|
| 56 | + * process events.
|
|
| 57 | + */
|
|
| 58 | + #registeredListeners = false;
|
|
| 54 | 59 | |
| 55 | 60 | onExit = () => {};
|
| 56 | 61 | |
| ... | ... | @@ -74,6 +79,7 @@ export class TorProcessAndroid { |
| 74 | 79 | this,
|
| 75 | 80 | Object.values(TorIncomingEvents)
|
| 76 | 81 | );
|
| 82 | + this.#registeredListeners = true;
|
|
| 77 | 83 | let config;
|
| 78 | 84 | try {
|
| 79 | 85 | config = await lazy.EventDispatcher.instance.sendRequestForResult(
|
| ... | ... | @@ -103,10 +109,13 @@ export class TorProcessAndroid { |
| 103 | 109 | });
|
| 104 | 110 | logger.debug("Sent the stop event.");
|
| 105 | 111 | this.#processHandle = null;
|
| 106 | - lazy.EventDispatcher.instance.unregisterListener(
|
|
| 107 | - this,
|
|
| 108 | - Object.values(TorIncomingEvents)
|
|
| 109 | - );
|
|
| 112 | + if (this.#registeredListeners) {
|
|
| 113 | + lazy.EventDispatcher.instance.unregisterListener(
|
|
| 114 | + this,
|
|
| 115 | + Object.values(TorIncomingEvents)
|
|
| 116 | + );
|
|
| 117 | + this.#registeredListeners = false;
|
|
| 118 | + }
|
|
| 110 | 119 | }
|
| 111 | 120 | |
| 112 | 121 | onEvent(event, data, _callback) {
|
| ... | ... | @@ -48,6 +48,7 @@ const ListenedEvents = Object.freeze({ |
| 48 | 48 | bootstrapBeginAuto: "GeckoView:Tor:BootstrapBeginAuto",
|
| 49 | 49 | bootstrapCancel: "GeckoView:Tor:BootstrapCancel",
|
| 50 | 50 | startAgain: "GeckoView:Tor:StartAgain",
|
| 51 | + restartProvider: "GeckoView:Tor:RestartProvider",
|
|
| 51 | 52 | quickstartGet: "GeckoView:Tor:QuickstartGet",
|
| 52 | 53 | quickstartSet: "GeckoView:Tor:QuickstartSet",
|
| 53 | 54 | regionNamesGet: "GeckoView:Tor:RegionNamesGet",
|
| ... | ... | @@ -98,11 +99,6 @@ class TorAndroidIntegrationImpl { |
| 98 | 99 | lazy.TorConnect.init();
|
| 99 | 100 | |
| 100 | 101 | lazy.TorDomainIsolator.init();
|
| 101 | - |
|
| 102 | - // On Android immediately call firstWindowLoaded. This should be safe to
|
|
| 103 | - // call since it will await the initialisation of the TorProvider set up
|
|
| 104 | - // by TorProviderBuilder.init.
|
|
| 105 | - lazy.TorProviderBuilder.firstWindowLoaded();
|
|
| 106 | 102 | }
|
| 107 | 103 | |
| 108 | 104 | observe(subj, topic) {
|
| ... | ... | @@ -203,6 +199,9 @@ class TorAndroidIntegrationImpl { |
| 203 | 199 | case ListenedEvents.startAgain:
|
| 204 | 200 | lazy.TorConnect.startAgain();
|
| 205 | 201 | break;
|
| 202 | + case ListenedEvents.restartProvider:
|
|
| 203 | + lazy.TorConnect.restartProvider();
|
|
| 204 | + break;
|
|
| 206 | 205 | case ListenedEvents.quickstartGet:
|
| 207 | 206 | callback?.onSuccess(lazy.TorConnect.quickstart);
|
| 208 | 207 | return;
|
| ... | ... | @@ -1109,12 +1109,9 @@ export const TorConnect = { |
| 1109 | 1109 | throw new Error(`Trying to set the stage to ${name} during a bootstrap`);
|
| 1110 | 1110 | }
|
| 1111 | 1111 | if (!this._providerRunning && name !== TorConnectStage.ProviderStopped) {
|
| 1112 | - if (!lazy.TorLauncherUtil.isAndroid) {
|
|
| 1113 | - // TODO: Remove Android exception.
|
|
| 1114 | - throw new Error(
|
|
| 1115 | - `Trying to set the stage to ${name} when provider is not running`
|
|
| 1116 | - );
|
|
| 1117 | - }
|
|
| 1112 | + throw new Error(
|
|
| 1113 | + `Trying to set the stage to ${name} when provider is not running`
|
|
| 1114 | + );
|
|
| 1118 | 1115 | }
|
| 1119 | 1116 | |
| 1120 | 1117 | lazy.logger.info(`Entering stage ${name}`);
|
| ... | ... | @@ -1596,13 +1593,8 @@ export const TorConnect = { |
| 1596 | 1593 | return;
|
| 1597 | 1594 | }
|
| 1598 | 1595 | if (!this._providerRunning && stage !== TorConnectStage.ProviderStopped) {
|
| 1599 | - if (!lazy.TorLauncherUtil.isAndroid) {
|
|
| 1600 | - // TODO: Remove Android exception.
|
|
| 1601 | - lazy.logger.warn(
|
|
| 1602 | - `Cannot move to ${stage} when provider is not running`
|
|
| 1603 | - );
|
|
| 1604 | - return;
|
|
| 1605 | - }
|
|
| 1596 | + lazy.logger.warn(`Cannot move to ${stage} when provider is not running`);
|
|
| 1597 | + return;
|
|
| 1606 | 1598 | }
|
| 1607 | 1599 | if (this._stageName === TorConnectStage.Loading) {
|
| 1608 | 1600 | if (stage === TorConnectStage.ProviderStopped) {
|
| ... | ... | @@ -1709,13 +1701,7 @@ export const TorConnect = { |
| 1709 | 1701 | // But other methods should take into account that _providerRunning is now
|
| 1710 | 1702 | // `false` to early return and guarantee that we enter this
|
| 1711 | 1703 | // ProviderStopped stage.
|
| 1712 | - if (lazy.TorLauncherUtil.isAndroid) {
|
|
| 1713 | - // TODO: Remove this Android path when android supports the
|
|
| 1714 | - // `ProviderStopped` stage.
|
|
| 1715 | - this._makeStageRequest(TorConnectStage.Start, true);
|
|
| 1716 | - } else {
|
|
| 1717 | - this._makeStageRequest(TorConnectStage.ProviderStopped, true);
|
|
| 1718 | - }
|
|
| 1704 | + this._makeStageRequest(TorConnectStage.ProviderStopped, true);
|
|
| 1719 | 1705 | }
|
| 1720 | 1706 | }
|
| 1721 | 1707 |