2019-01-24 22:07:52 +01:00
|
|
|
/* 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/. */
|
|
|
|
|
2019-01-23 22:39:53 +01:00
|
|
|
package org.mozilla.fenix
|
|
|
|
|
2019-02-13 16:08:35 +01:00
|
|
|
import android.annotation.SuppressLint
|
2019-02-26 17:24:14 +01:00
|
|
|
import android.app.ActivityManager
|
2019-01-23 22:39:53 +01:00
|
|
|
import android.app.Application
|
2019-01-29 20:20:29 +01:00
|
|
|
import android.content.Context
|
2019-02-26 17:24:14 +01:00
|
|
|
import android.os.Process
|
2019-01-29 20:20:29 +01:00
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
|
import kotlinx.coroutines.GlobalScope
|
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
import mozilla.components.service.fretboard.Fretboard
|
|
|
|
import mozilla.components.service.fretboard.source.kinto.KintoExperimentSource
|
|
|
|
import mozilla.components.service.fretboard.storage.flatfile.FlatFileExperimentStorage
|
2019-01-31 17:27:36 +01:00
|
|
|
import mozilla.components.service.glean.Glean
|
2019-01-29 20:20:29 +01:00
|
|
|
import mozilla.components.support.base.log.Log
|
|
|
|
import mozilla.components.support.base.log.logger.Logger
|
|
|
|
import mozilla.components.support.base.log.sink.AndroidLogSink
|
2019-01-23 22:39:53 +01:00
|
|
|
import org.mozilla.fenix.components.Components
|
2019-01-29 20:20:29 +01:00
|
|
|
import java.io.File
|
2019-01-23 22:39:53 +01:00
|
|
|
|
2019-02-13 16:08:35 +01:00
|
|
|
@SuppressLint("Registered")
|
|
|
|
open class FenixApplication : Application() {
|
2019-01-29 20:20:29 +01:00
|
|
|
lateinit var fretboard: Fretboard
|
|
|
|
|
2019-01-23 22:39:53 +01:00
|
|
|
val components by lazy { Components(this) }
|
2019-01-29 17:42:10 +01:00
|
|
|
|
|
|
|
override fun onCreate() {
|
|
|
|
super.onCreate()
|
2019-02-26 17:24:14 +01:00
|
|
|
|
2019-01-29 20:20:29 +01:00
|
|
|
Log.addSink(AndroidLogSink())
|
2019-02-26 17:24:14 +01:00
|
|
|
setupCrashReporting()
|
2019-01-29 17:42:10 +01:00
|
|
|
|
2019-02-26 17:24:14 +01:00
|
|
|
if (!isMainProcess(this)) {
|
|
|
|
// If this is not the main process then do not continue with the initialization here. Everything that
|
|
|
|
// follows only needs to be done in our app's main process and should not be done in other processes like
|
|
|
|
// a GeckoView child process or the crash handling process. Most importantly we never want to end up in a
|
|
|
|
// situation where we create a GeckoRuntime from the Gecko child process (
|
|
|
|
return
|
2019-02-13 16:08:35 +01:00
|
|
|
}
|
2019-02-26 17:24:14 +01:00
|
|
|
|
2019-02-13 16:08:35 +01:00
|
|
|
setupLeakCanary()
|
2019-01-31 17:27:36 +01:00
|
|
|
setupGlean(this)
|
2019-01-29 20:20:29 +01:00
|
|
|
loadExperiments()
|
|
|
|
}
|
|
|
|
|
2019-02-13 16:08:35 +01:00
|
|
|
protected open fun setupLeakCanary() {
|
|
|
|
// no-op, LeakCanary is disabled by default
|
|
|
|
}
|
|
|
|
|
|
|
|
open fun toggleLeakCanary(newValue: Boolean) {
|
|
|
|
// no-op, LeakCanary is disabled by default
|
|
|
|
}
|
|
|
|
|
2019-01-31 17:27:36 +01:00
|
|
|
private fun setupGlean(context: Context) {
|
|
|
|
Glean.initialize(context)
|
2019-02-08 11:43:32 +01:00
|
|
|
Glean.setUploadEnabled(BuildConfig.TELEMETRY)
|
2019-01-31 17:27:36 +01:00
|
|
|
}
|
|
|
|
|
2019-01-29 20:20:29 +01:00
|
|
|
private fun loadExperiments() {
|
|
|
|
val experimentsFile = File(filesDir, EXPERIMENTS_JSON_FILENAME)
|
|
|
|
val experimentSource = KintoExperimentSource(
|
2019-02-26 17:24:14 +01:00
|
|
|
EXPERIMENTS_BASE_URL,
|
|
|
|
EXPERIMENTS_BUCKET_NAME,
|
|
|
|
EXPERIMENTS_COLLECTION_NAME,
|
|
|
|
components.core.client
|
2019-01-29 20:20:29 +01:00
|
|
|
)
|
2019-01-31 20:16:04 +01:00
|
|
|
// TODO add ValueProvider to keep clientID in sync with Glean when ready
|
|
|
|
fretboard = Fretboard(experimentSource, FlatFileExperimentStorage(experimentsFile))
|
2019-01-29 20:20:29 +01:00
|
|
|
fretboard.loadExperiments()
|
|
|
|
Logger.debug("Bucket is ${fretboard.getUserBucket(this@FenixApplication)}")
|
|
|
|
Logger.debug("Experiments active: ${fretboard.getExperimentsMap(this@FenixApplication)}")
|
|
|
|
GlobalScope.launch(Dispatchers.IO) {
|
|
|
|
fretboard.updateExperiments()
|
|
|
|
}
|
2019-01-29 17:42:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun setupCrashReporting() {
|
|
|
|
@Suppress("ConstantConditionIf")
|
|
|
|
if (!BuildConfig.CRASH_REPORTING || BuildConfig.BUILD_TYPE != "release") {
|
|
|
|
// Only enable crash reporting if this is a release build and if crash reporting was explicitly enabled
|
|
|
|
// via a Gradle command line flag.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
components
|
|
|
|
.analytics
|
|
|
|
.crashReporter
|
|
|
|
.install(this)
|
|
|
|
}
|
2019-01-23 22:39:53 +01:00
|
|
|
}
|
2019-02-26 17:24:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Are we running in the main process?
|
|
|
|
*
|
|
|
|
* Let's move this code to Android Components:
|
|
|
|
* https://github.com/mozilla-mobile/android-components/issues/2207
|
|
|
|
*/
|
|
|
|
private fun isMainProcess(context: Context): Boolean {
|
|
|
|
val pid = Process.myPid()
|
|
|
|
|
|
|
|
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE)
|
|
|
|
as ActivityManager
|
|
|
|
|
|
|
|
activityManager.runningAppProcesses?.forEach { processInfo ->
|
|
|
|
if (processInfo.pid == pid) {
|
|
|
|
return processInfo.processName == context.packageName
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|