1
0
Fork 0

For #9059: Add WebPush engine integration

master
Jonathan Almeida 2020-03-09 15:38:00 -04:00 committed by Jonathan Almeida
parent 667ebe3142
commit ef42becbf9
2 changed files with 123 additions and 0 deletions

View File

@ -37,6 +37,7 @@ import org.mozilla.fenix.components.Components
import org.mozilla.fenix.components.metrics.MetricServiceType
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.push.PushFxaIntegration
import org.mozilla.fenix.push.WebPushEngineIntegration
import org.mozilla.fenix.session.NotificationSessionObserver
import org.mozilla.fenix.session.PerformanceActivityLifecycleCallbacks
import org.mozilla.fenix.session.VisibilityLifecycleCallback
@ -182,6 +183,9 @@ open class FenixApplication : LocaleAwareApplication() {
// Install the AutoPush singleton to receive messages.
PushProcessor.install(it)
// WebPush integration to observe and deliver push messages to engine.
WebPushEngineIntegration(components.core.engine, it).start()
// Perform a one-time initialization of the account manager if a message is received.
PushFxaIntegration(it, lazy { components.backgroundServices.accountManager }).launch()

View File

@ -0,0 +1,119 @@
/* 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 http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.push
import android.util.Base64
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import mozilla.components.concept.engine.Engine
import mozilla.components.concept.engine.webpush.WebPushDelegate
import mozilla.components.concept.engine.webpush.WebPushHandler
import mozilla.components.concept.engine.webpush.WebPushSubscription
import mozilla.components.feature.push.AutoPushFeature
import mozilla.components.feature.push.AutoPushSubscription
import mozilla.components.feature.push.PushScope
import mozilla.components.support.base.log.logger.Logger
/**
* Engine integration with the push feature to enable WebPush support.
*/
class WebPushEngineIntegration(
private val engine: Engine,
private val pushFeature: AutoPushFeature
) : AutoPushFeature.Observer {
private var handler: WebPushHandler? = null
private val delegate = WebPushEngineDelegate(pushFeature)
fun start() {
handler = engine.registerWebPushDelegate(delegate)
pushFeature.register(this)
}
fun stop() {
pushFeature.unregister(this)
}
override fun onMessageReceived(scope: PushScope, message: ByteArray?) {
CoroutineScope(Dispatchers.Main).launch {
handler?.onPushMessage(scope, message)
}
}
override fun onSubscriptionChanged(scope: PushScope) {
CoroutineScope(Dispatchers.Main).launch {
handler?.onSubscriptionChanged(scope)
}
}
}
internal class WebPushEngineDelegate(
private val pushFeature: AutoPushFeature
) : WebPushDelegate {
private val logger = Logger("WebPushEngineDelegate")
override fun onGetSubscription(scope: String, onSubscription: (WebPushSubscription?) -> Unit) {
// We don't have the appServerKey unless an app is creating a new subscription so we
// allow the key to be null since it won't be overridden from a previous subscription.
pushFeature.subscribe(
scope = scope,
onSubscribeError = {
logger.error("Error on push onGetSubscription.")
onSubscription(null)
},
onSubscribe = { subscription ->
onSubscription(subscription.toEnginePushSubscription())
})
}
override fun onSubscribe(
scope: String,
serverKey: ByteArray?,
onSubscribe: (WebPushSubscription?) -> Unit
) {
pushFeature.subscribe(
scope = scope,
// See the full note at the implementation of `toEnginePushSubscription`.
// Issue: https://github.com/mozilla/application-services/issues/2698
appServerKey = null,
onSubscribeError = {
logger.error("Error on push onSubscribe.")
onSubscribe(null)
},
onSubscribe = { subscription ->
onSubscribe(subscription.toEnginePushSubscription())
})
}
override fun onUnsubscribe(scope: String, onUnsubscribe: (Boolean) -> Unit) {
pushFeature.unsubscribe(
scope = scope,
onUnsubscribeError = {
logger.error("Error on push onUnsubscribe.")
onUnsubscribe(false)
},
onUnsubscribe = { result ->
onUnsubscribe(result)
})
}
}
internal fun AutoPushSubscription.toEnginePushSubscription() = WebPushSubscription(
scope = this.scope,
publicKey = this.publicKey.toDecodedByteArray(),
endpoint = this.endpoint,
authSecret = this.authKey.toDecodedByteArray(),
// We don't send the `serverKey` because the code path from that will query
// the push database for this key, which leads to an exception thrown.
// Our workaround for now is to not put the server key in to begin with (which
// will probably break a lot of sites).
// See: https://github.com/mozilla/application-services/issues/2698
appServerKey = null
)
private fun String.toDecodedByteArray() =
Base64.decode(this.toByteArray(), Base64.URL_SAFE or Base64.NO_PADDING or Base64.NO_WRAP)