diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/MessageNotificationWorker.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/MessageNotificationWorker.kt index 74abfe6837..9f6d2b6855 100644 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/MessageNotificationWorker.kt +++ b/app/src/main/java/org/mozilla/fenix/gleanplumb/MessageNotificationWorker.kt @@ -192,8 +192,9 @@ class NotificationDismissedService : Service() { NimbusMessagingController(applicationContext.components.analytics.messagingStorage) // Get the relevant message. - val messageId = intent.getStringExtra(DISMISSED_MESSAGE_ID)!! - val message = runBlockingIncrement { nimbusMessagingController.getMessage(messageId) } + val message = intent.getStringExtra(DISMISSED_MESSAGE_ID) ?.let { messageId -> + runBlockingIncrement { nimbusMessagingController.getMessage(messageId) } + } if (message != null) { // Update message as 'dismissed'. @@ -220,8 +221,9 @@ class NotificationClickedReceiverActivity : Activity() { NimbusMessagingController(components.analytics.messagingStorage) // Get the relevant message. - val messageId = intent.getStringExtra(CLICKED_MESSAGE_ID)!! - val message = runBlockingIncrement { nimbusMessagingController.getMessage(messageId) } + val message = intent.getStringExtra(CLICKED_MESSAGE_ID) ?.let { messageId -> + runBlockingIncrement { nimbusMessagingController.getMessage(messageId) } + } if (message != null) { // Update message as 'clicked'. diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingController.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingController.kt index 4680ee04d6..2ab9e623cc 100644 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingController.kt +++ b/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingController.kt @@ -84,7 +84,7 @@ class NimbusMessagingController( * @return the [Message] with a matching [id], or null if no [Message] has a matching [id]. */ suspend fun getMessage(id: String): Message? { - return messagingStorage.getMessages().find { it.id == id } + return messagingStorage.getMessage(id) } /** diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorage.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorage.kt index 0873d62c53..6fe8f37a56 100644 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorage.kt +++ b/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorage.kt @@ -53,7 +53,30 @@ class NimbusMessagingStorage( get() = attributeProvider?.getCustomAttributes(context) ?: JSONObject() /** - * Returns a list of available messages descending sorted by their priority. + * Returns the [Message] for the given [key] or returns null if none found. + */ + @Suppress("ReturnCount") + suspend fun getMessage(key: String): Message? { + val featureValue = messagingFeature.value() + val value = featureValue.messages[key] ?: return null + val trigger = sanitizeTriggers(key, value.trigger, featureValue.triggers) ?: return null + val action = sanitizeAction(key, value.action, featureValue.actions, value.isControl) ?: return null + val defaultStyle = StyleData() + val storageMetadata = metadataStorage.getMetadata() + + return Message( + id = key, + data = value, + action = action, + style = featureValue.styles[value.style] ?: defaultStyle, + metadata = storageMetadata[key] ?: addMetadata(key), + triggers = trigger, + ) + } + + /** + * Returns a list of currently available messages descending sorted by their priority. + * This list of messages will not include any expired, pressed or dismissed messages. */ suspend fun getMessages(): List { val featureValue = messagingFeature.value() diff --git a/app/src/test/java/org/mozilla/fenix/gleanplumb/NimbusMessagingControllerTest.kt b/app/src/test/java/org/mozilla/fenix/gleanplumb/NimbusMessagingControllerTest.kt index 7586e81cd2..b3273751b6 100644 --- a/app/src/test/java/org/mozilla/fenix/gleanplumb/NimbusMessagingControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/gleanplumb/NimbusMessagingControllerTest.kt @@ -283,27 +283,8 @@ class NimbusMessagingControllerTest { fun `GIVEN stored messages contains a matching message WHEN calling getMessage THEN return the matching message`() = coroutineScope.runTest { val message1 = createMessage("1") - val message2 = createMessage("2") - val message3 = createMessage("3") - val messages = listOf(message1, message2, message3) - coEvery { storage.getMessages() }.returns(messages) - - val actualMessage = controller.getMessage(message2.id) - - assertEquals(message2, actualMessage) - } - - @Test - fun `GIVEN stored messages contains multiple matching messages WHEN calling getMessage THEN return the first matching message`() = - coroutineScope.runTest { - val id = "same id" - val message1 = createMessage(id) - val message2 = createMessage(id) - val message3 = createMessage(id) - val messages = listOf(message1, message2, message3) - coEvery { storage.getMessages() }.returns(messages) - - val actualMessage = controller.getMessage(id) + coEvery { storage.getMessage(message1.id) }.returns(message1) + val actualMessage = controller.getMessage(message1.id) assertEquals(message1, actualMessage) } @@ -311,12 +292,7 @@ class NimbusMessagingControllerTest { @Test fun `GIVEN stored messages doesn't contain a matching message WHEN calling getMessage THEN return null`() = coroutineScope.runTest { - val message1 = createMessage("1") - val message2 = createMessage("2") - val message3 = createMessage("3") - val messages = listOf(message1, message2, message3) - coEvery { storage.getMessages() }.returns(messages) - + coEvery { storage.getMessage("unknown id") }.returns(null) val actualMessage = controller.getMessage("unknown id") assertNull(actualMessage) diff --git a/app/src/test/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorageTest.kt b/app/src/test/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorageTest.kt index b1a06b9725..983c8a7d2a 100644 --- a/app/src/test/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorageTest.kt +++ b/app/src/test/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorageTest.kt @@ -600,6 +600,45 @@ class NimbusMessagingStorageTest { verify { messagingFeature wasNot Called } } + @Test + fun `WHEN calling getMessage THEN return message with matching key OR null if doesn't exist`() = + runTest { + val messages = mapOf( + "low-message" to createMessageData(style = "low-priority"), + "high-message" to createMessageData(style = "high-priority"), + "medium-message" to createMessageData(style = "medium-priority"), + ) + val styles = mapOf( + "high-priority" to createStyle(priority = 100), + "medium-priority" to createStyle(priority = 50), + "low-priority" to createStyle(priority = 1), + ) + val metadataStorage: MessageMetadataStorage = mockk(relaxed = true) + val messagingFeature = createMessagingFeature( + styles = styles, + messages = messages, + ) + + coEvery { metadataStorage.getMetadata() } returns mapOf( + "message-1" to Message.Metadata( + id = "message-1", + ), + ) + + val storage = NimbusMessagingStorage( + testContext, + metadataStorage, + reportMalformedMessage, + gleanPlumb, + messagingFeature, + ) + + assertEquals("high-message", storage.getMessage("high-message")?.id) + assertEquals("medium-message", storage.getMessage("medium-message")?.id) + assertEquals("low-message", storage.getMessage("low-message")?.id) + assertEquals(null, storage.getMessage("no-message")?.id) + } + private fun createMessageData( action: String = "action-1", style: String = "style-1",