Unverified Commit 0b6cd83e authored by Jonathan Almeida's avatar Jonathan Almeida
Browse files

Close #6957: Allow nullable encoding param in push messages

We fall back to the "aes128gcm" encoding if the value is not provided.
parent df2b7c35
......@@ -85,10 +85,10 @@ data class EncryptedPushMessage(
operator fun invoke(
channelId: String,
body: String?,
encoding: String,
encoding: String?,
salt: String? = null,
cryptoKey: String? = null
) = EncryptedPushMessage(channelId, body, encoding, salt ?: "", cryptoKey ?: "")
) = EncryptedPushMessage(channelId, body, encoding ?: "aes128gcm", salt ?: "", cryptoKey ?: "")
}
}
......
......@@ -31,4 +31,27 @@ interface PushService {
* If the push service is support on the device.
*/
fun isServiceAvailable(context: Context): Boolean
companion object {
/**
* Message key for "channel ID" in a push message.
*/
const val MESSAGE_KEY_CHANNEL_ID = "chid"
/**
* Message key for the body in a push message.
*/
const val MESSAGE_KEY_BODY = "body"
/**
* Message key for encoding in a push message.
*/
const val MESSAGE_KEY_ENCODING = "con"
/**
* Message key for encryption salt in a push message.
*/
const val MESSAGE_KEY_SALT = "enc"
/**
* Message key for "cryptoKey" in a push message.
*/
const val MESSAGE_KEY_CRYPTO_KEY = "cryptokey"
}
}
......@@ -14,6 +14,11 @@ import mozilla.components.concept.push.EncryptedPushMessage
import mozilla.components.concept.push.PushError
import mozilla.components.concept.push.PushProcessor
import mozilla.components.concept.push.PushService
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_BODY
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_CHANNEL_ID
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_CRYPTO_KEY
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_ENCODING
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_SALT
import mozilla.components.support.base.log.logger.Logger
/**
......@@ -56,21 +61,19 @@ abstract class AbstractAmazonPushService : ADMMessageHandlerBase("AbstractAmazon
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
public override fun onMessage(intent: Intent) {
intent.extras?.let {
val message = try {
EncryptedPushMessage(
channelId = it.getStringWithException("chid"),
encoding = it.getStringWithException("con"),
body = it.getString("body"),
salt = it.getString("enc"),
cryptoKey = it.getString("cryptokey")
)
} catch (e: NoSuchElementException) {
PushProcessor.requireInstance.onError(
PushError.MalformedMessage("parsing encrypted message failed: $e")
)
// This is not an AutoPush message we can handle.
if (!it.containsKey(MESSAGE_KEY_CHANNEL_ID)) {
return
}
val message = EncryptedPushMessage(
channelId = it.getStringWithException(MESSAGE_KEY_CHANNEL_ID),
encoding = it.getString(MESSAGE_KEY_ENCODING),
body = it.getString(MESSAGE_KEY_BODY),
salt = it.getString(MESSAGE_KEY_SALT),
cryptoKey = it.getString(MESSAGE_KEY_CRYPTO_KEY)
)
// In case of any errors, let the PushProcessor handle this exception. Instead of crashing
// here, just drop the message on the floor. This is fine, since we don't really need to
// "recover" from a bad incoming message.
......
......@@ -12,6 +12,12 @@ import com.amazon.device.messaging.ADMMessageHandlerBase
import mozilla.components.concept.push.EncryptedPushMessage
import mozilla.components.concept.push.PushError
import mozilla.components.concept.push.PushProcessor
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_BODY
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_CHANNEL_ID
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_CRYPTO_KEY
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_ENCODING
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_SALT
import mozilla.components.support.test.any
import mozilla.components.support.test.argumentCaptor
import mozilla.components.support.test.mock
import mozilla.components.support.test.robolectric.testContext
......@@ -61,11 +67,11 @@ class AbstractAmazonPushServiceTest {
fun `new encrypted messages are passed to the processor`() {
val messageIntent = Intent()
val bundleExtra = Bundle()
bundleExtra.putString("chid", "1234")
bundleExtra.putString("body", "contents")
bundleExtra.putString("con", "encoding")
bundleExtra.putString("enc", "salt")
bundleExtra.putString("cryptokey", "dh256")
bundleExtra.putString(MESSAGE_KEY_CHANNEL_ID, "1234")
bundleExtra.putString(MESSAGE_KEY_BODY, "contents")
bundleExtra.putString(MESSAGE_KEY_ENCODING, "encoding")
bundleExtra.putString(MESSAGE_KEY_SALT, "salt")
bundleExtra.putString(MESSAGE_KEY_CRYPTO_KEY, "dh256")
val captor = argumentCaptor<EncryptedPushMessage>()
messageIntent.putExtras(bundleExtra)
......@@ -99,19 +105,22 @@ class AbstractAmazonPushServiceTest {
}
@Test
fun `malformed message exception handled with the processor`() {
fun `malformed message exception should not be thrown`() {
val messageIntent = Intent()
val bundleExtra = Bundle()
bundleExtra.putString("con", "qu2to2")
bundleExtra.putString(MESSAGE_KEY_CHANNEL_ID, "1234")
val captor = argumentCaptor<PushError>()
val captor = argumentCaptor<EncryptedPushMessage>()
messageIntent.putExtras(bundleExtra)
service.onMessage(messageIntent)
verify(processor).onError(captor.capture())
verify(processor, never()).onError(any())
verify(processor).onMessageReceived(captor.capture())
assertTrue(captor.value is PushError.MalformedMessage)
assertTrue(captor.value.message.contains("NoSuchElementException"))
assertEquals("1234", captor.value.channelId)
assertEquals("aes128gcm", captor.value.encoding)
assertEquals("", captor.value.salt)
assertEquals("", captor.value.cryptoKey)
}
@Test
......
......@@ -18,6 +18,11 @@ import mozilla.components.concept.push.EncryptedPushMessage
import mozilla.components.concept.push.PushError
import mozilla.components.concept.push.PushProcessor
import mozilla.components.concept.push.PushService
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_BODY
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_CHANNEL_ID
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_CRYPTO_KEY
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_ENCODING
import mozilla.components.concept.push.PushService.Companion.MESSAGE_KEY_SALT
import mozilla.components.support.base.log.logger.Logger
import java.io.IOException
import kotlin.coroutines.CoroutineContext
......@@ -50,20 +55,13 @@ abstract class AbstractFirebasePushService(
return
}
val message = try {
EncryptedPushMessage(
channelId = it.data.getValue(MESSAGE_KEY_CHANNEL_ID),
encoding = it.data.getValue(MESSAGE_KEY_ENCODING),
body = it.data[MESSAGE_KEY_BODY],
salt = it.data[MESSAGE_KEY_SALT],
cryptoKey = it.data[MESSAGE_KEY_CRYPTO_KEY]
)
} catch (e: NoSuchElementException) {
PushProcessor.requireInstance.onError(
PushError.MalformedMessage("parsing encrypted message failed: $e")
)
return
}
val message = EncryptedPushMessage(
channelId = it.data.getValue(MESSAGE_KEY_CHANNEL_ID),
encoding = it.data[MESSAGE_KEY_ENCODING],
body = it.data[MESSAGE_KEY_BODY],
salt = it.data[MESSAGE_KEY_SALT],
cryptoKey = it.data[MESSAGE_KEY_CRYPTO_KEY]
)
// In case of any errors, let the PushProcessor handle this exception. Instead of crashing
// here, just drop the message on the floor. This is fine, since we don't really need to
......@@ -104,12 +102,4 @@ abstract class AbstractFirebasePushService(
override fun isServiceAvailable(context: Context): Boolean {
return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS
}
companion object {
const val MESSAGE_KEY_CHANNEL_ID = "chid"
const val MESSAGE_KEY_BODY = "body"
const val MESSAGE_KEY_ENCODING = "con"
const val MESSAGE_KEY_SALT = "enc"
const val MESSAGE_KEY_CRYPTO_KEY = "cryptokey"
}
}
......@@ -9,8 +9,8 @@ import com.google.android.gms.common.GoogleApiAvailability
import com.google.firebase.messaging.RemoteMessage
import kotlinx.coroutines.Dispatchers
import mozilla.components.concept.push.EncryptedPushMessage
import mozilla.components.concept.push.PushError
import mozilla.components.concept.push.PushProcessor
import mozilla.components.support.test.any
import mozilla.components.support.test.argumentCaptor
import mozilla.components.support.test.mock
import mozilla.components.support.test.robolectric.testContext
......@@ -21,6 +21,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.`when`
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
......@@ -73,22 +74,22 @@ class AbstractFirebasePushServiceTest {
}
@Test
fun `malformed message exception handled with the processor`() {
fun `malformed message exception should not be thrown`() {
val remoteMessage: RemoteMessage = mock()
val data = mapOf(
"chid" to "1234",
"enc" to "salt",
"body" to "oo3j532j4",
"cryptokey" to "dh256"
"chid" to "1234"
)
val captor = argumentCaptor<PushError>()
val captor = argumentCaptor<EncryptedPushMessage>()
`when`(remoteMessage.data).thenReturn(data)
service.onMessageReceived(remoteMessage)
verify(processor).onError(captor.capture())
verify(processor, never()).onError(any())
verify(processor).onMessageReceived(captor.capture())
assertTrue(captor.value is PushError.MalformedMessage)
assertTrue(captor.value.message.contains("NoSuchElementException"))
assertEquals("1234", captor.value.channelId)
assertEquals("aes128gcm", captor.value.encoding)
assertEquals("", captor.value.salt)
assertEquals("", captor.value.cryptoKey)
}
@Test
......
......@@ -59,6 +59,9 @@ permalink: /changelog/
* **feature-accounts**
* ⚠️ **This is a breaking change**: Refactored component to use `browser-state` instead of `browser-session`. The `FxaWebChannelFeature` now requires a `BrowserStore` instance instead of a `SessionManager`.
* **lib-push-fcm**, **lib-push-adm**, **concept-push**
* Allow nullable encoding values in push messsages. If they are null, we attempt to use `aes128gcm` for encoding.
* **browser-toolbar**
* It will only be animated for vertical scrolls inside the EngineView. Not for horizontal scrolls. Not for zoom gestures.
......
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