Commit 98db88f8 authored by MozLando's avatar MozLando
Browse files

Merge #6126

6126: Closes #6125: Reset FxA push subscriptions to new format r=csadilek a=jonalmeida
Co-authored-by: default avatarJonathan Almeida <>
parents 1e5bfb16 a4438647
......@@ -108,8 +108,12 @@ internal class AccountObserver(
private val logger = Logger(
private val constellationObserver = ConstellationObserver(context, push)
private val pushReset = OneTimeFxaPushReset(context, push)
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
// We need a new subscription only when we have a new account.
// The subscription is removed when an account logs out.
if (authType != AuthType.Existing && authType != AuthType.Recovered) {
......@@ -278,6 +282,48 @@ internal class VerificationDelegate(context: Context) : SharedPreferencesCache<V
* Resets the fxa push scope (and therefore push subscription) if it does not follow the new format.
* This is needed only for our existing push users and can be removed when we're more confident our users are
* all migrated.
* Implementation Notes: In order to support a new performance fix related to push and
* [FxaAccountManager] we need to use a new push scope format. This class checks if we have the old
* format, and removes it if so, thereby generating a new push scope with the new format.
class OneTimeFxaPushReset(
private val context: Context,
private val pushFeature: AutoPushFeature
) {
* Resets the push subscription if the old subscription format is used.
fun resetSubscriptionIfNeeded(account: OAuthAccount) {
val pushScope = preference(context).getString(PREF_FXA_SCOPE, null) ?: return
if (pushScope.contains(FxaPushSupportFeature.PUSH_SCOPE_PREFIX)) {
val newPushScope = FxaPushSupportFeature.PUSH_SCOPE_PREFIX + pushScope
pushFeature.subscribe(newPushScope) { subscription ->
endpoint = subscription.endpoint,
publicKey = subscription.publicKey,
authKey = subscription.authKey
preference(context).edit().putString(PREF_FXA_SCOPE, newPushScope).apply()
internal data class VerificationState(val timestamp: Long, val totalCount: Int)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at
package mozilla.components.feature.accounts.push
import mozilla.components.concept.sync.DeviceConstellation
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.feature.accounts.push.FxaPushSupportFeature.Companion.PUSH_SCOPE_PREFIX
import mozilla.components.feature.push.AutoPushFeature
import mozilla.components.feature.push.AutoPushSubscription
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.`when`
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
import org.robolectric.RobolectricTestRunner
class OneTimeFxaPushResetTest {
private val pushFeature: AutoPushFeature = mock()
private val account: OAuthAccount = mock()
private val constellation: DeviceConstellation = mock()
fun setup() {
fun `no changes are made if a scope does not exist`() {
val reset = OneTimeFxaPushReset(testContext, pushFeature)
assertNull(preference(testContext).getString(PREF_FXA_SCOPE, null))
fun `existing valid new scope format does nothing`() {
val validPushScope = PUSH_SCOPE_PREFIX + "12345"
preference(testContext).edit().putString(PREF_FXA_SCOPE, validPushScope).apply()
val reset = OneTimeFxaPushReset(testContext, pushFeature)
val testScope = preference(testContext).getString(PREF_FXA_SCOPE, null)
assertEquals(validPushScope, testScope)
fun `existing invalid scope format is updated`() {
preference(testContext).edit().putString(PREF_FXA_SCOPE, "12345").apply()
val validPushScope = PUSH_SCOPE_PREFIX + "12345"
val reset = OneTimeFxaPushReset(testContext, pushFeature)
`when`(pushFeature.subscribe(any(), nullable(), any(), any())).thenAnswer {
// Invoke the `onSubscribe` lambda with a fake subscription.
(it.arguments[3] as ((AutoPushSubscription) -> Unit)).invoke(
scope = validPushScope,
endpoint = "https://foo",
publicKey = "p256dh",
authKey = "auth",
appServerKey = null
verify(pushFeature).unsubscribe(eq("12345"), any(), any())
verify(pushFeature).subscribe(eq(validPushScope), nullable(), any(), any())
assertEquals(validPushScope, preference(testContext).getString(PREF_FXA_SCOPE, null))
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment