From 90b1e5c2620b2547e4da9099cc0c2973a40a9e57 Mon Sep 17 00:00:00 2001 From: Jonathan Almeida Date: Mon, 29 Jul 2019 17:24:49 -0400 Subject: [PATCH] Closes #4355: unsubscribe FxA subscription on logout --- .../fenix/components/BackgroundServices.kt | 129 +++++++++++------- 1 file changed, 82 insertions(+), 47 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt index f7875f981..a5be114ab 100644 --- a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt +++ b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.components import android.content.Context +import android.content.SharedPreferences import android.os.Build import android.preference.PreferenceManager import androidx.lifecycle.ProcessLifecycleOwner @@ -89,47 +90,11 @@ class BackgroundServices( val pushService by lazy { FirebasePush() } val push by lazy { - val logger = Logger("AutoPushFeature") - AutoPushFeature(context = context, service = pushService, config = pushConfig!!).also { - // Notify observers for Services' messages. - it.registerForPushMessages(PushType.Services, object : Bus.Observer { - override fun onEvent(type: PushType, message: String) { - accountManager.authenticatedAccount()?.deviceConstellation() - ?.processRawEventAsync(message) - } - }, ProcessLifecycleOwner.get(), false) - - // Notify observers for subscription changes. - it.registerForSubscriptions(object : PushSubscriptionObserver { - override fun onSubscriptionAvailable(subscription: AutoPushSubscription) { - // Update for only the services subscription. - if (subscription.type == PushType.Services) { - logger.info("New push subscription received for FxA") - accountManager.authenticatedAccount()?.deviceConstellation() - ?.setDevicePushSubscriptionAsync( - DevicePushSubscription( - endpoint = subscription.endpoint, - publicKey = subscription.publicKey, - authKey = subscription.authKey - ) - ) - } - } - }, ProcessLifecycleOwner.get(), false) - - // For all the current Fenix users, we need to remove the current push token and - // re-subscribe again on the right push server. We should never do this otherwise! - // Should be removed after majority of our users are correctly subscribed. - // See: https://github.com/mozilla-mobile/fenix/issues/4218 - - val preferences = PreferenceManager.getDefaultSharedPreferences(context) - val prefResetSubKey = "reset_broken_push_subscription" - if (!preferences.getBoolean(prefResetSubKey, false)) { - preferences.edit().putBoolean(prefResetSubKey, true).apply() - logger.info("Forcing push registration renewal") - it.forceRegistrationRenewal() - } - } + AutoPushFeature( + context = context, + service = pushService, + config = pushConfig!! + ) } init { @@ -156,8 +121,11 @@ class BackgroundServices( ) /** - * We add an observer to the AccountManager so that we can control when the Firebase service - * will start/stop. This is only needed when landing the push service to ensure Firebase works + * When we login/logout of FxA, we need to update our push subscriptions to match the newly + * logged in account. + * + * We added the push service to the AccountManager observer so that we can control when the + * service will start/stop. Firebase was added when landing the push service to ensure it works * as expected without causing any (as many) side effects. * * In order to use Firebase with Leanplum and other marketing features, we need it always @@ -167,18 +135,37 @@ class BackgroundServices( * of the send-tab/push feature: https://github.com/mozilla-mobile/fenix/issues/4063 */ private val accountObserver = object : AccountObserver { + // We want to update our subscriptions only on a fresh sign in. + // See https://github.com/mozilla-mobile/android-components/issues/3964 + @Suppress("MayBeConst") // linter is wrong + val prefFreshSignInKey = "fresh_sign_in" + override fun onAuthenticationProblems() {} override fun onProfileUpdated(profile: Profile) {} override fun onLoggedOut() { pushService.stop() + + preferences.edit().putBoolean(prefFreshSignInKey, true).apply() + push.unsubscribeForType(PushType.Services) } override fun onAuthenticated(account: OAuthAccount) { pushService.start(context) + + if (preferences.getBoolean(prefFreshSignInKey, true)) { + preferences.edit().putBoolean(prefFreshSignInKey, false).apply() + push.subscribeForType(PushType.Services) + } } } + private val preferences: SharedPreferences by lazy { + PreferenceManager.getDefaultSharedPreferences( + context + ) + } + val accountManager = FxaAccountManager( context, serverConfig, @@ -191,11 +178,59 @@ class BackgroundServices( // See https://github.com/mozilla-mobile/android-components/issues/3732 setOf("https://identity.mozilla.com/apps/oldsync") ).also { - it.registerForDeviceEvents(deviceEventObserver, ProcessLifecycleOwner.get(), false) + if (FeatureFlags.sendTabEnabled) { + it.registerForDeviceEvents(deviceEventObserver, ProcessLifecycleOwner.get(), false) - // This should be removed in the future. See comment on `accountObserver`. - if (FeatureFlags.sendTabEnabled && pushConfig != null) { - it.register(accountObserver) + // Enable push if we have the config. + if (pushConfig != null) { + + // Register our account observer so we know how to update our push subscriptions. + it.register(accountObserver) + + val logger = Logger("AutoPushFeature") + + // Notify observers for Services' messages. + push.registerForPushMessages( + PushType.Services, + object : Bus.Observer { + override fun onEvent(type: PushType, message: String) { + it.authenticatedAccount()?.deviceConstellation() + ?.processRawEventAsync(message) + } + }, + ProcessLifecycleOwner.get(), + false + ) + + // Notify observers for subscription changes. + push.registerForSubscriptions(object : PushSubscriptionObserver { + override fun onSubscriptionAvailable(subscription: AutoPushSubscription) { + // Update for only the services subscription. + if (subscription.type == PushType.Services) { + logger.info("New push subscription received for FxA") + it.authenticatedAccount()?.deviceConstellation() + ?.setDevicePushSubscriptionAsync( + DevicePushSubscription( + endpoint = subscription.endpoint, + publicKey = subscription.publicKey, + authKey = subscription.authKey + ) + ) + } + } + }, ProcessLifecycleOwner.get(), false) + + // For all the current Fenix users, we need to remove the current push token and + // re-subscribe again on the right push server. We should never do this otherwise! + // Should be removed after majority of our users are correctly subscribed. + // See: https://github.com/mozilla-mobile/fenix/issues/4218 + val prefResetSubKey = "reset_broken_push_subscription" + if (!preferences.getBoolean(prefResetSubKey, false)) { + preferences.edit().putBoolean(prefResetSubKey, true).apply() + logger.info("Forcing push registration renewal") + push.forceRegistrationRenewal() + } + } } CoroutineScope(Dispatchers.Main).launch { it.initAsync().await() } }