brizental pushed to branch tor-browser-153.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
-
d4d29dca
by Beatriz Rizental at 2026-07-28T15:50:37+02:00
-
584d0657
by Beatriz Rizental at 2026-07-28T15:50:37+02:00
-
51b77601
by Beatriz Rizental at 2026-07-28T15:50:37+02:00
6 changed files:
- mobile/android/fenix/app/build.gradle
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/ClientUUID.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/llm/Llm.kt
- mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/ClientUUIDTest.kt
Changes:
| ... | ... | @@ -564,7 +564,6 @@ dependencies { |
| 564 | 564 | implementation project(':components:lib-push-firebase')
|
| 565 | 565 | implementation project(':components:lib-state')
|
| 566 | 566 | implementation project(':components:lib-accelerometer-sensormanager')
|
| 567 | - implementation project(':components:lib-integrity-googleplay')
|
|
| 568 | 567 | implementation project(':components:lib-llm-mlpa')
|
| 569 | 568 | implementation project(':components:lib-shake')
|
| 570 | 569 | implementation project(':components:lib-ai-controls')
|
| ... | ... | @@ -592,7 +592,7 @@ open class FenixApplication : Application(), Provider, ThemeProvider { |
| 592 | 592 | }
|
| 593 | 593 | runOnVisualCompleteness(queue) {
|
| 594 | 594 | GlobalScope.launch(IO) {
|
| 595 | - components.integrityClient.warmUp()
|
|
| 595 | + components.warmUpIntegrityClient()
|
|
| 596 | 596 | }
|
| 597 | 597 | }
|
| 598 | 598 | }
|
| ... | ... | @@ -6,8 +6,6 @@ package org.mozilla.fenix.components |
| 6 | 6 | |
| 7 | 7 | import android.content.Context
|
| 8 | 8 | import android.content.SharedPreferences
|
| 9 | -import androidx.core.content.edit
|
|
| 10 | -import mozilla.components.lib.integrity.googleplay.RequestHashProvider
|
|
| 11 | 9 | import mozilla.components.lib.llm.mlpa.UserIdProvider
|
| 12 | 10 | import mozilla.components.lib.llm.mlpa.service.UserId
|
| 13 | 11 | import mozilla.components.support.ktx.kotlin.toHexString
|
| ... | ... | @@ -39,9 +37,15 @@ fun interface Hasher { |
| 39 | 37 | |
| 40 | 38 | /**
|
| 41 | 39 | * Generates and persists a stable per-install UUID, used to identify this client
|
| 42 | - * consistently across [UserIdProvider] and [RequestHashProvider] consumers.
|
|
| 40 | + * consistently across [UserIdProvider] consumers and other callers that need a
|
|
| 41 | + * stable per-request hash derived from that UUID.
|
|
| 43 | 42 | */
|
| 44 | -interface ClientUUID : UserIdProvider, RequestHashProvider {
|
|
| 43 | +interface ClientUUID : UserIdProvider {
|
|
| 44 | + /**
|
|
| 45 | + * Generates a hash derived from the client's stable UUID.
|
|
| 46 | + */
|
|
| 47 | + fun generateHash(): String
|
|
| 48 | + |
|
| 45 | 49 | companion object {
|
| 46 | 50 | /**
|
| 47 | 51 | * Convenience initializer that creates a [SharedPreferences] to be used by [ClientUUID].
|
| ... | ... | @@ -62,12 +66,9 @@ internal class PrefsBackedClientUUID( |
| 62 | 66 | private val generateUUID: () -> String = { UUID.randomUUID().toString() },
|
| 63 | 67 | private val hasher: Hasher = Hasher.sha256,
|
| 64 | 68 | ) : ClientUUID {
|
| 69 | + // tor-browser#45134: never expose a unique, trackable per-install identifier.
|
|
| 65 | 70 | private val uuid: String by lazy {
|
| 66 | - getPrefs().let { prefs ->
|
|
| 67 | - prefs.getString(KEY, null) ?: generateUUID().also {
|
|
| 68 | - prefs.edit { putString(KEY, it) }
|
|
| 69 | - }
|
|
| 70 | - }
|
|
| 71 | + NIL_UUID
|
|
| 71 | 72 | }
|
| 72 | 73 | |
| 73 | 74 | override fun getUserId() = UserId(uuid)
|
| ... | ... | @@ -76,5 +77,6 @@ internal class PrefsBackedClientUUID( |
| 76 | 77 | |
| 77 | 78 | companion object {
|
| 78 | 79 | private const val KEY = "uuid"
|
| 80 | + private const val NIL_UUID = "00000000-0000-0000-0000-000000000000"
|
|
| 79 | 81 | }
|
| 80 | 82 | } |
| ... | ... | @@ -19,6 +19,7 @@ import kotlinx.coroutines.MainScope |
| 19 | 19 | import kotlinx.coroutines.SupervisorJob
|
| 20 | 20 | import mozilla.components.concept.ai.controls.AIFeatureBlock
|
| 21 | 21 | import mozilla.components.concept.ai.controls.AIFeatureRegistry
|
| 22 | +import mozilla.components.concept.integrity.IntegrityClient
|
|
| 22 | 23 | import mozilla.components.feature.addons.AddonManager
|
| 23 | 24 | import mozilla.components.feature.addons.amo.AMOAddonsProvider
|
| 24 | 25 | import mozilla.components.feature.addons.migration.DefaultSupportedAddonsChecker
|
| ... | ... | @@ -31,7 +32,6 @@ import mozilla.components.lib.ai.controls.dataStore |
| 31 | 32 | import mozilla.components.lib.ai.controls.default
|
| 32 | 33 | import mozilla.components.lib.crash.store.CrashAction
|
| 33 | 34 | import mozilla.components.lib.crash.store.CrashMiddleware
|
| 34 | -import mozilla.components.lib.integrity.googleplay.GooglePlayIntegrityClient
|
|
| 35 | 35 | import mozilla.components.lib.llm.mlpa.MlpaTokenStorage
|
| 36 | 36 | import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
| 37 | 37 | import mozilla.components.service.fxrelay.eligibility.RelayEligibilityStore
|
| ... | ... | @@ -437,14 +437,18 @@ class Components(private val context: Context) { |
| 437 | 437 | )
|
| 438 | 438 | }
|
| 439 | 439 | |
| 440 | - val integrityClient by lazyMonitored {
|
|
| 441 | - GooglePlayIntegrityClient.create(
|
|
| 442 | - context = context,
|
|
| 443 | - projectNumberToken = BuildConfig.GPS_INTEGRITY_TOKEN,
|
|
| 444 | - requestHashProvider = clientUUID,
|
|
| 445 | - )
|
|
| 440 | + // tor-browser#45085: Disable Google Play Integrity
|
|
| 441 | + val integrityClient: IntegrityClient by lazyMonitored {
|
|
| 442 | + IntegrityClient { Result.failure(IllegalStateException("Google Play Integrity is disabled")) }
|
|
| 446 | 443 | }
|
| 447 | 444 | |
| 445 | + /**
|
|
| 446 | + * Eagerly initializes the underlying Play Integrity token provider. This is exposed
|
|
| 447 | + * separately from [integrityClient] because warm-up is specific to the Google
|
|
| 448 | + * Play-backed implementation and isn't part of the [IntegrityClient] concept.
|
|
| 449 | + */
|
|
| 450 | + suspend fun warmUpIntegrityClient(): Boolean = false // tor-browser#45085: no-op
|
|
| 451 | + |
|
| 448 | 452 | val termsOfUsePromptRepository by lazyMonitored {
|
| 449 | 453 | DefaultTermsOfUsePromptRepository(settings)
|
| 450 | 454 | }
|
| ... | ... | @@ -5,8 +5,7 @@ |
| 5 | 5 | package org.mozilla.fenix.components.llm
|
| 6 | 6 | |
| 7 | 7 | import mozilla.components.concept.fetch.Client
|
| 8 | -import mozilla.components.lib.integrity.googleplay.GooglePlayIntegrityClient
|
|
| 9 | -import mozilla.components.lib.integrity.googleplay.IntegrityConsumer
|
|
| 8 | +import mozilla.components.concept.integrity.IntegrityClient
|
|
| 10 | 9 | import mozilla.components.lib.llm.mlpa.MlpaLlmProvider
|
| 11 | 10 | import mozilla.components.lib.llm.mlpa.MlpaTokenProvider
|
| 12 | 11 | import mozilla.components.lib.llm.mlpa.MlpaTokenStorage
|
| ... | ... | @@ -25,7 +24,7 @@ class Llm( |
| 25 | 24 | private val client: Client,
|
| 26 | 25 | private val storage: MlpaTokenStorage,
|
| 27 | 26 | private val fxaTokenProvider: FxaAccessTokenProvider,
|
| 28 | - private val integrityClient: GooglePlayIntegrityClient,
|
|
| 27 | + private val integrityClient: IntegrityClient,
|
|
| 29 | 28 | private val userIdProvider: UserIdProvider,
|
| 30 | 29 | ) {
|
| 31 | 30 | |
| ... | ... | @@ -36,7 +35,7 @@ class Llm( |
| 36 | 35 | MlpaTokenProvider.choose(
|
| 37 | 36 | MlpaTokenProvider.fxaTokenProvider(fxaTokenProvider),
|
| 38 | 37 | MlpaTokenProvider.mlpaIntegrityHandshake(
|
| 39 | - integrityClient = integrityClient.forConsumer(IntegrityConsumer.Summarize),
|
|
| 38 | + integrityClient = integrityClient,
|
|
| 40 | 39 | authenticationService = fenixMlpaService,
|
| 41 | 40 | userIdProvider = userIdProvider,
|
| 42 | 41 | storage = storage,
|
| ... | ... | @@ -7,9 +7,25 @@ package org.mozilla.fenix.components |
| 7 | 7 | import mozilla.components.lib.llm.mlpa.service.UserId
|
| 8 | 8 | import mozilla.components.support.test.fakes.android.FakeSharedPreferences
|
| 9 | 9 | import org.junit.Assert.assertEquals
|
| 10 | +import org.junit.Ignore
|
|
| 10 | 11 | import org.junit.Test
|
| 11 | 12 | |
| 12 | 13 | class ClientUUIDTest {
|
| 14 | + @Test
|
|
| 15 | + fun `that the client uuid is always the nil uuid, regardless of generateUUID`() {
|
|
| 16 | + val prefs = FakeSharedPreferences()
|
|
| 17 | + val nilUuid = UserId("00000000-0000-0000-0000-000000000000")
|
|
| 18 | + |
|
| 19 | + val first = PrefsBackedClientUUID({ prefs }, generateUUID = { "my-generated-uuid" })
|
|
| 20 | + assertEquals(nilUuid, first.getUserId())
|
|
| 21 | + // idempotency check
|
|
| 22 | + assertEquals(nilUuid, first.getUserId())
|
|
| 23 | + |
|
| 24 | + val second = PrefsBackedClientUUID({ prefs }, generateUUID = { "another-generated-uuid" })
|
|
| 25 | + assertEquals(nilUuid, second.getUserId())
|
|
| 26 | + }
|
|
| 27 | + |
|
| 28 | + @Ignore("tor-browser#45134: PrefsBackedClientUUID always returns the nil uuid, see the test above")
|
|
| 13 | 29 | @Test
|
| 14 | 30 | fun `that a client uuid will only be generated the first time`() {
|
| 15 | 31 | val prefs = FakeSharedPreferences()
|
| ... | ... | @@ -25,6 +41,7 @@ class ClientUUIDTest { |
| 25 | 41 | assertEquals(UserId("my-generated-uuid"), second.getUserId())
|
| 26 | 42 | }
|
| 27 | 43 | |
| 44 | + @Ignore("tor-browser#45134: PrefsBackedClientUUID always returns the nil uuid, so the hash is no longer derived from generateUUID's output")
|
|
| 28 | 45 | @Test
|
| 29 | 46 | fun `that generateHash uses the provided hasher`() {
|
| 30 | 47 | val prefs = FakeSharedPreferences()
|