mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-17 15:26:23 +00:00
[fenix] For https://github.com/mozilla-mobile/fenix/issues/25446: Ensure for every message shown we have recordExposure
This commit is contained in:
parent
51044beb79
commit
7cb57f1b9a
@ -136,11 +136,6 @@ sealed class AppAction : Action {
|
|||||||
*/
|
*/
|
||||||
data class MessageClicked(val message: Message) : MessagingAction()
|
data class MessageClicked(val message: Message) : MessagingAction()
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates the given [message] was shown.
|
|
||||||
*/
|
|
||||||
data class MessageDisplayed(val message: Message) : MessagingAction()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates the given [message] was dismissed.
|
* Indicates the given [message] was dismissed.
|
||||||
*/
|
*/
|
||||||
|
@ -14,7 +14,6 @@ import org.mozilla.fenix.HomeActivity
|
|||||||
import org.mozilla.fenix.components.AppStore
|
import org.mozilla.fenix.components.AppStore
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageClicked
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageClicked
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDismissed
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDismissed
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDisplayed
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles default interactions with the ui of GleanPlumb messages.
|
* Handles default interactions with the ui of GleanPlumb messages.
|
||||||
@ -44,14 +43,6 @@ class DefaultMessageController(
|
|||||||
appStore.dispatch(MessageDismissed(message))
|
appStore.dispatch(MessageDismissed(message))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMessageDisplayed(message: Message) {
|
|
||||||
if (message.maxDisplayCount <= message.metadata.displayCount + 1) {
|
|
||||||
Messaging.messageExpired.record(Messaging.MessageExpiredExtra(message.id))
|
|
||||||
}
|
|
||||||
Messaging.messageShown.record(Messaging.MessageShownExtra(message.id))
|
|
||||||
appStore.dispatch(MessageDisplayed(message))
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
internal fun handleAction(action: String): Intent {
|
internal fun handleAction(action: String): Intent {
|
||||||
val partialAction = if (action.startsWith("http", ignoreCase = true)) {
|
val partialAction = if (action.startsWith("http", ignoreCase = true)) {
|
||||||
|
@ -17,9 +17,4 @@ interface MessageController {
|
|||||||
* Indicates the provided [message] was dismissed by a user.
|
* Indicates the provided [message] was dismissed by a user.
|
||||||
*/
|
*/
|
||||||
fun onMessageDismissed(message: Message)
|
fun onMessageDismissed(message: Message)
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates the provided [message] was displayed to a user.
|
|
||||||
*/
|
|
||||||
fun onMessageDisplayed(message: Message)
|
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,12 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import mozilla.components.lib.state.Middleware
|
import mozilla.components.lib.state.Middleware
|
||||||
import mozilla.components.lib.state.MiddlewareContext
|
import mozilla.components.lib.state.MiddlewareContext
|
||||||
|
import org.mozilla.fenix.GleanMetrics.Messaging
|
||||||
import org.mozilla.fenix.components.appstate.AppAction
|
import org.mozilla.fenix.components.appstate.AppAction
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.ConsumeMessageToShow
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.ConsumeMessageToShow
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.Evaluate
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.Evaluate
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageClicked
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageClicked
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDismissed
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDismissed
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDisplayed
|
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.Restore
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.Restore
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessageToShow
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessageToShow
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessages
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessages
|
||||||
@ -47,6 +47,7 @@ class MessagingMiddleware(
|
|||||||
val message = messagingStorage.getNextMessage(context.state.messaging.messages)
|
val message = messagingStorage.getNextMessage(context.state.messaging.messages)
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
context.dispatch(UpdateMessageToShow(message))
|
context.dispatch(UpdateMessageToShow(message))
|
||||||
|
onMessagedDisplayed(message, context)
|
||||||
} else {
|
} else {
|
||||||
context.dispatch(ConsumeMessageToShow)
|
context.dispatch(ConsumeMessageToShow)
|
||||||
}
|
}
|
||||||
@ -56,8 +57,6 @@ class MessagingMiddleware(
|
|||||||
|
|
||||||
is MessageDismissed -> onMessageDismissed(context, action.message)
|
is MessageDismissed -> onMessageDismissed(context, action.message)
|
||||||
|
|
||||||
is MessageDisplayed -> onMessagedDisplayed(action.message, context)
|
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
@ -70,6 +69,7 @@ class MessagingMiddleware(
|
|||||||
oldMessage: Message,
|
oldMessage: Message,
|
||||||
context: AppStoreMiddlewareContext
|
context: AppStoreMiddlewareContext
|
||||||
) {
|
) {
|
||||||
|
sendShownMessageTelemetry(oldMessage.id)
|
||||||
val newMetadata = oldMessage.metadata.copy(
|
val newMetadata = oldMessage.metadata.copy(
|
||||||
displayCount = oldMessage.metadata.displayCount + 1,
|
displayCount = oldMessage.metadata.displayCount + 1,
|
||||||
lastTimeShown = now()
|
lastTimeShown = now()
|
||||||
@ -80,6 +80,7 @@ class MessagingMiddleware(
|
|||||||
val newMessages = if (newMetadata.displayCount < oldMessage.maxDisplayCount) {
|
val newMessages = if (newMetadata.displayCount < oldMessage.maxDisplayCount) {
|
||||||
updateMessage(context, oldMessage, newMessage)
|
updateMessage(context, oldMessage, newMessage)
|
||||||
} else {
|
} else {
|
||||||
|
sendExpiredMessageTelemetry(newMessage.id)
|
||||||
consumeMessageToShowIfNeeded(context, oldMessage)
|
consumeMessageToShowIfNeeded(context, oldMessage)
|
||||||
removeMessage(context, oldMessage)
|
removeMessage(context, oldMessage)
|
||||||
}
|
}
|
||||||
@ -89,6 +90,16 @@ class MessagingMiddleware(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
internal fun sendShownMessageTelemetry(messageId: String) {
|
||||||
|
Messaging.messageShown.record(Messaging.MessageShownExtra(messageId))
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
internal fun sendExpiredMessageTelemetry(messageId: String) {
|
||||||
|
Messaging.messageExpired.record(Messaging.MessageExpiredExtra(messageId))
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
internal fun onMessageDismissed(
|
internal fun onMessageDismissed(
|
||||||
context: AppStoreMiddlewareContext,
|
context: AppStoreMiddlewareContext,
|
||||||
|
@ -188,11 +188,6 @@ interface SessionControlController {
|
|||||||
*/
|
*/
|
||||||
fun handleMessageClosed(message: Message)
|
fun handleMessageClosed(message: Message)
|
||||||
|
|
||||||
/**
|
|
||||||
* @see [MessageCardInteractor.onMessageDisplayed]
|
|
||||||
*/
|
|
||||||
fun handleMessageDisplayed(message: Message)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see [TabSessionInteractor.onPrivateModeButtonClicked]
|
* @see [TabSessionInteractor.onPrivateModeButtonClicked]
|
||||||
*/
|
*/
|
||||||
@ -619,10 +614,6 @@ class DefaultSessionControlController(
|
|||||||
messageController.onMessageDismissed(message)
|
messageController.onMessageDismissed(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleMessageDisplayed(message: Message) {
|
|
||||||
messageController.onMessageDisplayed(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handlePrivateModeButtonClicked(
|
override fun handlePrivateModeButtonClicked(
|
||||||
newMode: BrowsingMode,
|
newMode: BrowsingMode,
|
||||||
userHasBeenOnboarded: Boolean
|
userHasBeenOnboarded: Boolean
|
||||||
|
@ -239,11 +239,6 @@ interface MessageCardInteractor {
|
|||||||
* Called when close button on a [Message] card.
|
* Called when close button on a [Message] card.
|
||||||
*/
|
*/
|
||||||
fun onMessageClosedClicked(message: Message)
|
fun onMessageClosedClicked(message: Message)
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when close button on a [Message] card.
|
|
||||||
*/
|
|
||||||
fun onMessageDisplayed(message: Message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -470,8 +465,4 @@ class SessionControlInteractor(
|
|||||||
override fun onMessageClosedClicked(message: Message) {
|
override fun onMessageClosedClicked(message: Message) {
|
||||||
controller.handleMessageClosed(message)
|
controller.handleMessageClosed(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMessageDisplayed(message: Message) {
|
|
||||||
controller.handleMessageDisplayed(message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,6 @@ class MessageCardViewHolder(
|
|||||||
interactor.onMessageClosedClicked(message)
|
interactor.onMessageClosedClicked(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
interactor.onMessageDisplayed(message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -24,7 +24,6 @@ import org.mozilla.fenix.HomeActivity
|
|||||||
import org.mozilla.fenix.components.AppStore
|
import org.mozilla.fenix.components.AppStore
|
||||||
import org.mozilla.fenix.components.appstate.AppAction
|
import org.mozilla.fenix.components.appstate.AppAction
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageClicked
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageClicked
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDisplayed
|
|
||||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
import org.mozilla.fenix.nimbus.MessageData
|
import org.mozilla.fenix.nimbus.MessageData
|
||||||
|
|
||||||
@ -103,28 +102,6 @@ class DefaultMessageControllerTest {
|
|||||||
verify { store.dispatch(AppAction.MessagingAction.MessageDismissed(message)) }
|
verify { store.dispatch(AppAction.MessagingAction.MessageDismissed(message)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `WHEN calling onMessageDisplayed THEN report to the messageManager`() {
|
|
||||||
val data = MessageData()
|
|
||||||
val message = mockMessage(data)
|
|
||||||
assertNull(Messaging.messageExpired.testGetValue())
|
|
||||||
assertNull(Messaging.messageShown.testGetValue())
|
|
||||||
|
|
||||||
controller.onMessageDisplayed(message)
|
|
||||||
|
|
||||||
assertNotNull(Messaging.messageExpired.testGetValue())
|
|
||||||
val messageExpiredEvent = Messaging.messageExpired.testGetValue()!!
|
|
||||||
assertEquals(1, messageExpiredEvent.size)
|
|
||||||
assertEquals(message.id, messageExpiredEvent.single().extra!!["message_key"])
|
|
||||||
|
|
||||||
assertNotNull(Messaging.messageShown.testGetValue())
|
|
||||||
val event = Messaging.messageShown.testGetValue()!!
|
|
||||||
assertEquals(1, event.size)
|
|
||||||
assertEquals(message.id, event.single().extra!!["message_key"])
|
|
||||||
|
|
||||||
verify { store.dispatch(MessageDisplayed(message)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun mockMessage(data: MessageData = MessageData()) = Message(
|
private fun mockMessage(data: MessageData = MessageData()) = Message(
|
||||||
id = "id",
|
id = "id",
|
||||||
data = data,
|
data = data,
|
||||||
|
@ -28,7 +28,6 @@ import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.ConsumeMe
|
|||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.Evaluate
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.Evaluate
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageClicked
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageClicked
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDismissed
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDismissed
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDisplayed
|
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.Restore
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.Restore
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessageToShow
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessageToShow
|
||||||
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessages
|
import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessages
|
||||||
@ -143,7 +142,7 @@ class MessagingMiddlewareTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `WHEN MessageDisplayed THEN update storage`() = runTestOnMain {
|
fun `GIEN a expiring message WHEN MessageDisplayed THEN update storage`() = runTestOnMain {
|
||||||
val message = Message(
|
val message = Message(
|
||||||
"control-id",
|
"control-id",
|
||||||
mockk(relaxed = true),
|
mockk(relaxed = true),
|
||||||
@ -161,13 +160,11 @@ class MessagingMiddlewareTest {
|
|||||||
every { appState.messaging } returns messagingState
|
every { appState.messaging } returns messagingState
|
||||||
every { middlewareContext.state } returns appState
|
every { middlewareContext.state } returns appState
|
||||||
|
|
||||||
spiedMiddleware.invoke(
|
spiedMiddleware.onMessagedDisplayed(message, middlewareContext)
|
||||||
middlewareContext, {},
|
|
||||||
MessageDisplayed(message)
|
|
||||||
)
|
|
||||||
|
|
||||||
coVerify { messagingStorage.updateMetadata(message.metadata.copy(displayCount = 1)) }
|
coVerify { messagingStorage.updateMetadata(message.metadata.copy(displayCount = 1)) }
|
||||||
verify { middlewareContext.dispatch(UpdateMessages(emptyList())) }
|
verify { middlewareContext.dispatch(UpdateMessages(emptyList())) }
|
||||||
|
verify { spiedMiddleware.sendExpiredMessageTelemetry(message.id) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -340,5 +337,6 @@ class MessagingMiddlewareTest {
|
|||||||
verify { spiedMiddleware.removeMessage(middlewareContext, oldMessage) }
|
verify { spiedMiddleware.removeMessage(middlewareContext, oldMessage) }
|
||||||
verify { middlewareContext.dispatch(UpdateMessages(emptyList())) }
|
verify { middlewareContext.dispatch(UpdateMessages(emptyList())) }
|
||||||
coVerify { messagingStorage.updateMetadata(updatedMessage.metadata) }
|
coVerify { messagingStorage.updateMetadata(updatedMessage.metadata) }
|
||||||
|
verify { spiedMiddleware.sendShownMessageTelemetry(oldMessage.id) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1228,13 +1228,12 @@ class DefaultSessionControlControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `WHEN handleMessageClicked,handleMessageClosed and handleMessageDisplayed are called THEN delegate to messageController`() {
|
fun `WHEN handleMessageClicked and handleMessageClosed are called THEN delegate to messageController`() {
|
||||||
val controller = createController()
|
val controller = createController()
|
||||||
val message = mockk<Message>()
|
val message = mockk<Message>()
|
||||||
|
|
||||||
controller.handleMessageClicked(message)
|
controller.handleMessageClicked(message)
|
||||||
controller.handleMessageClosed(message)
|
controller.handleMessageClosed(message)
|
||||||
controller.handleMessageDisplayed(message)
|
|
||||||
|
|
||||||
verify {
|
verify {
|
||||||
messageController.onMessagePressed(message)
|
messageController.onMessagePressed(message)
|
||||||
@ -1242,9 +1241,6 @@ class DefaultSessionControlControllerTest {
|
|||||||
verify {
|
verify {
|
||||||
messageController.onMessageDismissed(message)
|
messageController.onMessageDismissed(message)
|
||||||
}
|
}
|
||||||
verify {
|
|
||||||
messageController.onMessageDisplayed(message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createController(
|
private fun createController(
|
||||||
|
Loading…
Reference in New Issue
Block a user