Commit 78354bc1 authored by MickeyMoz's avatar MickeyMoz
Browse files

Merge #4081

4081: Bug 1572796 - Improve service-experiments public API docstrings r=travis79 a=travis79

As part of Doc Days of Summer 2019 2.0, improves the docstrings of the public API classes and especially the exposed methods and properties.

### Pull Request checklist
<!-- Before submitting the PR, please address each item -->
- [ ] **Quality**: This PR builds and passes detekt/ktlint checks (A pre-push hook is recommended)
- [ ] **Tests**: This PR includes thorough tests or an explanation of why it does not
- [ ] **Changelog**: This PR includes [a changelog entry](https://github.com/mozilla-mobile/android-components/blob/master/docs/changelog.md) or does not need one
- [ ] **Accessibility**: The code in this PR follows [accessibility best practices](https://github.com/mozilla-mobile/shared-docs/blob/master/android/accessibility_guide.md) or does not include any user facing features

### After merge
- [ ] **Milestone**: Make sure issues closed by this pull request are added to the [milestone](https://github.com/mozilla-mobile/android-components/milestones) of the version currently in development.
- [ ] **Breaking Changes**: If this is a breaking change, please push a draft PR on [Reference Browser](https://github.com/mozilla-mobile/reference-browser

) to address the breaking issues.

Co-authored-by: default avatarTravis Long <tlong@mozilla.com>
parents d1796478 cec85e11
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -11,6 +11,9 @@ import mozilla.components.lib.fetch.httpurlconnection.HttpURLConnectionClient
 * The Configuration class describes how to configure Experiments.
 *
 * @property httpClient The HTTP client implementation to use for uploading pings.
 * @property kintoEndpoint the endpoint to fetch experiments from, must be one of:
 * [ExperimentsUpdater.KINTO_ENDPOINT_DEV], [ExperimentsUpdater.KINTO_ENDPOINT_STAGING], or
 * [ExperimentsUpdater.KINTO_ENDPOINT_PROD]
 */
data class Configuration(
    val httpClient: Lazy<Client> = lazy { HttpURLConnectionClient() },
+40 −5
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@ import androidx.annotation.VisibleForTesting
import java.io.File

/**
 * Entry point of the library.
 * This is the main experiments API, which is exposed through the global [Experiments] object.
 */
@Suppress("TooManyFunctions")
open class ExperimentsInternalAPI internal constructor() {
@@ -51,6 +51,8 @@ open class ExperimentsInternalAPI internal constructor() {
     * as shared preferences.  As we cannot enforce through the compiler that the context pass to
     * the initialize function is a applicationContext, there could potentially be a memory leak
     * if the initializing application doesn't comply.
     *
     * @param configuration [Configuration] containing information about the experiments endpoint.
     */
    fun initialize(
        applicationContext: Context,
@@ -91,11 +93,17 @@ open class ExperimentsInternalAPI internal constructor() {
        updater.initialize(configuration)
    }

    /**
     * Returns the [ExperimentsUpdater] for the given [Context].
     */
    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    internal fun getExperimentsUpdater(context: Context): ExperimentsUpdater {
        return ExperimentsUpdater(context, this)
    }

    /**
     * Returns the [FlatFileExperimentStorage] for the given [Context]
     */
    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    internal fun getExperimentsStorage(context: Context): FlatFileExperimentStorage {
        return FlatFileExperimentStorage(
@@ -122,8 +130,11 @@ open class ExperimentsInternalAPI internal constructor() {
    }

    /**
     * Requests new experiments from the server and
     * saves them to local storage
     * Handles the required tasks when new experiments have been fetched from the server.
     *
     * This includes:
     * - Storing the experiments that have been freshly retrieved from the server.
     * - Updating the active experiment
     */
    @Synchronized
    internal fun onExperimentsUpdated(serverState: ExperimentsSnapshot) {
@@ -132,7 +143,6 @@ open class ExperimentsInternalAPI internal constructor() {
        experimentsResult = serverState
        storage.save(serverState)

        // TODO
        // Choices here:
        // 1) There currently is an active experiment.
        // 1a) Should it stop? E.g. because it was deleted. If so, continue with 2.
@@ -161,6 +171,10 @@ open class ExperimentsInternalAPI internal constructor() {
        }
    }

    /**
     * Evaluates the current [experimentsResult] to determine enrollment in any experiments,
     * including reporting enrollment in an experiment in Glean.
     */
    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    internal fun findAndStartActiveExperiment() {
        assert(activeExperiment == null) { "Should not have an active experiment" }
@@ -173,6 +187,10 @@ open class ExperimentsInternalAPI internal constructor() {
        }
    }

    /**
     * Performs the necessary tasks to stop the active experiment, including reporting this to
     * telemetry via Glean.
     */
    private fun stopActiveExperiment() {
        assert(activeExperiment != null) { "Should have an active experiment" }

@@ -184,6 +202,9 @@ open class ExperimentsInternalAPI internal constructor() {
        activeExperiment = null
    }

    /**
     * This function finds and returns any active experiments from persisted storage.
     */
    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    internal fun loadActiveExperiment(
        context: Context,
@@ -244,6 +265,10 @@ open class ExperimentsInternalAPI internal constructor() {
        return evaluator.getExperiment(ExperimentDescriptor(experimentId), experimentsResult.experiments)
    }

    /**
     * Helper function to perform the tasks necessary to override the experiment once it has been
     * set using [setOverride] or [setOverrideNow].
     */
    private fun overrideActiveExperiment() {
        evaluator.findActiveExperiment(context, experimentsResult.experiments)?.let {
            logger.info("""Setting override experiment - id="${it.experiment.id}", branch="${it.branch}"""")
@@ -355,11 +380,21 @@ open class ExperimentsInternalAPI internal constructor() {
    companion object {
        private const val LOG_TAG = "experiments"
        private const val EXPERIMENTS_DATA_DIR = "experiments-service"

        private const val EXPERIMENTS_JSON_FILENAME = "experiments.json"
    }
}

/**
 * The main Experiments object.
 *
 * This is a global object that must be initialized by the application by calling the [initialize]
 * function before the experiments library can fetch updates from the server or be used to determine
 * experiment enrollment.
 *
 * ```
 * Experiments.initialize(applicationContext)
 * ```
 */
@SuppressLint("StaticFieldLeak")
object Experiments : ExperimentsInternalAPI() {
    internal const val SCHEMA_VERSION = 1
+35 −3
Original line number Diff line number Diff line
@@ -16,6 +16,20 @@ import mozilla.components.service.experiments.Experiments
import mozilla.components.service.experiments.ExperimentsUpdater
import mozilla.components.support.base.log.logger.Logger

/**
 * Debugging activity exported by service-experiments to allow easier debugging. This accepts
 * commands that can force the library to do the following:
 * - Fetch or update experiments
 * - Change the Kinto endpoint to the `dev`, `staging`, or `prod` endpoint
 * - Override the active experiment to a branch specified by the `branch` command
 * - Clear any overridden experiment
 *
 * See here for more information on using the ExperimentsDebugActivity:
 * https://github.com/mozilla-mobile/android-components/tree/master/components/service/experiments#experimentsdebugactivity-usage
 *
 * See the adb developer docs for more info:
 * https://developer.android.com/studio/command-line/adb#am
 */
class ExperimentsDebugActivity : Activity() {
    private val logger = Logger(LOG_TAG)

@@ -28,16 +42,34 @@ class ExperimentsDebugActivity : Activity() {
        private const val LOG_TAG = "ExperimentsDebugActivity"

        // This is a list of the currently accepted commands
        /**
         * Fetch experiments from the server and update the active experiment if necessary.
         */
        const val UPDATE_EXPERIMENTS_EXTRA_KEY = "updateExperiments"
        /**
         * Sets the Kinto endpoint to the supplied endpoint.
         * Must be one of: `dev`, `staging`, or `prod`.
         */
        const val SET_KINTO_INSTANCE_EXTRA_KEY = "setKintoInstance"

        // Both of these need to be supplied in order to select both the branch and the
        // ExperimentDescriptor.id of the experiment to override.
        /**
         * Overrides the current experiment and set the active experiment to the given `branch`.
         * This command requires two parameters to be passed, `overrideExperiment` and `branch` in
         * order for it to work.
         */
        const val OVERRIDE_EXPERIMENT_EXTRA_KEY = "overrideExperiment"
        /**
         * Used only with [OVERRIDE_EXPERIMENT_EXTRA_KEY].
         */
        const val OVERRIDE_BRANCH_EXTRA_KEY = "branch"
        /**
         * Clears any existing overrides.
         */
        const val OVERRIDE_CLEAR_ALL_EXTRA_KEY = "clearAllOverrides"
    }

    /**
     * On creation of the debug activity, process the command switches
     */
    @Suppress("ComplexMethod")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)