[fenix] For https://github.com/mozilla-mobile/fenix/issues/9059: Add WebPush engine integration
parent
63f1556fbf
commit
cf1971176c
@ -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)
|
Loading…
Reference in New Issue