1
0
Fork 0
fenix/app/src/main/java/org/mozilla/fenix/components/metrics/LeanplumMetricsService.kt

164 lines
6.5 KiB
Kotlin

/* 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.components.metrics
import android.app.Application
import android.util.Log
import com.leanplum.Leanplum
import com.leanplum.LeanplumActivityHelper
import com.leanplum.annotations.Parser
import com.leanplum.internal.LeanplumInternal
import mozilla.components.support.locale.LocaleManager
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.ext.settings
import java.util.Locale
import java.util.UUID.randomUUID
private val Event.name: String?
get() = when (this) {
is Event.AddBookmark -> "E_Add_Bookmark"
is Event.RemoveBookmark -> "E_Remove_Bookmark"
is Event.OpenedBookmark -> "E_Opened_Bookmark"
is Event.OpenedApp -> "E_Opened_App"
is Event.OpenedAppFirstRun -> "E_Opened_App_FirstRun"
is Event.InteractWithSearchURLArea -> "E_Interact_With_Search_URL_Area"
is Event.CollectionSaved -> "E_Collection_Created"
is Event.CollectionTabRestored -> "E_Collection_Tab_Opened"
is Event.SyncAuthSignIn -> "E_Sign_In_FxA"
is Event.SyncAuthSignOut -> "E_Sign_Out_FxA"
is Event.ClearedPrivateData -> "E_Cleared_Private_Data"
is Event.DismissedOnboarding -> "E_Dismissed_Onboarding"
// Do not track other events in Leanplum
else -> ""
}
class LeanplumMetricsService(private val application: Application) : MetricsService {
data class Token(val id: String, val token: String) {
enum class Type { Development, Production, Invalid }
val type by lazy {
when {
token.take(ProdPrefix.length) == ProdPrefix -> Type.Production
token.take(DevPrefix.length) == DevPrefix -> Type.Development
else -> Type.Invalid
}
}
companion object {
private const val ProdPrefix = "prod"
private const val DevPrefix = "dev"
}
}
private val token = Token(LeanplumId, LeanplumToken)
override fun start() {
if (!application.settings().isMarketingTelemetryEnabled) return
val applicationSetLocale = LocaleManager.getCurrentLocale(application)
val currentLocale = when (applicationSetLocale != null) {
true -> applicationSetLocale.isO3Language
false -> Locale.getDefault().isO3Language
}
if (!isLeanplumEnabled(currentLocale)) {
Log.i(LOGTAG, "Leanplum is not available for this locale: $currentLocale")
return
}
when (token.type) {
Token.Type.Production -> Leanplum.setAppIdForProductionMode(token.id, token.token)
Token.Type.Development -> Leanplum.setAppIdForDevelopmentMode(token.id, token.token)
Token.Type.Invalid -> {
Log.i(LOGTAG, "Invalid or missing Leanplum token")
return
}
}
Leanplum.setIsTestModeEnabled(false)
Leanplum.setApplicationContext(application)
Leanplum.setDeviceId(randomUUID().toString())
Parser.parseVariables(application)
LeanplumActivityHelper.enableLifecycleCallbacks(application)
val installedApps = MozillaProductDetector.getInstalledMozillaProducts(application)
Leanplum.start(application, hashMapOf(
"default_browser" to MozillaProductDetector.getMozillaBrowserDefault(application).orEmpty(),
"fennec_installed" to installedApps.contains(MozillaProductDetector.MozillaProducts.FIREFOX.productName),
"focus_installed" to installedApps.contains(MozillaProductDetector.MozillaProducts.FOCUS.productName),
"klar_installed" to installedApps.contains(MozillaProductDetector.MozillaProducts.KLAR.productName),
"fxa_signed_in" to application.settings().fxaSignedIn,
"fxa_has_synced_items" to application.settings().fxaHasSyncedItems,
"search_widget_installed" to application.settings().searchWidgetInstalled
))
}
override fun stop() {
if (application.settings().isMarketingTelemetryEnabled) return
// As written in LeanPlum SDK documentation, "This prevents Leanplum from communicating with the server."
// as this "isTestMode" flag is checked before LeanPlum SDK does anything.
// Also has the benefit effect of blocking the display of already downloaded messages.
// The reverse of this - setIsTestModeEnabled(false) must be called before trying to init
// LP in the same session.
Leanplum.setIsTestModeEnabled(true)
// This is just to allow restarting LP and it's functionality in the same app session
// as LP stores it's state internally and check against it
LeanplumInternal.setCalledStart(false)
LeanplumInternal.setHasStarted(false)
}
override fun track(event: Event) {
val leanplumExtras = event.extras
?.map { (key, value) -> key.toString() to value }
?.toMap()
event.name?.also {
Leanplum.track(it, leanplumExtras)
}
}
override fun shouldTrack(event: Event): Boolean {
return application.settings().isTelemetryEnabled &&
token.type != Token.Type.Invalid && !event.name.isNullOrEmpty()
}
private fun isLeanplumEnabled(locale: String): Boolean {
return LEANPLUM_ENABLED_LOCALES.contains(locale)
}
companion object {
private const val LOGTAG = "LeanplumMetricsService"
private val LeanplumId: String
// Debug builds have a null (nullable) LEANPLUM_ID
get() = BuildConfig.LEANPLUM_ID.orEmpty()
private val LeanplumToken: String
// Debug builds have a null (nullable) LEANPLUM_TOKEN
get() = BuildConfig.LEANPLUM_TOKEN.orEmpty()
// Leanplum needs to be enabled for the following locales.
// Irrespective of the actual device location.
private val LEANPLUM_ENABLED_LOCALES = listOf(
"eng", // English
"zho", // Chinese
"deu", // German
"fra", // French
"ita", // Italian
"ind", // Indonesian
"por", // Portuguese
"spa", // Spanish; Castilian
"pol", // Polish
"rus", // Russian
"hin", // Hindi
"per", // Persian
"fas", // Persian
"ara", // Arabic
"jpn" // Japanese
)
}
}