diff --git a/.buildconfig.yml b/.buildconfig.yml index 312d3f143f1..ac7b1daa7e5 100644 --- a/.buildconfig.yml +++ b/.buildconfig.yml @@ -1,4 +1,4 @@ -componentsVersion: 8.0.0 +componentsVersion: 9.0.0 projects: concept-awesomebar: path: components/concept/awesomebar diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index dcbe9729c43..e96e88170cb 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,4 +1,6 @@ +--- + ### Pull Request checklist @@ -9,4 +11,4 @@ ### 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. \ No newline at end of file +- [ ] **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. diff --git a/.taskcluster.yml b/.taskcluster.yml index d9be145d62d..5c0f33ab3cc 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -9,7 +9,11 @@ tasks: $let: decision_task_id: {$eval: as_slugid("decision_task")} expires_in: {$fromNow: '1 year'} - user: ${event.sender.login} + user: + # GitHub adds "[bot]" to bot usernames and that doesn't validate as email. + $if: 'event.sender.login == "bors[bot]"' + then: bors + else: ${event.sender.login} # We define the following variable at the very top, because they are used in the # default definition @@ -153,7 +157,7 @@ tasks: metadata: name: 'Android Components - Decision task (Pull Request #${pull_request_number})' description: 'Building and testing Android components - triggered by [#${pull_request_number}](${pull_request_url})' - - $if: 'tasks_for == "github-push" && head_branch[:10] != "refs/tags/"' + - $if: 'tasks_for == "github-push" && head_branch[:10] != "refs/tags/" && head_branch != "staging.tmp" && head_branch != "trying.tmp"' then: $mergeDeep: - {$eval: 'default_task_definition'} diff --git a/README.md b/README.md index 830fd1edb44..fce42ee4474 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Task Status](https://github.taskcluster.net/v1/repository/mozilla-mobile/android-components/master/badge.svg)](https://github.taskcluster.net/v1/repository/mozilla-mobile/android-components/master/latest) [![codecov](https://codecov.io/gh/mozilla-mobile/android-components/branch/master/graph/badge.svg)](https://codecov.io/gh/mozilla-mobile/android-components) +[![Bors enabled](https://bors.tech/images/badge_small.svg)](https://app.bors.tech/repositories/19637) _A collection of Android libraries to build browsers or browser-like applications._ diff --git a/bors.toml b/bors.toml new file mode 100644 index 00000000000..1bf908949fa --- /dev/null +++ b/bors.toml @@ -0,0 +1,13 @@ +status = [ + "Taskcluster (push)" +] +block_labels = [ + "blocked", + "work in progress" +] +[committer] +name = "MickeyMoz" +email = "sebastian@mozilla.com" +required_approvals = 1 +delete_merged_branches = true +cut_body_after = "---" diff --git a/buildSrc/src/main/java/Gecko.kt b/buildSrc/src/main/java/Gecko.kt index 94d05591e1d..536952e9d13 100644 --- a/buildSrc/src/main/java/Gecko.kt +++ b/buildSrc/src/main/java/Gecko.kt @@ -6,12 +6,12 @@ internal object GeckoVersions { /** * GeckoView Nightly Version. */ - const val nightly_version = "70.0.20190807095705" + const val nightly_version = "70.0.20190809095611" /** * GeckoView Beta Version. */ - const val beta_version = "69.0.20190808090046" + const val beta_version = "69.0.20190812090043" /** * GeckoView Release Version. diff --git a/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt b/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt index 68e77524d5d..2c9e77415d8 100644 --- a/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt +++ b/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt @@ -26,6 +26,9 @@ internal class GeckoMedia( ) : Media() { override val controller: Controller = GeckoMediaController(mediaElement) + override var metadata: Metadata = Metadata() + internal set + init { mediaElement.delegate = MediaDelegate(this) } @@ -44,7 +47,7 @@ internal class GeckoMedia( } private class MediaDelegate( - private val media: Media + private val media: GeckoMedia ) : MediaElement.Delegate { override fun onPlaybackStateChange(mediaElement: MediaElement, mediaState: Int) { @@ -63,8 +66,11 @@ private class MediaDelegate( } } + override fun onMetadataChange(mediaElement: MediaElement, metaData: MediaElement.Metadata) { + media.metadata = Media.Metadata(metaData.duration) + } + override fun onReadyStateChange(mediaElement: MediaElement, readyState: Int) = Unit - override fun onMetadataChange(mediaElement: MediaElement, metaData: MediaElement.Metadata) = Unit override fun onLoadProgress(mediaElement: MediaElement, progressInfo: MediaElement.LoadProgressInfo) = Unit override fun onVolumeChange(mediaElement: MediaElement, volume: Double, muted: Boolean) = Unit override fun onTimeChange(mediaElement: MediaElement, time: Double) = Unit diff --git a/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt b/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt index 58620bf5186..34d3111f9df 100644 --- a/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt +++ b/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt @@ -7,6 +7,7 @@ package mozilla.components.browser.engine.gecko.media import mozilla.components.concept.engine.media.Media import mozilla.components.support.test.argumentCaptor import mozilla.components.support.test.mock +import mozilla.components.test.ReflectionUtils import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test @@ -84,4 +85,38 @@ class GeckoMediaTest { delegate.onPlaybackStateChange(mediaElement, MediaElement.MEDIA_STATE_PLAYING) verify(observer).onPlaybackStateChanged(media, Media.PlaybackState.PLAYING) } + + @Test + fun `GeckoMedia exposes Metadata`() { + val mediaElement: MediaElement = mock() + + val media = GeckoMedia(mediaElement) + + val captor = argumentCaptor() + verify(mediaElement).delegate = captor.capture() + + assertEquals(-1.0, media.metadata.duration, 0.0001) + + val delegate = captor.value + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = 5.0)) + assertEquals(5.0, media.metadata.duration, 0.0001) + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = 572.0)) + assertEquals(572.0, media.metadata.duration, 0.0001) + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = 0.0)) + assertEquals(0.0, media.metadata.duration, 0.0001) + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = -1.0)) + assertEquals(-1.0, media.metadata.duration, 0.0001) + } +} + +private class MockedGeckoMetadata( + duration: Double +) : MediaElement.Metadata() { + init { + ReflectionUtils.setField(this, "duration", duration) + } } diff --git a/components/browser/engine-gecko-nightly/README.md b/components/browser/engine-gecko-nightly/README.md index 882a22aa964..72ff914043d 100644 --- a/components/browser/engine-gecko-nightly/README.md +++ b/components/browser/engine-gecko-nightly/README.md @@ -12,6 +12,25 @@ Use Gradle to download the library from [maven.mozilla.org](https://maven.mozill implementation "org.mozilla.components:browser-engine-gecko-nightly:{latest-version}" ``` +### Integration with the Glean SDK + +The [Glean SDK](../../../components/service/glean/README.md) can be used to collect [Gecko Telemetry](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/index.html). +Applications using both this component and the Glean SDK should setup the Gecko Telemetry delegate +as shown below: + +```Kotlin + val builder = GeckoRuntimeSettings.Builder() + val runtimeSettings = builder + .telemetryDelegate(GeckoGleanAdapter()) // Sets up the delegate! + .build() + // Create the Gecko runtime. + GeckoRuntime.create(context, runtimeSettings) +``` + +#### Adding new metrics + +New Gecko metrics can be added as described [in the Firefox Telemetry docs](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/start/adding-a-new-probe.html). + ## License This Source Code Form is subject to the terms of the Mozilla Public diff --git a/components/browser/engine-gecko-nightly/metrics.yaml b/components/browser/engine-gecko-nightly/metrics.yaml new file mode 100644 index 00000000000..71bd78cb87a --- /dev/null +++ b/components/browser/engine-gecko-nightly/metrics.yaml @@ -0,0 +1,29 @@ +# 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/. + +# IMPORTANT NOTE: this file is here only as a safety measure, to make +# sure the correct code is generated even though the GeckoView AAR file +# reports an empty metrics.yaml file. The metric in this file is currently +# disabled and not supposed to collect any data. + +$schema: moz://mozilla.org/schemas/glean/metrics/1-0-0 + +test.glean.geckoview: + streaming: + type: timing_distribution + gecko_datapoint: TELEMETRY_TEST_STREAMING + disabled: true + description: | + A test-only, disabled metric. This is required to guarantee + that a `GleanGeckoHistogramMapping` is always generated, even + though the GeckoView AAR exports no metric. Please note that + the data-review field below contains no review, since this + metric is disabled and not allowed to collect any data. + bugs: + - 1566374 + data_reviews: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1566374 + notification_emails: + - glean-team@mozilla.com + expires: never diff --git a/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/glean/GeckoAdapter.kt b/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/glean/GeckoAdapter.kt new file mode 100644 index 00000000000..8b852ff92a3 --- /dev/null +++ b/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/glean/GeckoAdapter.kt @@ -0,0 +1,27 @@ +/* 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 mozilla.components.browser.engine.gecko.glean + +import mozilla.components.browser.engine.gecko.GleanMetrics.GleanGeckoHistogramMapping +import org.mozilla.geckoview.RuntimeTelemetry + +/** + * This implements a [RuntimeTelemetry.Delegate] that dispatches Gecko runtime + * telemetry to the Glean SDK. + * + * Metrics defined in the `metrics.yaml` file in Gecko's mozilla-central repository + * will be automatically dispatched to the Glean SDK and sent through the requested + * pings. + * + * This can be used, in products collecting data through the Glean SDK, by + * providing an instance to `GeckoRuntimeSettings.Builder().telemetryDelegate`. + */ +class GeckoAdapter : RuntimeTelemetry.Delegate { + override fun onTelemetryReceived(metric: RuntimeTelemetry.Metric) { + // Note that the `GleanGeckoHistogramMapping` is automatically generated at + // build time by the Glean SDK parsers. + GleanGeckoHistogramMapping[metric.name]?.accumulateSamples(metric.values) + } +} diff --git a/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt b/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt index 68e77524d5d..2c9e77415d8 100644 --- a/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt +++ b/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt @@ -26,6 +26,9 @@ internal class GeckoMedia( ) : Media() { override val controller: Controller = GeckoMediaController(mediaElement) + override var metadata: Metadata = Metadata() + internal set + init { mediaElement.delegate = MediaDelegate(this) } @@ -44,7 +47,7 @@ internal class GeckoMedia( } private class MediaDelegate( - private val media: Media + private val media: GeckoMedia ) : MediaElement.Delegate { override fun onPlaybackStateChange(mediaElement: MediaElement, mediaState: Int) { @@ -63,8 +66,11 @@ private class MediaDelegate( } } + override fun onMetadataChange(mediaElement: MediaElement, metaData: MediaElement.Metadata) { + media.metadata = Media.Metadata(metaData.duration) + } + override fun onReadyStateChange(mediaElement: MediaElement, readyState: Int) = Unit - override fun onMetadataChange(mediaElement: MediaElement, metaData: MediaElement.Metadata) = Unit override fun onLoadProgress(mediaElement: MediaElement, progressInfo: MediaElement.LoadProgressInfo) = Unit override fun onVolumeChange(mediaElement: MediaElement, volume: Double, muted: Boolean) = Unit override fun onTimeChange(mediaElement: MediaElement, time: Double) = Unit diff --git a/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt b/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt index 405d8d87fa5..558568444a6 100644 --- a/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt +++ b/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt @@ -12,46 +12,21 @@ import androidx.annotation.VisibleForTesting import mozilla.components.browser.engine.gecko.GeckoEngineSession import mozilla.components.concept.engine.prompt.Choice import mozilla.components.concept.engine.prompt.PromptRequest -import mozilla.components.concept.engine.prompt.PromptRequest.Alert -import mozilla.components.concept.engine.prompt.PromptRequest.Authentication.Level -import mozilla.components.concept.engine.prompt.PromptRequest.Authentication.Method import mozilla.components.concept.engine.prompt.PromptRequest.MenuChoice import mozilla.components.concept.engine.prompt.PromptRequest.MultipleChoice import mozilla.components.concept.engine.prompt.PromptRequest.SingleChoice -import mozilla.components.concept.engine.prompt.PromptRequest.TimeSelection import mozilla.components.support.base.log.logger.Logger import mozilla.components.support.ktx.kotlin.toDate import org.mozilla.geckoview.AllowOrDeny import org.mozilla.geckoview.GeckoResult import org.mozilla.geckoview.GeckoSession -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AlertCallback -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthCallback -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_FLAG_CROSS_ORIGIN_SUB_RESOURCE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_FLAG_HOST -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_FLAG_ONLY_PASSWORD -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_FLAG_PREVIOUS_FAILED -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_LEVEL_NONE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_LEVEL_PW_ENCRYPTED -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_LEVEL_SECURE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.BUTTON_TYPE_NEGATIVE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.BUTTON_TYPE_NEUTRAL -import org.mozilla.geckoview.GeckoSession.PromptDelegate.BUTTON_TYPE_POSITIVE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.ButtonCallback -import org.mozilla.geckoview.GeckoSession.PromptDelegate.CAPTURE_TYPE_ANY -import org.mozilla.geckoview.GeckoSession.PromptDelegate.CAPTURE_TYPE_ENVIRONMENT -import org.mozilla.geckoview.GeckoSession.PromptDelegate.CAPTURE_TYPE_USER -import org.mozilla.geckoview.GeckoSession.PromptDelegate.Choice.CHOICE_TYPE_MENU -import org.mozilla.geckoview.GeckoSession.PromptDelegate.Choice.CHOICE_TYPE_MULTIPLE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.Choice.CHOICE_TYPE_SINGLE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.ChoiceCallback -import org.mozilla.geckoview.GeckoSession.PromptDelegate.DATETIME_TYPE_DATE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.DATETIME_TYPE_DATETIME_LOCAL -import org.mozilla.geckoview.GeckoSession.PromptDelegate.DATETIME_TYPE_MONTH -import org.mozilla.geckoview.GeckoSession.PromptDelegate.DATETIME_TYPE_TIME -import org.mozilla.geckoview.GeckoSession.PromptDelegate.DATETIME_TYPE_WEEK -import org.mozilla.geckoview.GeckoSession.PromptDelegate.FileCallback -import org.mozilla.geckoview.GeckoSession.PromptDelegate.TextCallback +import org.mozilla.geckoview.GeckoSession.PromptDelegate +import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.DATE +import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.DATETIME_LOCAL +import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.MONTH +import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.TIME +import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.WEEK +import org.mozilla.geckoview.GeckoSession.PromptDelegate.PromptResponse import java.io.FileOutputStream import java.io.IOException import java.security.InvalidParameterException @@ -59,102 +34,118 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale -typealias GeckoChoice = GeckoSession.PromptDelegate.Choice +typealias GeckoAuthOptions = PromptDelegate.AuthPrompt.AuthOptions +typealias GeckoChoice = PromptDelegate.ChoicePrompt.Choice +typealias GECKO_AUTH_FLAGS = PromptDelegate.AuthPrompt.AuthOptions.Flags +typealias GECKO_AUTH_LEVEL = PromptDelegate.AuthPrompt.AuthOptions.Level +typealias GECKO_PROMPT_FILE_TYPE = PromptDelegate.FilePrompt.Type +typealias GECKO_PROMPT_CHOICE_TYPE = PromptDelegate.ChoicePrompt.Type +typealias GECKO_PROMPT_FILE_CAPTURE = PromptDelegate.FilePrompt.Capture +typealias AC_AUTH_LEVEL = PromptRequest.Authentication.Level +typealias AC_AUTH_METHOD = PromptRequest.Authentication.Method +typealias AC_FILE_FACING_MODE = PromptRequest.File.FacingMode /** * Gecko-based PromptDelegate implementation. */ @Suppress("TooManyFunctions") internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSession) : - GeckoSession.PromptDelegate { + PromptDelegate { override fun onChoicePrompt( session: GeckoSession, - title: String?, - msg: String?, - type: Int, - geckoChoices: Array, - callback: ChoiceCallback - ) { - val choices = convertToChoices(geckoChoices) + geckoPrompt: PromptDelegate.ChoicePrompt + ): GeckoResult? { + val geckoResult = GeckoResult() + val choices = convertToChoices(geckoPrompt.choices) val onConfirmSingleChoice: (Choice) -> Unit = { selectedChoice -> - callback.confirm(selectedChoice.id) + geckoResult.complete(geckoPrompt.confirm(selectedChoice.id)) } val onConfirmMultipleSelection: (Array) -> Unit = { selectedChoices -> val ids = selectedChoices.toIdsArray() - callback.confirm(ids) + geckoResult.complete(geckoPrompt.confirm(ids)) } - val promptRequest = when (type) { - CHOICE_TYPE_SINGLE -> SingleChoice(choices, onConfirmSingleChoice) - CHOICE_TYPE_MENU -> MenuChoice(choices, onConfirmSingleChoice) - CHOICE_TYPE_MULTIPLE -> MultipleChoice(choices, onConfirmMultipleSelection) - else -> throw InvalidParameterException("$type is not a valid Gecko @Choice.ChoiceType") + val promptRequest = when (geckoPrompt.type) { + GECKO_PROMPT_CHOICE_TYPE.SINGLE -> SingleChoice( + choices, + onConfirmSingleChoice + ) + GECKO_PROMPT_CHOICE_TYPE.MENU -> MenuChoice( + choices, + onConfirmSingleChoice + ) + GECKO_PROMPT_CHOICE_TYPE.MULTIPLE -> MultipleChoice( + choices, + onConfirmMultipleSelection + ) + else -> throw InvalidParameterException("${geckoPrompt.type} is not a valid Gecko @Choice.ChoiceType") } geckoEngineSession.notifyObservers { onPromptRequest(promptRequest) } + + return geckoResult } - override fun onAlert( + override fun onAlertPrompt( session: GeckoSession, - title: String?, - message: String?, - callback: AlertCallback - ) { - - val hasShownManyDialogs = callback.hasCheckbox() - val onDismiss: () -> Unit = { - callback.dismiss() - } + prompt: PromptDelegate.AlertPrompt + ): GeckoResult { + val geckoResult = GeckoResult() + val onConfirm: () -> Unit = { geckoResult.complete(prompt.dismiss()) } + val title = prompt.title ?: "" + val message = prompt.message ?: "" geckoEngineSession.notifyObservers { - onPromptRequest(Alert(title ?: "", message ?: "", hasShownManyDialogs, onDismiss) { showMoreDialogs -> - callback.checkboxValue = showMoreDialogs - callback.dismiss() - }) + onPromptRequest( + PromptRequest.Alert( + title, + message, + false, + onConfirm + ) { _ -> + onConfirm() + }) } + return geckoResult } override fun onFilePrompt( session: GeckoSession, - title: String?, - selectionType: Int, - mimeTypes: Array?, - capture: Int, - callback: FileCallback - ) { + prompt: PromptDelegate.FilePrompt + ): GeckoResult? { + val geckoResult = GeckoResult() + val isMultipleFilesSelection = prompt.type == GECKO_PROMPT_FILE_TYPE.MULTIPLE + + val captureMode = when (prompt.capture) { + GECKO_PROMPT_FILE_CAPTURE.ANY -> AC_FILE_FACING_MODE.ANY + GECKO_PROMPT_FILE_CAPTURE.USER -> AC_FILE_FACING_MODE.FRONT_CAMERA + GECKO_PROMPT_FILE_CAPTURE.ENVIRONMENT -> AC_FILE_FACING_MODE.BACK_CAMERA + else -> AC_FILE_FACING_MODE.NONE + } val onSelectMultiple: (Context, Array) -> Unit = { context, uris -> val filesUris = uris.map { it.toFileUri(context) }.toTypedArray() - callback.confirm(context, filesUris) - } - - val isMultipleFilesSelection = selectionType == GeckoSession.PromptDelegate.FILE_TYPE_MULTIPLE - - val captureMode = when (capture) { - CAPTURE_TYPE_ANY -> PromptRequest.File.FacingMode.ANY - CAPTURE_TYPE_USER -> PromptRequest.File.FacingMode.FRONT_CAMERA - CAPTURE_TYPE_ENVIRONMENT -> PromptRequest.File.FacingMode.BACK_CAMERA - else -> PromptRequest.File.FacingMode.NONE + geckoResult.complete(prompt.confirm(context, filesUris)) } val onSelectSingle: (Context, Uri) -> Unit = { context, uri -> - callback.confirm(context, uri.toFileUri(context)) + geckoResult.complete(prompt.confirm(context, uri.toFileUri(context))) } val onDismiss: () -> Unit = { - callback.dismiss() + geckoResult.complete(prompt.dismiss()) } geckoEngineSession.notifyObservers { onPromptRequest( PromptRequest.File( - mimeTypes ?: emptyArray(), + prompt.mimeTypes ?: emptyArray(), isMultipleFilesSelection, captureMode, onSelectSingle, @@ -163,79 +154,77 @@ internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSe ) ) } + return geckoResult } override fun onDateTimePrompt( session: GeckoSession, - title: String?, - type: Int, - value: String?, - minDate: String?, - maxDate: String?, - geckoCallback: TextCallback - ) { - val initialDateString = value ?: "" + prompt: PromptDelegate.DateTimePrompt + ): GeckoResult? { + val geckoResult = GeckoResult() + val onConfirm: (String) -> Unit = { geckoResult.complete(prompt.confirm(it)) } val onClear: () -> Unit = { - geckoCallback.confirm("") + onConfirm("") } - val format = when (type) { - DATETIME_TYPE_DATE -> "yyyy-MM-dd" - DATETIME_TYPE_MONTH -> "yyyy-MM" - DATETIME_TYPE_WEEK -> "yyyy-'W'ww" - DATETIME_TYPE_TIME -> "HH:mm" - DATETIME_TYPE_DATETIME_LOCAL -> "yyyy-MM-dd'T'HH:mm" + val initialDateString = prompt.defaultValue ?: "" + + val format = when (prompt.type) { + DATE -> "yyyy-MM-dd" + MONTH -> "yyyy-MM" + WEEK -> "yyyy-'W'ww" + TIME -> "HH:mm" + DATETIME_LOCAL -> "yyyy-MM-dd'T'HH:mm" else -> { - throw InvalidParameterException("$type is not a valid DatetimeType") + throw InvalidParameterException("${prompt.type} is not a valid DatetimeType") } } notifyDatePromptRequest( - title ?: "", + prompt.title ?: "", initialDateString, - minDate, - maxDate, + prompt.minValue, + prompt.maxValue, onClear, format, - geckoCallback + onConfirm ) + + return geckoResult } override fun onAuthPrompt( session: GeckoSession, - title: String?, - message: String?, - options: AuthOptions, - geckoCallback: AuthCallback - ) { - - val flags = options.flags - val userName = options.username ?: "" - val password = options.password ?: "" - val method = if (flags in AUTH_FLAG_HOST) Method.HOST else Method.PROXY - - val level = getAuthLevel(options) - - val onlyShowPassword = flags in AUTH_FLAG_ONLY_PASSWORD - val previousFailed = flags in AUTH_FLAG_PREVIOUS_FAILED - val isCrossOrigin = flags in AUTH_FLAG_CROSS_ORIGIN_SUB_RESOURCE - - val onConfirm: (String, String) -> Unit = { user, pass -> - if (onlyShowPassword) { - geckoCallback.confirm(pass) - } else { - geckoCallback.confirm(user, pass) + geckoPrompt: PromptDelegate.AuthPrompt + ): GeckoResult? { + val geckoResult = GeckoResult() + val title = geckoPrompt.title ?: "" + val message = geckoPrompt.message ?: "" + val flags = geckoPrompt.authOptions.flags + val userName = geckoPrompt.authOptions.username ?: "" + val password = geckoPrompt.authOptions.password ?: "" + val method = + if (flags in GECKO_AUTH_FLAGS.HOST) AC_AUTH_METHOD.HOST else AC_AUTH_METHOD.PROXY + val level = geckoPrompt.authOptions.toACLevel() + val onlyShowPassword = flags in GECKO_AUTH_FLAGS.ONLY_PASSWORD + val previousFailed = flags in GECKO_AUTH_FLAGS.PREVIOUS_FAILED + val isCrossOrigin = flags in GECKO_AUTH_FLAGS.CROSS_ORIGIN_SUB_RESOURCE + + val onConfirm: (String, String) -> Unit = + { user, pass -> + if (onlyShowPassword) { + geckoResult.complete(geckoPrompt.confirm(pass)) + } else { + geckoResult.complete(geckoPrompt.confirm(user, pass)) + } } - } - val onDismiss: () -> Unit = { - geckoCallback.dismiss() - } + val onDismiss: () -> Unit = { geckoResult.complete(geckoPrompt.dismiss()) } geckoEngineSession.notifyObservers { onPromptRequest( PromptRequest.Authentication( - title ?: "", - message ?: "", + title, + message, userName, password, method, @@ -248,63 +237,64 @@ internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSe ) ) } + return geckoResult } override fun onTextPrompt( session: GeckoSession, - title: String?, - inputLabel: String?, - inputValue: String?, - callback: TextCallback - ) { - val hasShownManyDialogs = callback.hasCheckbox() - val onDismiss: () -> Unit = { - callback.dismiss() - } + prompt: PromptDelegate.TextPrompt + ): GeckoResult? { + val geckoResult = GeckoResult() + val title = prompt.title ?: "" + val inputLabel = prompt.message ?: "" + val inputValue = prompt.defaultValue ?: "" + val onDismiss: () -> Unit = { geckoResult.complete(prompt.dismiss()) } geckoEngineSession.notifyObservers { onPromptRequest( PromptRequest.TextPrompt( - title ?: "", - inputLabel ?: "", - inputValue ?: "", - hasShownManyDialogs, + title, + inputLabel, + inputValue, + false, onDismiss - ) { showMoreDialogs, valueInput -> - callback.checkboxValue = showMoreDialogs - callback.confirm(valueInput) + ) { _, valueInput -> + geckoResult.complete(prompt.confirm(valueInput)) }) } + + return geckoResult } override fun onColorPrompt( session: GeckoSession, - title: String?, - defaultColor: String?, - callback: TextCallback - ) { + prompt: PromptDelegate.ColorPrompt + ): GeckoResult? { + val geckoResult = GeckoResult() + val onConfirm: (String) -> Unit = { geckoResult.complete(prompt.confirm(it)) } + val onDismiss: () -> Unit = { geckoResult.complete(prompt.dismiss()) } + + val defaultColor = prompt.defaultValue ?: "" - val onConfirm: (String) -> Unit = { - callback.confirm(it) - } - val onDismiss: () -> Unit = { - callback.dismiss() - } geckoEngineSession.notifyObservers { onPromptRequest( - PromptRequest.Color(defaultColor ?: "", onConfirm, onDismiss) + PromptRequest.Color(defaultColor, onConfirm, onDismiss) ) } + return geckoResult } - override fun onPopupRequest(session: GeckoSession, targetUri: String?): GeckoResult { - val geckoResult = GeckoResult() - val onAllow: () -> Unit = { geckoResult.complete(AllowOrDeny.ALLOW) } - val onDeny: () -> Unit = { geckoResult.complete(AllowOrDeny.DENY) } + override fun onPopupPrompt( + session: GeckoSession, + prompt: PromptDelegate.PopupPrompt + ): GeckoResult { + val geckoResult = GeckoResult() + val onAllow: () -> Unit = { geckoResult.complete(prompt.confirm(AllowOrDeny.ALLOW)) } + val onDeny: () -> Unit = { geckoResult.complete(prompt.confirm(AllowOrDeny.DENY)) } geckoEngineSession.notifyObservers { onPromptRequest( - PromptRequest.Popup(targetUri ?: "", onAllow, onDeny) + PromptRequest.Popup(prompt.targetUri ?: "", onAllow, onDeny) ) } return geckoResult @@ -312,56 +302,47 @@ internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSe override fun onButtonPrompt( session: GeckoSession, - title: String?, - message: String?, - buttonTitles: Array?, - callback: ButtonCallback - ) { - val hasShownManyDialogs = callback.hasCheckbox() - val positiveButtonTitle = buttonTitles?.get(BUTTON_TYPE_POSITIVE) ?: "" - val negativeButtonTitle = buttonTitles?.get(BUTTON_TYPE_NEGATIVE) ?: "" - val neutralButtonTitle = buttonTitles?.get(BUTTON_TYPE_NEUTRAL) ?: "" - - val onConfirmPositiveButton: (Boolean) -> Unit = { showMoreDialogs -> - callback.checkboxValue = showMoreDialogs - callback.confirm(BUTTON_TYPE_POSITIVE) - } + prompt: PromptDelegate.ButtonPrompt + ): GeckoResult? { + val geckoResult = GeckoResult() + val title = prompt.title ?: "" + val message = prompt.message ?: "" - val onConfirmNegativeButton: (Boolean) -> Unit = { showMoreDialogs -> - callback.checkboxValue = showMoreDialogs - callback.confirm(BUTTON_TYPE_NEGATIVE) + val onConfirmPositiveButton: (Boolean) -> Unit = { + geckoResult.complete(prompt.confirm(PromptDelegate.ButtonPrompt.Type.POSITIVE)) } - - val onConfirmNeutralButton: (Boolean) -> Unit = { showMoreDialogs -> - callback.checkboxValue = showMoreDialogs - callback.confirm(BUTTON_TYPE_NEUTRAL) + val onConfirmNegativeButton: (Boolean) -> Unit = { + geckoResult.complete(prompt.confirm(PromptDelegate.ButtonPrompt.Type.NEGATIVE)) } - val onDismiss: () -> Unit = { - callback.dismiss() - } + val onDismiss: (Boolean) -> Unit = { geckoResult.complete(prompt.dismiss()) } geckoEngineSession.notifyObservers { onPromptRequest( PromptRequest.Confirm( - title ?: "", - message ?: "", - hasShownManyDialogs, - positiveButtonTitle, - negativeButtonTitle, - neutralButtonTitle, + title, + message, + false, + "", + "", + "", onConfirmPositiveButton, onConfirmNegativeButton, - onConfirmNeutralButton, onDismiss - ) + ) { + onDismiss(false) + } ) } + return geckoResult } private fun GeckoChoice.toChoice(): Choice { val choiceChildren = items?.map { it.toChoice() }?.toTypedArray() - return Choice(id, !disabled, label, selected, separator, choiceChildren) + // On the GeckoView docs states that label is a @NonNull, but on run-time + // we are getting null values + @Suppress("USELESS_ELVIS") + return Choice(id, !disabled, label ?: "", selected, separator, choiceChildren) } /** @@ -386,35 +367,45 @@ internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSe maxDateString: String?, onClear: () -> Unit, format: String, - geckoCallback: TextCallback + onConfirm: (String) -> Unit ) { val initialDate = initialDateString.toDate(format) val minDate = if (minDateString.isNullOrEmpty()) null else minDateString.toDate(format) val maxDate = if (maxDateString.isNullOrEmpty()) null else maxDateString.toDate(format) val onSelect: (Date) -> Unit = { val stringDate = it.toString(format) - geckoCallback.confirm(stringDate) + onConfirm(stringDate) } val selectionType = when (format) { - "HH:mm" -> TimeSelection.Type.TIME - "yyyy-MM" -> TimeSelection.Type.MONTH - "yyyy-MM-dd'T'HH:mm" -> TimeSelection.Type.DATE_AND_TIME - else -> TimeSelection.Type.DATE + "HH:mm" -> PromptRequest.TimeSelection.Type.TIME + "yyyy-MM" -> PromptRequest.TimeSelection.Type.MONTH + "yyyy-MM-dd'T'HH:mm" -> PromptRequest.TimeSelection.Type.DATE_AND_TIME + else -> PromptRequest.TimeSelection.Type.DATE } geckoEngineSession.notifyObservers { - onPromptRequest(TimeSelection(title, initialDate, minDate, maxDate, selectionType, onSelect, onClear)) + onPromptRequest( + PromptRequest.TimeSelection( + title, + initialDate, + minDate, + maxDate, + selectionType, + onSelect, + onClear + ) + ) } } - private fun getAuthLevel(options: AuthOptions): Level { - return when (options.level) { - AUTH_LEVEL_NONE -> Level.NONE - AUTH_LEVEL_PW_ENCRYPTED -> Level.PASSWORD_ENCRYPTED - AUTH_LEVEL_SECURE -> Level.SECURED + private fun GeckoAuthOptions.toACLevel(): AC_AUTH_LEVEL { + return when (level) { + GECKO_AUTH_LEVEL.NONE -> AC_AUTH_LEVEL.NONE + GECKO_AUTH_LEVEL.PW_ENCRYPTED -> AC_AUTH_LEVEL.PASSWORD_ENCRYPTED + GECKO_AUTH_LEVEL.SECURE -> AC_AUTH_LEVEL.SECURED else -> { - Level.NONE + AC_AUTH_LEVEL.NONE } } } diff --git a/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt b/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt index 58620bf5186..34d3111f9df 100644 --- a/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt +++ b/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt @@ -7,6 +7,7 @@ package mozilla.components.browser.engine.gecko.media import mozilla.components.concept.engine.media.Media import mozilla.components.support.test.argumentCaptor import mozilla.components.support.test.mock +import mozilla.components.test.ReflectionUtils import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test @@ -84,4 +85,38 @@ class GeckoMediaTest { delegate.onPlaybackStateChange(mediaElement, MediaElement.MEDIA_STATE_PLAYING) verify(observer).onPlaybackStateChanged(media, Media.PlaybackState.PLAYING) } + + @Test + fun `GeckoMedia exposes Metadata`() { + val mediaElement: MediaElement = mock() + + val media = GeckoMedia(mediaElement) + + val captor = argumentCaptor() + verify(mediaElement).delegate = captor.capture() + + assertEquals(-1.0, media.metadata.duration, 0.0001) + + val delegate = captor.value + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = 5.0)) + assertEquals(5.0, media.metadata.duration, 0.0001) + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = 572.0)) + assertEquals(572.0, media.metadata.duration, 0.0001) + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = 0.0)) + assertEquals(0.0, media.metadata.duration, 0.0001) + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = -1.0)) + assertEquals(-1.0, media.metadata.duration, 0.0001) + } +} + +private class MockedGeckoMetadata( + duration: Double +) : MediaElement.Metadata() { + init { + ReflectionUtils.setField(this, "duration", duration) + } } diff --git a/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegateTest.kt b/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegateTest.kt index 7cabe58ac9b..02429dd28ec 100644 --- a/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegateTest.kt +++ b/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegateTest.kt @@ -4,56 +4,47 @@ package mozilla.components.browser.engine.gecko.prompt -import android.content.Context import android.net.Uri -import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import mozilla.components.browser.engine.gecko.GeckoEngineSession import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.prompt.Choice import mozilla.components.concept.engine.prompt.PromptRequest -import mozilla.components.concept.engine.prompt.PromptRequest.Authentication.Level.NONE -import mozilla.components.concept.engine.prompt.PromptRequest.Authentication.Level.PASSWORD_ENCRYPTED -import mozilla.components.concept.engine.prompt.PromptRequest.Authentication.Level.SECURED -import mozilla.components.concept.engine.prompt.PromptRequest.Authentication.Method.HOST import mozilla.components.concept.engine.prompt.PromptRequest.MultipleChoice import mozilla.components.concept.engine.prompt.PromptRequest.SingleChoice import mozilla.components.support.ktx.kotlin.toDate import mozilla.components.support.test.mock +import mozilla.components.support.test.robolectric.testContext +import mozilla.components.test.ReflectionUtils import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith -import org.mozilla.geckoview.AllowOrDeny -import org.mozilla.geckoview.GeckoResult +import org.mozilla.gecko.util.GeckoBundle import org.mozilla.geckoview.GeckoSession -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_FLAG_CROSS_ORIGIN_SUB_RESOURCE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_FLAG_HOST -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_FLAG_ONLY_PASSWORD -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_FLAG_PREVIOUS_FAILED -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_LEVEL_PW_ENCRYPTED -import org.mozilla.geckoview.GeckoSession.PromptDelegate.AuthOptions.AUTH_LEVEL_SECURE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.BUTTON_TYPE_NEGATIVE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.BUTTON_TYPE_NEUTRAL -import org.mozilla.geckoview.GeckoSession.PromptDelegate.BUTTON_TYPE_POSITIVE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.Choice.CHOICE_TYPE_MULTIPLE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.Choice.CHOICE_TYPE_SINGLE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.DATETIME_TYPE_DATE -import org.mozilla.geckoview.GeckoSession.PromptDelegate.DATETIME_TYPE_DATETIME_LOCAL -import org.mozilla.geckoview.GeckoSession.PromptDelegate.DATETIME_TYPE_MONTH -import org.mozilla.geckoview.GeckoSession.PromptDelegate.DATETIME_TYPE_TIME -import org.mozilla.geckoview.GeckoSession.PromptDelegate.DATETIME_TYPE_WEEK -import org.mozilla.geckoview.GeckoSession.PromptDelegate.TextCallback +import java.security.InvalidParameterException +import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.DATE +import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.DATETIME_LOCAL +import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.MONTH +import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.TIME +import org.mozilla.geckoview.GeckoSession.PromptDelegate.DateTimePrompt.Type.WEEK +import org.mozilla.geckoview.GeckoSession.PromptDelegate.FilePrompt.Capture.ANY +import org.mozilla.geckoview.GeckoSession.PromptDelegate.FilePrompt.Capture.NONE +import org.mozilla.geckoview.GeckoSession.PromptDelegate.FilePrompt.Capture.USER import org.robolectric.Shadows.shadowOf import java.io.FileInputStream -import java.security.InvalidParameterException import java.util.Calendar import java.util.Calendar.YEAR import java.util.Date - -typealias GeckoChoice = GeckoSession.PromptDelegate.Choice +typealias GeckoChoice = GeckoSession.PromptDelegate.ChoicePrompt.Choice +typealias GECKO_AUTH_LEVEL = GeckoSession.PromptDelegate.AuthPrompt.AuthOptions.Level +typealias GECKO_PROMPT_CHOICE_TYPE = GeckoSession.PromptDelegate.ChoicePrompt.Type +typealias GECKO_AUTH_FLAGS = GeckoSession.PromptDelegate.AuthPrompt.AuthOptions.Flags +typealias GECKO_PROMPT_FILE_TYPE = GeckoSession.PromptDelegate.FilePrompt.Type +typealias AC_AUTH_METHOD = PromptRequest.Authentication.Method +typealias AC_AUTH_LEVEL = PromptRequest.Authentication.Level @RunWith(AndroidJUnit4::class) class GeckoPromptDelegateTest { @@ -63,23 +54,26 @@ class GeckoPromptDelegateTest { val mockSession = GeckoEngineSession(mock()) var promptRequestSingleChoice: PromptRequest = MultipleChoice(arrayOf()) {} var confirmWasCalled = false - - val callback = object : DefaultGeckoChoiceCallback() { - override fun confirm(id: String?) { - confirmWasCalled = true - } - } - val gecko = GeckoPromptDelegate(mockSession) val geckoChoice = object : GeckoChoice() {} - val geckoChoices = arrayOf(geckoChoice) + val geckoPrompt = GeckoChoicePrompt( + "title", + "message", + GECKO_PROMPT_CHOICE_TYPE.SINGLE, + arrayOf(geckoChoice) + ) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { promptRequestSingleChoice = promptRequest } }) - gecko.onChoicePrompt(mock(), null, null, CHOICE_TYPE_SINGLE, geckoChoices, callback) + + val geckoResult = gecko.onChoicePrompt(mock(), geckoPrompt) + + geckoResult!!.accept { + confirmWasCalled = true + } assertTrue(promptRequestSingleChoice is SingleChoice) val request = promptRequestSingleChoice as SingleChoice @@ -93,16 +87,14 @@ class GeckoPromptDelegateTest { val mockSession = GeckoEngineSession(mock()) var promptRequestSingleChoice: PromptRequest = SingleChoice(arrayOf()) {} var confirmWasCalled = false - - val callback = object : DefaultGeckoChoiceCallback() { - override fun confirm(ids: Array) { - confirmWasCalled = true - } - } - val gecko = GeckoPromptDelegate(mockSession) val mockGeckoChoice = object : GeckoChoice() {} - val geckoChoices = arrayOf(mockGeckoChoice) + val geckoPrompt = GeckoChoicePrompt( + "title", + "message", + GECKO_PROMPT_CHOICE_TYPE.MULTIPLE, + arrayOf(mockGeckoChoice) + ) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { @@ -110,7 +102,11 @@ class GeckoPromptDelegateTest { } }) - gecko.onChoicePrompt(mock(), null, null, CHOICE_TYPE_MULTIPLE, geckoChoices, callback) + val geckoResult = gecko.onChoicePrompt(mock(), geckoPrompt) + + geckoResult!!.accept { + confirmWasCalled = true + } assertTrue(promptRequestSingleChoice is MultipleChoice) @@ -123,16 +119,14 @@ class GeckoPromptDelegateTest { val mockSession = GeckoEngineSession(mock()) var promptRequestSingleChoice: PromptRequest = PromptRequest.MenuChoice(arrayOf()) {} var confirmWasCalled = false - - val callback = object : DefaultGeckoChoiceCallback() { - override fun confirm(id: String?) { - confirmWasCalled = true - } - } - val gecko = GeckoPromptDelegate(mockSession) val geckoChoice = object : GeckoChoice() {} - val geckoChoices = arrayOf(geckoChoice) + val geckoPrompt = GeckoChoicePrompt( + "title", + "message", + GECKO_PROMPT_CHOICE_TYPE.MENU, + arrayOf(geckoChoice) + ) mockSession.register( object : EngineSession.Observer { @@ -141,10 +135,10 @@ class GeckoPromptDelegateTest { } }) - gecko.onChoicePrompt( - mock(), null, null, - GeckoSession.PromptDelegate.Choice.CHOICE_TYPE_MENU, geckoChoices, callback - ) + val geckoResult = gecko.onChoicePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + confirmWasCalled = true + } assertTrue(promptRequestSingleChoice is PromptRequest.MenuChoice) val request = promptRequestSingleChoice as PromptRequest.MenuChoice @@ -156,37 +150,20 @@ class GeckoPromptDelegateTest { @Test(expected = InvalidParameterException::class) fun `calling onChoicePrompt with not valid Gecko ChoiceType will throw an exception`() { val promptDelegate = GeckoPromptDelegate(mock()) - promptDelegate.onChoicePrompt( - mock(), + val geckoPrompt = GeckoChoicePrompt( "title", "message", -1, - arrayOf(), - mock() + arrayOf() ) + promptDelegate.onChoicePrompt(mock(), geckoPrompt) } @Test - fun `onAlert must provide an alert PromptRequest`() { + fun `onAlertPrompt must provide an alert PromptRequest`() { val mockSession = GeckoEngineSession(mock()) var alertRequest: PromptRequest? = null var dismissWasCalled = false - var setCheckboxValueWasCalled = false - - val callback = object : GeckoSession.PromptDelegate.AlertCallback { - - override fun setCheckboxValue(value: Boolean) { - setCheckboxValueWasCalled = true - } - - override fun dismiss() { - dismissWasCalled = true - } - - override fun getCheckboxValue(): Boolean = false - override fun hasCheckbox(): Boolean = false - override fun getCheckboxMessage(): String = "" - } val promptDelegate = GeckoPromptDelegate(mockSession) @@ -196,31 +173,19 @@ class GeckoPromptDelegateTest { } }) - promptDelegate.onAlert(mock(), "title", "message", callback) - + val geckoResult = promptDelegate.onAlertPrompt(mock(), GeckoAlertPrompt()) + geckoResult.accept { + dismissWasCalled = true + } assertTrue(alertRequest is PromptRequest.Alert) (alertRequest as PromptRequest.Alert).onDismiss() assertTrue(dismissWasCalled) - (alertRequest as PromptRequest.Alert).onConfirm(true) - assertTrue(setCheckboxValueWasCalled) - assertEquals((alertRequest as PromptRequest.Alert).title, "title") assertEquals((alertRequest as PromptRequest.Alert).message, "message") } - @Test - fun `hitting default values`() { - val mockSession = GeckoEngineSession(mock()) - val gecko = GeckoPromptDelegate(mockSession) - gecko.onDateTimePrompt(mock(), null, DATETIME_TYPE_DATE, null, null, null, mock()) - gecko.onDateTimePrompt(mock(), null, DATETIME_TYPE_WEEK, null, null, null, mock()) - gecko.onDateTimePrompt(mock(), null, DATETIME_TYPE_MONTH, null, null, null, mock()) - gecko.onDateTimePrompt(mock(), null, DATETIME_TYPE_TIME, null, "", "", mock()) - gecko.onButtonPrompt(mock(), null, null, arrayOf(null, null, null), mock()) - } - @Test fun `toIdsArray must convert an list of choices to array of id strings`() { val choices = arrayOf(Choice(id = "0", label = ""), Choice(id = "1", label = "")) @@ -236,32 +201,31 @@ class GeckoPromptDelegateTest { var dateRequest: PromptRequest? = null var confirmCalled = false var onClearPicker = false + var geckoPrompt = GeckoDateTimePrompt("title", DATE, "", "", "") - val callback = object : TextCallback { - override fun dismiss() = Unit - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(text: String?) { - confirmCalled = true - if (text!!.isEmpty()) { - onClearPicker = true - } - } - } val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { dateRequest = promptRequest } }) - promptDelegate.onDateTimePrompt(mock(), "title", DATETIME_TYPE_DATE, "", "", "", callback) + + var geckoResult = promptDelegate.onDateTimePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + confirmCalled = true + } + assertTrue(dateRequest is PromptRequest.TimeSelection) (dateRequest as PromptRequest.TimeSelection).onConfirm(Date()) assertTrue(confirmCalled) assertEquals((dateRequest as PromptRequest.TimeSelection).title, "title") + geckoPrompt = GeckoDateTimePrompt("title", DATE, "", "", "") + geckoResult = promptDelegate.onDateTimePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + onClearPicker = true + } + (dateRequest as PromptRequest.TimeSelection).onClear() assertTrue(onClearPicker) } @@ -271,31 +235,27 @@ class GeckoPromptDelegateTest { val mockSession = GeckoEngineSession(mock()) var timeSelectionRequest: PromptRequest.TimeSelection? = null var geckoDate: String? = null - val callback = object : TextCallback { - override fun dismiss() = Unit - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(text: String?) { - geckoDate = text - } - } + + val geckoPrompt = + GeckoDateTimePrompt( + title = "title", + type = DATE, + defaultValue = "2019-11-29", + minValue = "2019-11-28", + maxValue = "2019-11-30" + ) val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { timeSelectionRequest = promptRequest as PromptRequest.TimeSelection } }) - promptDelegate.onDateTimePrompt( - mock(), - "title", - DATETIME_TYPE_DATE, - "2019-11-29", - "2019-11-28", - "2019-11-30", - callback - ) + + val geckoResult = promptDelegate.onDateTimePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + geckoDate = geckoPrompt.getGeckoResult()["datetime"].toString() + } + assertNotNull(timeSelectionRequest) with(timeSelectionRequest!!) { assertEquals(initialDate, "2019-11-29".toDate("yyyy-MM-dd")) @@ -313,23 +273,19 @@ class GeckoPromptDelegateTest { val mockSession = GeckoEngineSession(mock()) var dateRequest: PromptRequest? = null var confirmCalled = false - val callback = object : TextCallback { - override fun dismiss() = Unit - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(text: String?) { - confirmCalled = true - } - } + val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { dateRequest = promptRequest } }) - promptDelegate.onDateTimePrompt(mock(), "title", DATETIME_TYPE_MONTH, "", "", "", callback) + val geckoPrompt = GeckoDateTimePrompt(type = MONTH) + + val geckoResult = promptDelegate.onDateTimePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + confirmCalled = true + } assertTrue(dateRequest is PromptRequest.TimeSelection) (dateRequest as PromptRequest.TimeSelection).onConfirm(Date()) assertTrue(confirmCalled) @@ -341,31 +297,25 @@ class GeckoPromptDelegateTest { val mockSession = GeckoEngineSession(mock()) var timeSelectionRequest: PromptRequest.TimeSelection? = null var geckoDate: String? = null - val callback = object : TextCallback { - override fun dismiss() = Unit - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(text: String?) { - geckoDate = text - } - } + val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { timeSelectionRequest = promptRequest as PromptRequest.TimeSelection } }) - promptDelegate.onDateTimePrompt( - mock(), - "title", - DATETIME_TYPE_MONTH, - "2019-11", - "2019-11", - "2019-11", - callback + val geckoPrompt = GeckoDateTimePrompt( + title = "title", + type = MONTH, + defaultValue = "2019-11", + minValue = "2019-11", + maxValue = "2019-11" ) + val geckoResult = promptDelegate.onDateTimePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + geckoDate = geckoPrompt.getGeckoResult()["datetime"].toString() + } + assertNotNull(timeSelectionRequest) with(timeSelectionRequest!!) { assertEquals(initialDate, "2019-11".toDate("yyyy-MM")) @@ -383,23 +333,19 @@ class GeckoPromptDelegateTest { val mockSession = GeckoEngineSession(mock()) var dateRequest: PromptRequest? = null var confirmCalled = false - val callback = object : TextCallback { - override fun dismiss() = Unit - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(text: String?) { - confirmCalled = true - } - } val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { dateRequest = promptRequest } }) - promptDelegate.onDateTimePrompt(mock(), "title", DATETIME_TYPE_WEEK, "", "", "", callback) + val geckoPrompt = GeckoDateTimePrompt(type = WEEK) + + val geckoResult = promptDelegate.onDateTimePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + confirmCalled = true + } + assertTrue(dateRequest is PromptRequest.TimeSelection) (dateRequest as PromptRequest.TimeSelection).onConfirm(Date()) assertTrue(confirmCalled) @@ -411,31 +357,25 @@ class GeckoPromptDelegateTest { val mockSession = GeckoEngineSession(mock()) var timeSelectionRequest: PromptRequest.TimeSelection? = null var geckoDate: String? = null - val callback = object : TextCallback { - override fun dismiss() = Unit - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(text: String?) { - geckoDate = text - } - } val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { timeSelectionRequest = promptRequest as PromptRequest.TimeSelection } }) - promptDelegate.onDateTimePrompt( - mock(), - "title", - DATETIME_TYPE_WEEK, - "2018-W18", - "2018-W18", - "2018-W26", - callback + + val geckoPrompt = GeckoDateTimePrompt( + title = "title", + type = WEEK, + defaultValue = "2018-W18", + minValue = "2018-W18", + maxValue = "2018-W26" ) + val geckoResult = promptDelegate.onDateTimePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + geckoDate = geckoPrompt.getGeckoResult()["datetime"].toString() + } + assertNotNull(timeSelectionRequest) with(timeSelectionRequest!!) { assertEquals(initialDate, "2018-W18".toDate("yyyy-'W'ww")) @@ -454,23 +394,19 @@ class GeckoPromptDelegateTest { var dateRequest: PromptRequest? = null var confirmCalled = false - val callback = object : TextCallback { - override fun dismiss() = Unit - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(text: String?) { - confirmCalled = true - } - } val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { dateRequest = promptRequest } }) - promptDelegate.onDateTimePrompt(mock(), "title", DATETIME_TYPE_TIME, "", "", "", callback) + val geckoPrompt = GeckoDateTimePrompt(type = TIME) + + val geckoResult = promptDelegate.onDateTimePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + confirmCalled = true + } + assertTrue(dateRequest is PromptRequest.TimeSelection) (dateRequest as PromptRequest.TimeSelection).onConfirm(Date()) assertTrue(confirmCalled) @@ -482,31 +418,26 @@ class GeckoPromptDelegateTest { val mockSession = GeckoEngineSession(mock()) var timeSelectionRequest: PromptRequest.TimeSelection? = null var geckoDate: String? = null - val callback = object : TextCallback { - override fun dismiss() = Unit - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(text: String?) { - geckoDate = text - } - } + val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { timeSelectionRequest = promptRequest as PromptRequest.TimeSelection } }) - promptDelegate.onDateTimePrompt( - mock(), - "title", - DATETIME_TYPE_TIME, - "17:00", - "9:00", - "18:00", - callback + + val geckoPrompt = GeckoDateTimePrompt( + title = "title", + type = TIME, + defaultValue = "17:00", + minValue = "9:00", + maxValue = "18:00" ) + val geckoResult = promptDelegate.onDateTimePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + geckoDate = geckoPrompt.getGeckoResult()["datetime"].toString() + } + assertNotNull(timeSelectionRequest) with(timeSelectionRequest!!) { assertEquals(initialDate, "17:00".toDate("HH:mm")) @@ -525,26 +456,17 @@ class GeckoPromptDelegateTest { var dateRequest: PromptRequest? = null var confirmCalled = false - val callback = object : TextCallback { - override fun dismiss() = Unit - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(text: String?) { - confirmCalled = true - } - } val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { dateRequest = promptRequest } }) - promptDelegate.onDateTimePrompt( - mock(), "title", - DATETIME_TYPE_DATETIME_LOCAL, "", "", "", callback - ) + val geckoResult = promptDelegate.onDateTimePrompt(mock(), GeckoDateTimePrompt(type = DATETIME_LOCAL)) + geckoResult!!.accept { + confirmCalled = true + } + assertTrue(dateRequest is PromptRequest.TimeSelection) (dateRequest as PromptRequest.TimeSelection).onConfirm(Date()) assertTrue(confirmCalled) @@ -556,31 +478,24 @@ class GeckoPromptDelegateTest { val mockSession = GeckoEngineSession(mock()) var timeSelectionRequest: PromptRequest.TimeSelection? = null var geckoDate: String? = null - val callback = object : TextCallback { - override fun dismiss() = Unit - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(text: String?) { - geckoDate = text - } - } val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { timeSelectionRequest = promptRequest as PromptRequest.TimeSelection } }) - promptDelegate.onDateTimePrompt( - mock(), - "title", - DATETIME_TYPE_DATETIME_LOCAL, - "2018-06-12T19:30", - "2018-06-07T00:00", - "2018-06-14T00:00", - callback + val geckoPrompt = GeckoDateTimePrompt( + title = "title", + type = DATETIME_LOCAL, + defaultValue = "2018-06-12T19:30", + minValue = "2018-06-07T00:00", + maxValue = "2018-06-14T00:00" ) + val geckoResult = promptDelegate.onDateTimePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + geckoDate = geckoPrompt.getGeckoResult()["datetime"].toString() + } + assertNotNull(timeSelectionRequest) with(timeSelectionRequest!!) { assertEquals(initialDate, "2018-06-12T19:30".toDate("yyyy-MM-dd'T'HH:mm")) @@ -598,12 +513,12 @@ class GeckoPromptDelegateTest { val promptDelegate = GeckoPromptDelegate(mock()) promptDelegate.onDateTimePrompt( mock(), - "title", - 13223, - "17:00", - "9:00", - "18:00", - mock() + GeckoDateTimePrompt( + type = 13223, + defaultValue = "17:00", + minValue = "9:00", + maxValue = "18:00" + ) ) } @@ -623,10 +538,9 @@ class GeckoPromptDelegateTest { @Test fun `Calling onFilePrompt must provide a FilePicker PromptRequest`() { - val context = ApplicationProvider.getApplicationContext() + val context = testContext val mockSession = GeckoEngineSession(mock()) - var request: PromptRequest? = null var onSingleFileSelectedWasCalled = false var onMultipleFilesSelectedWasCalled = false var onDismissWasCalled = false @@ -635,51 +549,39 @@ class GeckoPromptDelegateTest { val shadowContentResolver = shadowOf(context.contentResolver) shadowContentResolver.registerInputStream(mockUri, mockFileInput) - - val callback = object : GeckoSession.PromptDelegate.FileCallback { - override fun dismiss() { - onDismissWasCalled = true - } - - override fun confirm(context: Context?, uri: Uri?) { - onSingleFileSelectedWasCalled = true - } - - override fun confirm(context: Context?, uris: Array?) { - onMultipleFilesSelectedWasCalled = true - } - - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - } + var filePickerRequest: PromptRequest.File = mock() val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { - request = promptRequest + filePickerRequest = promptRequest as PromptRequest.File } }) + var geckoPrompt = GeckoFilePrompt(type = GECKO_PROMPT_FILE_TYPE.SINGLE, capture = NONE) - promptDelegate.onFilePrompt( - mock(), - "title", - GeckoSession.PromptDelegate.FILE_TYPE_SINGLE, - emptyArray(), - GeckoSession.PromptDelegate.CAPTURE_TYPE_NONE, - callback - ) - assertTrue(request is PromptRequest.File) - - val filePickerRequest = request as PromptRequest.File + var geckoResult = promptDelegate.onFilePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + onSingleFileSelectedWasCalled = true + } filePickerRequest.onSingleFileSelected(context, mockUri) assertTrue(onSingleFileSelectedWasCalled) + geckoPrompt = GeckoFilePrompt(type = GECKO_PROMPT_FILE_TYPE.MULTIPLE, capture = ANY) + geckoResult = promptDelegate.onFilePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + onMultipleFilesSelectedWasCalled = true + } + filePickerRequest.onMultipleFilesSelected(context, arrayOf(mockUri)) assertTrue(onMultipleFilesSelectedWasCalled) + geckoPrompt = GeckoFilePrompt(type = GECKO_PROMPT_FILE_TYPE.SINGLE, capture = NONE) + geckoResult = promptDelegate.onFilePrompt(mock(), geckoPrompt) + geckoResult!!.accept { + onDismissWasCalled = true + } + filePickerRequest.onDismiss() assertTrue(onDismissWasCalled) @@ -689,74 +591,66 @@ class GeckoPromptDelegateTest { promptDelegate.onFilePrompt( mock(), - "title", - GeckoSession.PromptDelegate.FILE_TYPE_MULTIPLE, - emptyArray(), - GeckoSession.PromptDelegate.CAPTURE_TYPE_USER, - callback + GeckoFilePrompt(type = GECKO_PROMPT_FILE_TYPE.MULTIPLE, capture = USER) ) - assertTrue((request as PromptRequest.File).isMultipleFilesSelection) - assertEquals(PromptRequest.File.FacingMode.FRONT_CAMERA, (request as PromptRequest.File).captureMode) + assertTrue(filePickerRequest.isMultipleFilesSelection) + assertEquals( + PromptRequest.File.FacingMode.FRONT_CAMERA, + filePickerRequest.captureMode + ) } @Test fun `Calling onAuthPrompt must provide an Authentication PromptRequest`() { val mockSession = GeckoEngineSession(mock()) - var request: PromptRequest? = null + var authRequest: PromptRequest.Authentication = mock() var onConfirmWasCalled = false var onConfirmOnlyPasswordWasCalled = false var onDismissWasCalled = false - val authOptions = mock() - - val geckoCallback = object : GeckoSession.PromptDelegate.AuthCallback { - - override fun confirm(username: String, password: String) { - onConfirmWasCalled = true - } - - override fun dismiss() { - onDismissWasCalled = true - } - - override fun confirm(password: String?) { - onConfirmOnlyPasswordWasCalled = true - } - - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - } val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { - request = promptRequest + authRequest = promptRequest as PromptRequest.Authentication } }) - promptDelegate.onAuthPrompt(mock(), "title", "message", authOptions, geckoCallback) - assertTrue(request is PromptRequest.Authentication) - - var authRequest = request as PromptRequest.Authentication + var geckoResult = + promptDelegate.onAuthPrompt(mock(), GeckoAuthPrompt(authOptions = mock())) + geckoResult!!.accept { + onConfirmWasCalled = true + } authRequest.onConfirm("", "") assertTrue(onConfirmWasCalled) + geckoResult = + promptDelegate.onAuthPrompt(mock(), GeckoAuthPrompt(authOptions = mock())) + geckoResult!!.accept { + onDismissWasCalled = true + } + authRequest.onDismiss() assertTrue(onDismissWasCalled) - authOptions.level = AUTH_LEVEL_SECURE + val authOptions = GeckoAuthOptions() + ReflectionUtils.setField(authOptions, "level", GECKO_AUTH_LEVEL.SECURE) - authOptions.flags = authOptions.flags.or(AUTH_FLAG_ONLY_PASSWORD) - authOptions.flags = authOptions.flags.or(AUTH_FLAG_PREVIOUS_FAILED) - authOptions.flags = authOptions.flags.or(AUTH_FLAG_CROSS_ORIGIN_SUB_RESOURCE) - authOptions.flags = authOptions.flags.or(AUTH_FLAG_HOST) + var flags = 0 + flags = flags.or(GECKO_AUTH_FLAGS.ONLY_PASSWORD) + flags = flags.or(GECKO_AUTH_FLAGS.PREVIOUS_FAILED) + flags = flags.or(GECKO_AUTH_FLAGS.CROSS_ORIGIN_SUB_RESOURCE) + flags = flags.or(GECKO_AUTH_FLAGS.HOST) + ReflectionUtils.setField(authOptions, "flags", flags) - promptDelegate.onAuthPrompt(mock(), "title", "message", authOptions, geckoCallback) - - authRequest = request as PromptRequest.Authentication + val geckoPrompt = GeckoAuthPrompt(authOptions = authOptions) + geckoResult = promptDelegate.onAuthPrompt(mock(), geckoPrompt) + geckoResult!!.accept { + val hasPassword = geckoPrompt.getGeckoResult().containsKey("password") + val hasUser = geckoPrompt.getGeckoResult().containsKey("username") + onConfirmOnlyPasswordWasCalled = hasPassword && hasUser == false + } authRequest.onConfirm("", "") @@ -765,60 +659,43 @@ class GeckoPromptDelegateTest { assertTrue(previousFailed) assertTrue(isCrossOrigin) - assertEquals(method, HOST) - assertEquals(level, SECURED) + assertEquals(method, AC_AUTH_METHOD.HOST) + assertEquals(level, AC_AUTH_LEVEL.SECURED) assertTrue(onConfirmOnlyPasswordWasCalled) } - authOptions.level = AUTH_LEVEL_PW_ENCRYPTED + ReflectionUtils.setField(authOptions, "level", GECKO_AUTH_LEVEL.PW_ENCRYPTED) - promptDelegate.onAuthPrompt(mock(), "title", "message", authOptions, geckoCallback) - authRequest = request as PromptRequest.Authentication + promptDelegate.onAuthPrompt(mock(), GeckoAuthPrompt(authOptions = authOptions)) - assertEquals(authRequest.level, PASSWORD_ENCRYPTED) + assertEquals(authRequest.level, AC_AUTH_LEVEL.PASSWORD_ENCRYPTED) - authOptions.level = -2423 + ReflectionUtils.setField(authOptions, "level", -2423) - promptDelegate.onAuthPrompt(mock(), "title", "message", authOptions, geckoCallback) - authRequest = request as PromptRequest.Authentication + promptDelegate.onAuthPrompt(mock(), GeckoAuthPrompt(authOptions = authOptions)) - assertEquals(authRequest.level, NONE) + assertEquals(authRequest.level, AC_AUTH_LEVEL.NONE) } @Test fun `Calling onColorPrompt must provide a Color PromptRequest`() { val mockSession = GeckoEngineSession(mock()) - var request: PromptRequest? = null + var colorRequest: PromptRequest.Color = mock() var onConfirmWasCalled = false var onDismissWasCalled = false - val geckoCallback = object : TextCallback { - - override fun confirm(text: String?) { - onConfirmWasCalled = true - } - - override fun dismiss() { - onDismissWasCalled = true - } - - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - } - val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { - request = promptRequest + colorRequest = promptRequest as PromptRequest.Color } }) - promptDelegate.onColorPrompt(mock(), "title", "#e66465", geckoCallback) - assertTrue(request is PromptRequest.Color) - - var colorRequest = request as PromptRequest.Color + var geckoResult = + promptDelegate.onColorPrompt(mock(), GeckoColorPrompt(defaultValue = "#e66465")) + geckoResult!!.accept { + onConfirmWasCalled = true + } with(colorRequest) { @@ -826,68 +703,57 @@ class GeckoPromptDelegateTest { onConfirm("#f6b73c") assertTrue(onConfirmWasCalled) + } - onDismiss() - assertTrue(onDismissWasCalled) + geckoResult = promptDelegate.onColorPrompt(mock(), GeckoColorPrompt()) + geckoResult!!.accept { + onDismissWasCalled = true } - promptDelegate.onColorPrompt(mock(), null, null, geckoCallback) - colorRequest = request as PromptRequest.Color + colorRequest.onDismiss() + assertTrue(onDismissWasCalled) with(colorRequest) { - assertEquals(defaultColor, "") + assertEquals(defaultColor, "defaultValue") } } @Test fun `onTextPrompt must provide an TextPrompt PromptRequest`() { val mockSession = GeckoEngineSession(mock()) - var request: PromptRequest? = null + var request: PromptRequest.TextPrompt = mock() var dismissWasCalled = false var confirmWasCalled = false - var setCheckboxValueWasCalled = false - - val callback = object : TextCallback { - - override fun confirm(text: String?) { - confirmWasCalled = true - } - - override fun setCheckboxValue(value: Boolean) { - setCheckboxValueWasCalled = true - } - - override fun dismiss() { - dismissWasCalled = true - } - - override fun getCheckboxValue(): Boolean = false - override fun hasCheckbox(): Boolean = false - override fun getCheckboxMessage(): String = "" - } val promptDelegate = GeckoPromptDelegate(mockSession) mockSession.register(object : EngineSession.Observer { override fun onPromptRequest(promptRequest: PromptRequest) { - request = promptRequest + request = promptRequest as PromptRequest.TextPrompt } }) - promptDelegate.onTextPrompt(mock(), "title", "label", "value", callback) + var geckoResult = promptDelegate.onTextPrompt(mock(), GeckoTextPrompt()) + geckoResult!!.accept { + dismissWasCalled = true + } - with(request as PromptRequest.TextPrompt) { + with(request) { assertEquals(title, "title") - assertEquals(inputLabel, "label") - assertEquals(inputValue, "value") + assertEquals(inputLabel, "message") + assertEquals(inputValue, "defaultValue") onDismiss() assertTrue(dismissWasCalled) + } - onConfirm(true, "newInput") - assertTrue(setCheckboxValueWasCalled) - assertTrue(confirmWasCalled) + geckoResult = promptDelegate.onTextPrompt(mock(), GeckoTextPrompt()) + geckoResult!!.accept { + confirmWasCalled = true } + + request.onConfirm(true, "newInput") + assertTrue(confirmWasCalled) } @Test @@ -905,18 +771,12 @@ class GeckoPromptDelegateTest { } }) - var geckoCallback = promptDelegate.onPopupRequest(mock(), "www.popuptest.com/") - - val geckoThen: (AllowOrDeny?) -> GeckoResult = { - when (it!!) { - AllowOrDeny.ALLOW -> { onAllowWasCalled = true } - AllowOrDeny.DENY -> { onDenyWasCalled = true } - } - geckoCallback + var geckoPrompt = GeckoPopupPrompt(targetUri = "www.popuptest.com/") + var geckoResult = promptDelegate.onPopupPrompt(mock(), geckoPrompt) + geckoResult.accept { + onAllowWasCalled = geckoPrompt.getGeckoResult()["response"] == true } - geckoCallback.then(geckoThen) - with(request!!) { assertEquals(targetUri, "www.popuptest.com/") @@ -924,8 +784,11 @@ class GeckoPromptDelegateTest { assertTrue(onAllowWasCalled) } - geckoCallback = promptDelegate.onPopupRequest(mock(), "www.popuptest.com/") - geckoCallback.then(geckoThen) + geckoPrompt = GeckoPopupPrompt() + geckoResult = promptDelegate.onPopupPrompt(mock(), geckoPrompt) + geckoResult.accept { + onDenyWasCalled = geckoPrompt.getGeckoResult()["response"] == false + } request!!.onDeny() assertTrue(onDenyWasCalled) @@ -934,12 +797,11 @@ class GeckoPromptDelegateTest { @Test fun `onButtonPrompt must provide a Confirm PromptRequest`() { val mockSession = GeckoEngineSession(mock()) - var request: PromptRequest.Confirm? = null + var request: PromptRequest.Confirm = mock() var onPositiveButtonWasCalled = false var onNegativeButtonWasCalled = false var onNeutralButtonWasCalled = false var dismissWasCalled = false - var setCheckboxValueWasCalled = false val promptDelegate = GeckoPromptDelegate(mockSession) @@ -949,72 +811,103 @@ class GeckoPromptDelegateTest { } }) - val callback = object : GeckoSession.PromptDelegate.ButtonCallback { - - override fun confirm(button: Int) { - when (button) { - BUTTON_TYPE_POSITIVE -> onPositiveButtonWasCalled = true - BUTTON_TYPE_NEGATIVE -> onNegativeButtonWasCalled = true - BUTTON_TYPE_NEUTRAL -> onNeutralButtonWasCalled = true - } - } - - override fun setCheckboxValue(value: Boolean) { - setCheckboxValueWasCalled = true - } - - override fun dismiss() { - dismissWasCalled = true - } - - override fun getCheckboxValue(): Boolean = false - override fun hasCheckbox(): Boolean = true - override fun getCheckboxMessage(): String = "" + var geckoResult = promptDelegate.onButtonPrompt(mock(), GeckoPromptPrompt()) + geckoResult!!.accept { + onPositiveButtonWasCalled = true } - promptDelegate.onButtonPrompt( - mock(), - "title", - "message", - arrayOf("positive", "neutral", "negative"), - callback - ) - - with(request!!) { + with(request) { assertNotNull(request) assertEquals(title, "title") assertEquals(message, "message") - assertEquals(hasShownManyDialogs, true) - assertEquals(positiveButtonTitle, "positive") - assertEquals(negativeButtonTitle, "negative") - assertEquals(neutralButtonTitle, "neutral") onConfirmPositiveButton(false) assertTrue(onPositiveButtonWasCalled) + } + + geckoResult = promptDelegate.onButtonPrompt(mock(), GeckoPromptPrompt()) + geckoResult!!.accept { + onNeutralButtonWasCalled = true + } - onConfirmNegativeButton(false) - assertTrue(onNegativeButtonWasCalled) + request.onConfirmNeutralButton(false) + assertTrue(onNeutralButtonWasCalled) - onConfirmNeutralButton(false) - assertTrue(onNeutralButtonWasCalled) + geckoResult = promptDelegate.onButtonPrompt(mock(), GeckoPromptPrompt()) + geckoResult!!.accept { + onNegativeButtonWasCalled = true + } - assertTrue(setCheckboxValueWasCalled) + request.onConfirmNegativeButton(false) + assertTrue(onNegativeButtonWasCalled) - onDismiss() - assertTrue(dismissWasCalled) + geckoResult = promptDelegate.onButtonPrompt(mock(), GeckoPromptPrompt()) + geckoResult!!.accept { + dismissWasCalled = true } + + request.onDismiss() + assertTrue(dismissWasCalled) } - open class DefaultGeckoChoiceCallback : GeckoSession.PromptDelegate.ChoiceCallback { - override fun confirm(items: Array?) = Unit - override fun dismiss() {} - override fun getCheckboxValue() = false - override fun setCheckboxValue(value: Boolean) = Unit - override fun hasCheckbox() = false - override fun getCheckboxMessage() = "" - override fun confirm(ids: Array) = Unit - override fun confirm(item: GeckoChoice) = Unit - override fun confirm(id: String?) = Unit + class GeckoChoicePrompt( + title: String, + message: String, + type: Int, + choices: Array + ) : GeckoSession.PromptDelegate.ChoicePrompt(title, message, type, choices) + + class GeckoAlertPrompt(title: String = "title", message: String = "message") : + GeckoSession.PromptDelegate.AlertPrompt(title, message) + + class GeckoDateTimePrompt( + title: String = "title", + type: Int, + defaultValue: String = "", + minValue: String = "", + maxValue: String = "" + ) : GeckoSession.PromptDelegate.DateTimePrompt(title, type, defaultValue, minValue, maxValue) + + class GeckoFilePrompt( + title: String = "title", + type: Int, + capture: Int = 0, + mimeTypes: Array = emptyArray() + ) : GeckoSession.PromptDelegate.FilePrompt(title, type, capture, mimeTypes) + + class GeckoAuthPrompt( + title: String = "title", + message: String = "message", + authOptions: AuthOptions + ) : GeckoSession.PromptDelegate.AuthPrompt(title, message, authOptions) + + class GeckoColorPrompt( + title: String = "title", + defaultValue: String = "defaultValue" + ) : GeckoSession.PromptDelegate.ColorPrompt(title, defaultValue) + + class GeckoTextPrompt( + title: String = "title", + message: String = "message", + defaultValue: String = "defaultValue" + ) : GeckoSession.PromptDelegate.TextPrompt(title, message, defaultValue) + + class GeckoPopupPrompt( + targetUri: String = "targetUri" + ) : GeckoSession.PromptDelegate.PopupPrompt(targetUri) + + class GeckoPromptPrompt( + title: String = "title", + message: String = "message" + ) : GeckoSession.PromptDelegate.ButtonPrompt(title, message) + + class GeckoAuthOptions : GeckoSession.PromptDelegate.AuthPrompt.AuthOptions() + + private fun GeckoSession.PromptDelegate.BasePrompt.getGeckoResult(): GeckoBundle { + val javaClass = GeckoSession.PromptDelegate.BasePrompt::class.java + val method = javaClass.getDeclaredMethod("ensureResult") + method.isAccessible = true + return (method.invoke(this) as GeckoBundle) } } diff --git a/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt b/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt index 7c815261847..c3347d1a733 100644 --- a/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt +++ b/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/media/GeckoMedia.kt @@ -26,6 +26,9 @@ internal class GeckoMedia( ) : Media() { override val controller: Controller = GeckoMediaController(mediaElement) + override var metadata: Metadata = Metadata() + internal set + init { mediaElement.delegate = MediaDelegate(this) } @@ -44,7 +47,7 @@ internal class GeckoMedia( } private class MediaDelegate( - private val media: Media + private val media: GeckoMedia ) : MediaElement.Delegate { @Suppress("ComplexMethod") override fun onPlaybackStateChange(mediaElement: MediaElement, mediaState: Int) { @@ -63,8 +66,11 @@ private class MediaDelegate( } } + override fun onMetadataChange(mediaElement: MediaElement, metaData: MediaElement.Metadata) { + media.metadata = Media.Metadata(metaData.duration) + } + override fun onReadyStateChange(mediaElement: MediaElement, readyState: Int) = Unit - override fun onMetadataChange(mediaElement: MediaElement, metaData: MediaElement.Metadata) = Unit override fun onLoadProgress(mediaElement: MediaElement, progressInfo: MediaElement.LoadProgressInfo) = Unit override fun onVolumeChange(mediaElement: MediaElement, volume: Double, muted: Boolean) = Unit override fun onTimeChange(mediaElement: MediaElement, time: Double) = Unit diff --git a/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt b/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt index 8874e790268..e0daaf2fafb 100644 --- a/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt +++ b/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/media/GeckoMediaTest.kt @@ -7,6 +7,7 @@ package mozilla.components.browser.engine.gecko.media import mozilla.components.concept.engine.media.Media import mozilla.components.support.test.argumentCaptor import mozilla.components.support.test.mock +import mozilla.components.test.ReflectionUtils import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test @@ -67,4 +68,38 @@ class GeckoMediaTest { assertTrue(media.controller is GeckoMediaController) } + + @Test + fun `GeckoMedia exposes Metadata`() { + val mediaElement: MediaElement = mock() + + val media = GeckoMedia(mediaElement) + + val captor = argumentCaptor() + verify(mediaElement).delegate = captor.capture() + + assertEquals(-1.0, media.metadata.duration, 0.0001) + + val delegate = captor.value + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = 5.0)) + assertEquals(5.0, media.metadata.duration, 0.0001) + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = 572.0)) + assertEquals(572.0, media.metadata.duration, 0.0001) + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = 0.0)) + assertEquals(0.0, media.metadata.duration, 0.0001) + + delegate.onMetadataChange(mediaElement, MockedGeckoMetadata(duration = -1.0)) + assertEquals(-1.0, media.metadata.duration, 0.0001) + } +} + +private class MockedGeckoMetadata( + duration: Double +) : MediaElement.Metadata() { + init { + ReflectionUtils.setField(this, "duration", duration) + } } diff --git a/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt b/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt index 07ce63a9abc..a499402fb81 100644 --- a/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt +++ b/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt @@ -58,7 +58,6 @@ import mozilla.components.concept.engine.request.RequestInterceptor.Interception import mozilla.components.concept.storage.VisitType import mozilla.components.support.ktx.android.view.getRectWithViewLocation import mozilla.components.support.utils.DownloadUtils -import java.util.Date /** * WebView-based implementation of EngineView. @@ -71,9 +70,6 @@ class SystemEngineView @JvmOverloads constructor( ) : FrameLayout(context, attrs, defStyleAttr), EngineView, View.OnLongClickListener { @VisibleForTesting(otherwise = PRIVATE) internal var session: SystemEngineSession? = null - internal var jsAlertCount = 0 - internal var shouldShowMoreDialogs = true - internal var lastDialogShownAt = Date() /** * Render the content of the given session. @@ -169,7 +165,6 @@ class SystemEngineView @JvmOverloads constructor( onNavigationStateChange(view.canGoBack(), view.canGoForward()) } } - resetJSAlertAbuseState() } override fun onPageFinished(view: WebView?, url: String?) { @@ -406,25 +401,17 @@ class SystemEngineView @JvmOverloads constructor( result.cancel() } - if (shouldShowMoreDialogs) { - - session.notifyObservers { - onPromptRequest( - PromptRequest.Alert( - title, - message ?: "", - areDialogsBeingAbused(), - onDismiss - ) { shouldNotShowMoreDialogs -> - shouldShowMoreDialogs = !shouldNotShowMoreDialogs - result.confirm() - }) - } - } else { - result.cancel() + session.notifyObservers { + onPromptRequest( + PromptRequest.Alert( + title, + message ?: "", + false, + onDismiss + ) { _ -> + result.confirm() + }) } - - updateJSDialogAbusedState() return true } @@ -443,72 +430,57 @@ class SystemEngineView @JvmOverloads constructor( result.cancel() } - val onConfirm: (Boolean, String) -> Unit = { shouldNotShowMoreDialogs, valueInput -> - shouldShowMoreDialogs = !shouldNotShowMoreDialogs + val onConfirm: (Boolean, String) -> Unit = { _, valueInput -> result.confirm(valueInput) } - if (shouldShowMoreDialogs) { - session.notifyObservers { - onPromptRequest( - PromptRequest.TextPrompt( - title, - message ?: "", - defaultValue ?: "", - areDialogsBeingAbused(), - onDismiss, - onConfirm - ) + session.notifyObservers { + onPromptRequest( + PromptRequest.TextPrompt( + title, + message ?: "", + defaultValue ?: "", + false, + onDismiss, + onConfirm ) - } - } else { - result.cancel() + ) } - updateJSDialogAbusedState() return true } override fun onJsConfirm(view: WebView?, url: String?, message: String?, result: JsResult): Boolean { val session = session ?: return applyDefaultJsDialogBehavior(result) val title = context.getString(R.string.mozac_browser_engine_system_alert_title, url ?: session.currentUrl) - val positiveButton = context.getString(android.R.string.ok) - val negativeButton = context.getString(android.R.string.cancel) val onDismiss: () -> Unit = { result.cancel() } - val onConfirmPositiveButton: (Boolean) -> Unit = { shouldNotShowMoreDialogs -> - shouldShowMoreDialogs = !shouldNotShowMoreDialogs + val onConfirmPositiveButton: (Boolean) -> Unit = { _ -> result.confirm() } - val onConfirmNegativeButton: (Boolean) -> Unit = { shouldNotShowMoreDialogs -> - shouldShowMoreDialogs = !shouldNotShowMoreDialogs + val onConfirmNegativeButton: (Boolean) -> Unit = { _ -> result.cancel() } - if (shouldShowMoreDialogs) { - session.notifyObservers { - onPromptRequest( - PromptRequest.Confirm( - title, - message ?: "", - areDialogsBeingAbused(), - positiveButton, - negativeButton, - "", - onConfirmPositiveButton, - onConfirmNegativeButton, - {}, - onDismiss - ) + session.notifyObservers { + onPromptRequest( + PromptRequest.Confirm( + title, + message ?: "", + false, + "", + "", + "", + onConfirmPositiveButton, + onConfirmNegativeButton, + {}, + onDismiss ) - } - } else { - result.cancel() + ) } - updateJSDialogAbusedState() return true } @@ -708,42 +680,11 @@ class SystemEngineView @JvmOverloads constructor( }, handler) } - private fun resetJSAlertAbuseState() { - jsAlertCount = 0 - shouldShowMoreDialogs = true - } - private fun applyDefaultJsDialogBehavior(result: JsResult?): Boolean { result?.cancel() return true } - internal fun updateJSDialogAbusedState() { - if (!areDialogsAbusedByTime()) { - jsAlertCount = 0 - } - ++jsAlertCount - lastDialogShownAt = Date() - } - - internal fun areDialogsBeingAbused(): Boolean { - return areDialogsAbusedByTime() || areDialogsAbusedByCount() - } - - internal fun areDialogsAbusedByTime(): Boolean { - return if (jsAlertCount == 0) { - false - } else { - val now = Date() - val diffInSeconds = (now.time - lastDialogShownAt.time) / SECOND_MS - diffInSeconds < MAX_SUCCESSIVE_DIALOG_SECONDS_LIMIT - } - } - - internal fun areDialogsAbusedByCount(): Boolean { - return jsAlertCount > MAX_SUCCESSIVE_DIALOG_COUNT - } - @Suppress("Deprecation") private fun WebView.getAuthCredentials(host: String, realm: String): Pair { val credentials = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { diff --git a/components/browser/engine-system/src/main/res/values-cs/strings.xml b/components/browser/engine-system/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..bc5b5608f0c --- /dev/null +++ b/components/browser/engine-system/src/main/res/values-cs/strings.xml @@ -0,0 +1,10 @@ + + + + Sdělení stránky %1$s: + + %2$s požaduje vaše uživatelské jméno a heslo. Sdělení serveru: „%1$s“ + + %1$s požaduje vaše uživatelské jméno a heslo. + diff --git a/components/browser/engine-system/src/main/res/values-es-rAR/strings.xml b/components/browser/engine-system/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..8f0dde846d6 --- /dev/null +++ b/components/browser/engine-system/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,10 @@ + + + + La página en %1$s dice: + + %2$s está pidiendo tu nombre de usuario y contraseña. El sitio dice: “%1$s” + + %1$s te está pidiendo tu nombre de usuario y contraseña. + diff --git a/components/browser/engine-system/src/main/res/values-fi/strings.xml b/components/browser/engine-system/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..af33a323c4f --- /dev/null +++ b/components/browser/engine-system/src/main/res/values-fi/strings.xml @@ -0,0 +1,10 @@ + + + + Sivu osoitteessa %1$s sanoo: + + %2$s pyytää käyttäjätunnusta ja salasanaa. Sivusto sanoo: ”%1$s” + + %1$s pyytää käyttäjätunnusta ja salasanaa. + diff --git a/components/browser/engine-system/src/main/res/values-pa-rIN/strings.xml b/components/browser/engine-system/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..59c19abe0c6 --- /dev/null +++ b/components/browser/engine-system/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,10 @@ + + + + %1$s ਸਫ਼ੇ ਤੋਂ: + + %2$s ਤੁਹਾਡੇ ਵਰਤੋਂਕਾਰ-ਨਾਂ ਅਤੇ ਪਾਸਵਰਡ ਦੀ ਮੰਗ ਕਰ ਰਹੀ ਹੈ। ਸਾਈਟ ਕਹਿੰਦੀ ਹੈ: “%1$s” + + %1$s ਤੁਹਾਡੇ ਵਰਤੋਂਕਾਰ-ਨਾਂ ਅਤੇ ਪਾਸਵਰਡ ਦੀ ਮੰਗ ਕਰ ਰਹੀ ਹੈ। + diff --git a/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt b/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt index 80df5b9a53e..8835d9642d5 100644 --- a/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt +++ b/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt @@ -29,8 +29,6 @@ import android.webkit.WebViewClient import android.webkit.WebViewDatabase import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.coroutines.runBlocking -import mozilla.components.browser.engine.system.SystemEngineView.Companion.MAX_SUCCESSIVE_DIALOG_COUNT -import mozilla.components.browser.engine.system.SystemEngineView.Companion.MAX_SUCCESSIVE_DIALOG_SECONDS_LIMIT import mozilla.components.browser.engine.system.matcher.UrlMatcher import mozilla.components.browser.errorpages.ErrorType import mozilla.components.concept.engine.EngineSession @@ -69,8 +67,6 @@ import org.robolectric.Robolectric import org.robolectric.RuntimeEnvironment import org.robolectric.annotation.Config import java.util.Calendar -import java.util.Calendar.SECOND -import java.util.Calendar.YEAR import java.util.Date @RunWith(AndroidJUnit4::class) @@ -1068,131 +1064,13 @@ class SystemEngineViewTest { assertTrue(request is PromptRequest.Alert) assertTrue(alertRequest.title.contains("mozilla.org")) - assertEquals(alertRequest.hasShownManyDialogs, false) assertEquals(alertRequest.message, "message") alertRequest.onConfirm(true) verify(mockJSResult).confirm() - assertEquals(engineView.jsAlertCount, 1) alertRequest.onDismiss() verify(mockJSResult).cancel() - - alertRequest.onConfirm(true) - assertEquals(engineView.shouldShowMoreDialogs, false) - - engineView.lastDialogShownAt = engineView.lastDialogShownAt.add(YEAR, -1) - engineSession.webView.webChromeClient!!.onJsAlert(mock(), "http://www.mozilla.org", "message", mockJSResult) - - assertEquals(engineView.jsAlertCount, 1) - verify(mockJSResult, times(2)).cancel() - - engineView.lastDialogShownAt = engineView.lastDialogShownAt.add(YEAR, -1) - engineView.jsAlertCount = 100 - engineView.shouldShowMoreDialogs = true - - engineSession.webView.webChromeClient!!.onJsAlert(mock(), "http://www.mozilla.org", null, mockJSResult) - - assertTrue((request as PromptRequest.Alert).hasShownManyDialogs) - - engineSession.currentUrl = "http://www.mozilla.org" - engineSession.webView.webChromeClient!!.onJsAlert(mock(), null, "message", mockJSResult) - assertTrue((request as PromptRequest.Alert).title.contains("mozilla.org")) - } - - @Test - fun `are dialogs by count`() { - val engineView = SystemEngineView(testContext) - - with(engineView) { - - assertFalse(areDialogsAbusedByCount()) - - jsAlertCount = MAX_SUCCESSIVE_DIALOG_COUNT + 1 - - assertTrue(areDialogsAbusedByCount()) - - jsAlertCount = MAX_SUCCESSIVE_DIALOG_COUNT - 1 - - assertFalse(areDialogsAbusedByCount()) - } - } - - @Test - fun `are dialogs by time`() { - val engineView = SystemEngineView(testContext) - - with(engineView) { - - assertFalse(areDialogsAbusedByTime()) - - lastDialogShownAt = Date() - - jsAlertCount = 1 - - assertTrue(areDialogsAbusedByTime()) - } - } - - @Test - fun `are dialogs being abused`() { - val engineView = SystemEngineView(testContext) - - with(engineView) { - - assertFalse(areDialogsBeingAbused()) - - jsAlertCount = MAX_SUCCESSIVE_DIALOG_COUNT + 1 - - assertTrue(areDialogsBeingAbused()) - - jsAlertCount = 0 - lastDialogShownAt = Date() - - assertFalse(areDialogsBeingAbused()) - - jsAlertCount = 1 - lastDialogShownAt = Date() - - assertTrue(areDialogsBeingAbused()) - } - } - - @Test - fun `update JSDialog abused state`() { - val engineView = SystemEngineView(testContext) - - with(engineView) { - val thresholdInSeconds = MAX_SUCCESSIVE_DIALOG_SECONDS_LIMIT + 1 - lastDialogShownAt = lastDialogShownAt.add(SECOND, -thresholdInSeconds) - - val initialDate = lastDialogShownAt - updateJSDialogAbusedState() - - assertEquals(jsAlertCount, 1) - assertTrue(lastDialogShownAt.after(initialDate)) - - lastDialogShownAt = lastDialogShownAt.add(SECOND, -thresholdInSeconds) - updateJSDialogAbusedState() - assertEquals(jsAlertCount, 1) - } - } - - @Test - fun `js alert abuse state must be reset every time a page is started`() { - val engineSession = SystemEngineSession(testContext) - val engineView = SystemEngineView(testContext) - - with(engineView) { - jsAlertCount = 20 - shouldShowMoreDialogs = false - - render(engineSession) - engineSession.webView.webViewClient!!.onPageStarted(mock(), "www.mozilla.org", null) - - assertEquals(jsAlertCount, 0) - assertTrue(shouldShowMoreDialogs) - } } @Test @@ -1229,48 +1107,11 @@ class SystemEngineViewTest { textPromptRequest.onConfirm(true, "value") verify(mockJSPromptResult).confirm("value") - assertEquals(engineView.jsAlertCount, 1) textPromptRequest.onDismiss() verify(mockJSPromptResult).cancel() textPromptRequest.onConfirm(true, "value") - assertEquals(engineView.shouldShowMoreDialogs, false) - - engineView.lastDialogShownAt = engineView.lastDialogShownAt.add(YEAR, -1) - engineSession.webView.webChromeClient!!.onJsPrompt( - mock(), - "http://www.mozilla.org", - "message", "defaultValue", - mockJSPromptResult - ) - - assertEquals(engineView.jsAlertCount, 1) - verify(mockJSPromptResult, times(2)).cancel() - - engineView.lastDialogShownAt = engineView.lastDialogShownAt.add(YEAR, -1) - engineView.jsAlertCount = 100 - engineView.shouldShowMoreDialogs = true - - engineSession.webView.webChromeClient!!.onJsPrompt( - mock(), - "http://www.mozilla.org", - null, - null, - mockJSPromptResult - ) - - assertTrue((request as PromptRequest.TextPrompt).hasShownManyDialogs) - - engineSession.currentUrl = "http://www.mozilla.org" - engineSession.webView.webChromeClient!!.onJsPrompt( - mock(), - null, - "message", - "defaultValue", - mockJSPromptResult - ) - assertTrue((request as PromptRequest.TextPrompt).title.contains("mozilla.org")) } @Test @@ -1332,54 +1173,15 @@ class SystemEngineViewTest { assertTrue(confirmPromptRequest.title.contains("mozilla.org")) assertEquals(confirmPromptRequest.hasShownManyDialogs, false) assertEquals(confirmPromptRequest.message, "message") - assertEquals(confirmPromptRequest.positiveButtonTitle.toLowerCase(), "OK".toLowerCase()) - assertEquals(confirmPromptRequest.negativeButtonTitle.toLowerCase(), "Cancel".toLowerCase()) confirmPromptRequest.onConfirmPositiveButton(true) verify(mockJSPromptResult).confirm() - assertEquals(engineView.jsAlertCount, 1) confirmPromptRequest.onDismiss() verify(mockJSPromptResult).cancel() confirmPromptRequest.onConfirmNegativeButton(true) verify(mockJSPromptResult, times(2)).cancel() - - confirmPromptRequest.onConfirmPositiveButton(true) - assertEquals(engineView.shouldShowMoreDialogs, false) - - engineView.lastDialogShownAt = engineView.lastDialogShownAt.add(YEAR, -1) - engineSession.webView.webChromeClient!!.onJsConfirm( - mock(), - "http://www.mozilla.org", - "message", - mockJSPromptResult - ) - - assertEquals(engineView.jsAlertCount, 1) - verify(mockJSPromptResult, times(3)).cancel() - - engineView.lastDialogShownAt = engineView.lastDialogShownAt.add(YEAR, -1) - engineView.jsAlertCount = 100 - engineView.shouldShowMoreDialogs = true - - engineSession.webView.webChromeClient!!.onJsConfirm( - mock(), - "http://www.mozilla.org", - null, - mockJSPromptResult - ) - - assertTrue((request as PromptRequest.Confirm).hasShownManyDialogs) - - engineSession.currentUrl = "http://www.mozilla.org" - engineSession.webView.webChromeClient!!.onJsConfirm( - mock(), - null, - "message", - mockJSPromptResult - ) - assertTrue((request as PromptRequest.Confirm).title.contains("mozilla.org")) } @Test diff --git a/components/browser/errorpages/src/main/res/values-ca/strings.xml b/components/browser/errorpages/src/main/res/values-ca/strings.xml new file mode 100644 index 00000000000..780fa516978 --- /dev/null +++ b/components/browser/errorpages/src/main/res/values-ca/strings.xml @@ -0,0 +1,13 @@ + + + + + Torna-ho a provar + + + El port s\'ha restringit per motius de seguretat + + + L’adreça no és vàlida + + diff --git a/components/browser/errorpages/src/main/res/values-cs/strings.xml b/components/browser/errorpages/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..fd3f67d78ff --- /dev/null +++ b/components/browser/errorpages/src/main/res/values-cs/strings.xml @@ -0,0 +1,259 @@ + + + + Chyba při načítání stránky + + + Zkusit znovu + + + Přejít zpět + + + Nepodařilo se dokončit požadavek + + Další informace o této chybě nejsou bohužel dostupné.

+ ]]>
+ + + Chyba zabezpečeného spojení + + +
  • Požadovanou stránku nelze zobrazit, protože nelze ověřit autenticitu přijatých dat.
  • +
  • Kontaktujte prosím vlastníky webového serveru a informujte je o tomto problému.
  • + + ]]>
    + + + Chyba zabezpečeného spojení + + +
  • Tato chyba může být způsobena chybnou konfigurací serveru nebo někým, +kdo se snaží vydávat za server.
  • +
  • Pokud jste se k tomuto serveru připojili úspěšně již v minulosti, je možná chyba jenom dočasná, a můžete to zkusit znovu později.
  • + + ]]>
    + + + Spojení bylo přerušeno + + Podařilo se připojit k serveru, ale spojení bylo v průběhu přenosu přerušeno. Opakujte akci.

    +
      +
    • Stránka může být dočasně nedostupná nebo zaneprázdněná. Zkuste to znovu za pár okamžiků.
    • +
    • Pokud nemůžete načíst žádnou stránku, zkontrolujte svá mobilní data nebo Wi-Fi připojení.
    • +
    + ]]>
    + + + Vypršel čas spojení + + Požadovaný server neodpověděl na požadavek o připojení a prohlížeč ukončil čekání na tuto odpověď.

    +
      +
    • Server může být velmi vytížen; Opakujte akci později.
    • Je možné, že se jedná o síťový problém mezi vaším počítačem a serverem.
    • +
    • Pokud problém přetrvává, poraďte se se správcem vaší sítě, nebo poskytovatelem připojení k internetu.
    • +
    + ]]>
    + + + Nelze se připojit + + +
  • Stránka může být dočasně nedostupná nebo zaneprázdněná. Zkuste to znovu za pár okamžiků.
  • +
  • Pokud nemůžete načíst žádnou stránku, zkontrolujte svá mobilní data nebo Wi-Fi připojení.
  • + + ]]>
    + + + Neplatná odpověď serveru + + Server odpověděl na požadavek neočekávaným způsobem a prohlížeč tak nemohl pokračovat.

    + ]]>
    + + + Smyčka při přesměrování + + Prohlížeč ukončil spojení, protože server přesměrovává požadavky na tuto adresu sám na sebe, a to takovým způsobem, který zabraňuje jejich dokončení.

    +
      +
    • Je možné, že stránka vyžaduje ukládání cookies, které máte zakázané nebo je pro tento server blokujete.
    • +
    • Většinou se ale jedná o problém konfigurace serveru a není to tak problém vašeho počítače.
    • +
    + ]]>
    + + + Režim offline + + Prohlížeč je teď v režimu offline a k požadované položce se nelze připojit.

    +
      +
    • Je počítač připojen k funkční síti?
    • +
    • Pro přechod do režimu online a obnovení stránky klepněte na tlačítko „Zkusit znovu“.
    • +
    + ]]>
    + + + Omezení přístupu na port + + V požadované adrese (URL) byl zadán port (např. mozilla.org:80 pro port 80 na serveru mozilla.org), který se obvykle používá pro jiné internetové služby než je prohlížení webových stránek. Prohlížeč zrušil požadavek z důvodů vaší ochrany.

    + ]]>
    + + + Spojení přerušeno + + Spojení bylo v průběhu otevírání komunikačního kanálu se serverem neočekávaně přerušeno. Opakujte akci.

    +
      +
    • Server je dočasně nedostupný. Zkuste to prosím znovu za chvíli.
    • +
    • Pokud nemůžete načíst žádnou stránku, zkontrolujte svá mobilní data nebo Wi-Fi připojení.
    • +
    + ]]>
    + + + Nebezpečný typ souboru + + +
  • Kontaktujte prosím vlastníky webového serveru a informujte je o tomto problému.
  • + + ]]>
    + + + Chyba v obsahu stránky + + Požadovanou stránku nelze zobrazit, protože při přenosu dat došlo k chybě.

    +
      +
    • Kontaktujte prosím vlastníky webového serveru a informujte je o tomto problému.
    • +
    + ]]>
    + + + Pád obsahu + Požadovanou stránku nelze zobrazit, protože při přenosu dat došlo k chybě.

    +
      +
    • Kontaktujte prosím vlastníky webového serveru a informujte je o tomto problému.
    • +
    + ]]>
    + + + Chyba znakové sady obsahu + Požadovanou stránku nelze zobrazit, protože používá neplatný či nepodporovaný způsob komprese dat.

    +
      +
    • Kontaktujte prosím vlastníky webového serveru a informujte je o tomto problému.
    • +
    + ]]>
    + + + Adresa nenalezena + + URL adresa neodpovídá známému serveru a nelze ji načíst.

    +
      +
    • Zkontrolujte prosím, že jste adresu napsali správně (např. že neobsahuje + ww.example.com místo www.example.com
    • +
    • Pokud nemůžete načíst žádnou stránku, zkontrolujte svá mobilní data nebo Wi-Fi připojení.
    • +
    + ]]>
    + + + Neplatná adresa + Adresa (URL) není platná a nelze ji načíst. Zkontrolujte prosím, že je adresa napsána správně.

    + ]]>
    + + Neplatná adresa + + +
  • Webové adresy jsou obvykle psány jako http://www.example.com/
  • +
  • Ujistěte se, že používáte běžná lomítka (tj. /).
  • + + ]]>
    + + + Neznámý protokol + Adresu (URL) určuje protokol (např. wxyz://), který nebyl prohlížečem rozpoznán, a proto se k ní nemůže korektně připojit.

    +
      +
    • Zkoušíte přistupovat k multimédiím či jiné netextové službě? Podívejte se, jaké další věci stránka vyžaduje.
    • +
    • Některé protokoly mohou vyžadovat software třetích stran nebo zásuvné moduly dříve, než je prohlížeč může rozpoznat.
    • +
    + ]]>
    + + + Soubor nenalezen + +
  • Je možné, že byl smazán, přejmenován nebo přesunut.
  • +
  • Zkontrolujte prosím, že je adresa napsána správně, a to včetně velikosti písmen.
  • +
  • Jste-li autorem tohoto souboru, ověřte, že daný soubor na serveru existuje a že má příslušná práva na zobrazení.
  • + + ]]>
    + + + Přístup k souboru byl odepřen + +
  • Možná byl smazán, přesunut nebo jeho oprávnění zabraňují přístupu.
  • + + ]]>
    + + + Proxy server odmítl spojení + Prohlížeč je nakonfigurován k použití proxy serveru, který odmítl spojení.

    +
      +
    • Zkontrolujte v prohlížeči nastavení proxy serveru a opakujte akci.
    • +
    • Je možné, že proxy server nepovoluje připojení z vaší sítě.
    • +
    • Pokud problém přetrvává, poraďte se se správcem vaší sítě, nebo poskytovatelem připojení k internetu.
    • +
    + ]]>
    + + + Proxy server nenalezen + Prohlížeč je nakonfigurován k použití proxy serveru, který nemohl být nalezen.

    +
      +
    • Zkontrolujte v prohlížeči nastavení proxy serveru a opakujte akci.
    • +
    • Pokud problém přetrvává, poraďte se se správcem vaší sítě, nebo poskytovatelem připojení k internetu.
    • +
    + ]]>
    + + + Problém se škodlivým softwarem + + Stránka %1$s byla nahlášena jako útočná a byla zablokována na základě vašeho bezpečnostního nastavení.

    + ]]>
    + + + Problém s nežádoucí webovou stránkou + + Stránka %1$s byla nahlášena jako stránka s nežádoucím softwarem a byla zablokována na základě vašeho bezpečnostního nastavení.

    + ]]>
    + + + Problém se škodlivou stránkou + + Stránka %1$s byla nahlášena jako útočná a byla zablokována na základě vašeho bezpečnostního nastavení.

    + ]]>
    + + + Problém s klamavou stránkou + + Tato webová stránka na serveru %1$s byla nahlášena jako klamavá a byla zablokována na základě vašeho bezpečnostního nastavení.

    + ]]>
    +
    diff --git a/components/browser/errorpages/src/main/res/values-es-rAR/strings.xml b/components/browser/errorpages/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..96029c6568a --- /dev/null +++ b/components/browser/errorpages/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,229 @@ + + + + Problema al cargar la página + + + Probar de nuevo + + + Retroceder + + + No se puede completar el pedido + + En este momento no hay información adicional disponible para este problema o error.

    + ]]>
    + + + Falló la conexión segura + + +
  • La página que estás intentando ver no se puede mostrar porque no se pudo verificar la autenticidad de los datos recibidos.
  • +
  • Por favor contactate con los propietarios del sitio web para informarles de este problema.
  • + ]]>
    + + + Falló la conexión segura + + +
  • Esto podría ser un problema con la configuración del servidor o podría ser alguien tratando de hacerse pasar por el servidor.
  • +
  • Si te conectaste sin problemas a este servidor en el pasado, el error puede ser temporal y podés probar de nuevo más tarde.
  • + +]]>
    + + + Se interrumpió la conexión + + El navegador se conectó con éxito, pero se interrumpió la conexión mientras se transfería la información. Volvé a probar.

    +
      +
    • El sitio podría no estar disponible temporalmente o estar demasiado ocupado. Volvé a probar en unos minutos.
    • +
    • Si no podés cargar ninguna página, revisa la conexión wifi o de datos de tu dispositivo móvil.
    • +
    + ]]>
    + + + La conexión tardó demasiado tiempo + + El sitio solicitado no respondió a una pedido de conexión y el navegador dejó de esperar una respuesta.

    +
      +
    • ¿El servidor podría estar experimentando una alta demanda o un corte temporal? Volvé a probar más tarde.
    • +
    • ¿No podés navegar por otros sitios? Comprobá la conexión de red del equipo.
    • +
    • ¿Tu red o equipo está protegido por un firewall o un proxy? Una configuración incorrecta puede interferir con la navegación web.
    • +
    • ¿Todavía tenés problemas? Consultá con el administrador de la red o el proveedor de Internet para obtener asistencia técnica.
    • +
    + ]]>
    + + + No se puede conectar + + + +
  • El sitio puede estar temporariamente inaccesible o demasiado ocupado. Intentá nuevamente en un rato.
  • +
  • Si no podés cargar ninguna página, verificá la conexión de datos o Wi-Fi de tu dispositivo.
  • + ]]>
    + + + Respuesta inesperada del servidor + + El sitio respondió al pedido de la red de una forma inesperada y el navegador no puede continuar.

    ]]>
    + + + La página no se redirecciona correctamente + + + El navegador dejó de tratar de transferir el ítem solicitado. El sitio está redirigiendo el pedido en una manera que nunca se completará.

    +
      +
    • ¿Deshabilitaste o bloqueaste cookies requeridas por este sitio?
    • +
    • Si aceptar las cookies del sitio no resuelve el problema, seguramente es un problema de configuración del servidor y no de tu computadora.
    • + +
    + ]]>
    + + + Modo sin conexión + + + El navegador está funcionando en el modo sin conexión y no puede conectarse al ítem solicitado.

    • ¿La computadora está conectada a una red activa?
    • Presioná “Intentar de nuevo” para volver al modo con conexión y recargar la página.
    ]]>
    + + + Restricción del puerto por razones de seguridad + + La dirección solicitada especificaba un puerto (p. ej., mozilla.org:80 para el puerto 80 de mozilla.org) que suele usarse para propósitos distintos a navegar por Internet. El navegador canceló la solicitud para tu protección y seguridad.

    + ]]>
    + + + Se restableció la conexión + + + ]]> + + + Tipo de archivo no seguro + + + +
  • Contactate con los propietarios del sitio web para informarles de este problema.
  • + + ]]>
    + + + Error de contenido corrupto + + + La página que estás intentando ver no puede mostrarse porque se detectó un error en la transmisión de los datos.

    +
      +
    • Contactate con los propietarios del sitio web para informarles de este problema.
    • +
    + ]]>
    + + + El contenido falló + + La página que estás tratando de ver no puede ser mostrada porque se detectó un error en la transmisión de datos.

    +
      +
    • Contactá a los dueños del sitio web para informarles sobre este problema.
    • +
    + ]]>
    + + + Error de codificación de contenido + + La página que estás tratando de ver no puede mostrarse porque usa una forma de compresión inválida o no soportada.

    +
      +
    • Contactá a los dueños del sitio web para informarles sobre este problema.
    • + +
    + ]]>
    + + + No se encontró la dirección + + + El navegador no pudo encontrar el servidor de la dirección provista.

    +
      +
    • Verificá si la dirección no tiene errores de tipeo como + ww.example.com en lugar de + www.example.com.
    • +
    • Si no podés cargar ninguna página, verificá la conexión de datos o Wi-Fi de tu dispositivo.
    • +
    + ]]>
    + + + La dirección no es válida + La dirección provista no tiene un formato reconocible. Mirá si no hay errores en la barra de direcciones e intentá nuevamente.

    + ]]>
    + + La dirección no es válida + + + +
  • Usualmente las direcciones web se escriben como http://www.example.com/
  • +
  • Asegurate de estar usando las barras correctas (ej: /).
  • + + ]]>
    + + + Protocolo desconocido + + La dirección especifica un protocolo (ej: wxyz://) que el navegador no reconoce, así que no puede conectarse adecuadamente al sitio.

    +
      +
    • ¿Estás tratando de acceder a multimedia o a otros servicios que no son de texto? Verifiá el sitio para requerimientos extra.
    • +
    • Algunos protocolos pueden requerir software de terceros o plugins antes que el navegador pueda reconocerlos.
    • +
    + ]]>
    + + + Archivo no encontrado + + +
  • ¿Puede ser que el ítem haya sido renombrado, removido o reubicado?
  • +
  • ¿Hay un error de ortografía, mayúsculas o algún error tipográfico en la dirección?
  • +
  • ¿Tenés suficientes permisos de acceso al ítem solicitado?
  • + + ]]>
    + + + Se denegó el acceso al archivo + + +
  • Puede haber sido eliminado, movido o los permisos pueden evitar el acceso.
  • + + ]]>
    + + + El servidor proxy rechazó la conexión + + + No se encontró el servidor proxy + + El navegador está configurado para usar un servidor proxy, pero el proxy no se encontró el servidor.

    • ¿La configuración del proxy del navegador es correcta? Verificá la configuración y probá de nuevo.
    • ¿La computadora está conectada a una red activa?
    • ¿Todavía tenés problemas? Consultá con tu administrador de red o tu proveedor de Internet para recibir asistencia.
    ]]>
    + + + Problema del sitio con contenido malicioso + + + Problema de sitio no deseado + + + Problema de sitio dañino + + + El sitio es engañoso +
    diff --git a/components/browser/errorpages/src/main/res/values-eu/strings.xml b/components/browser/errorpages/src/main/res/values-eu/strings.xml index 04975de73bc..cf27173a0b9 100644 --- a/components/browser/errorpages/src/main/res/values-eu/strings.xml +++ b/components/browser/errorpages/src/main/res/values-eu/strings.xml @@ -42,6 +42,15 @@ Konexioa eten egin da + + Nabigatzaileak konexioa ondo sortu du, baina datuak jasotzen ari zela transferentzia eten egin da. Mesedez, saiatu berriro.

    +
      +
    • Gunea une batez desgaituta edo oso lanpetuta egon daiteke. Saiatu berriro minutu batzuen buruan.
    • +
    • Ezin baduzu beste orririk kargatu, egiaztatu zure gailuaren datu- edo WiFi-konexioa.
    • +
    + ]]>
    + Konexioaren denbora-muga gainditu da @@ -107,6 +116,15 @@ Konexioa berrezarri egin da + + Sareko lotura eten egin da konexioa negoziatzerakoan. Mesedez saiatu berriro.

    +
      +
    • Gunea une batez desgaituta edo oso lanpetuta egon daiteke. Saiatu berriro minutu batzuen buruan.
    • +
    • Ezin baduzu beste orririk kargatu, egiaztatu zure gailuaren datu- edo WiFi-konexioa.
    • +
    + ]]>
    + Fitxategi mota ez-segurua @@ -127,6 +145,8 @@ ]]> + + Edukiak huts egin du Ikusten saiatzen ari zaren orria ezin da erakutsi errore bat detektatu delako datu-transmisioan.

      @@ -147,6 +167,15 @@ Helbidea ez da aurkitu + + Nabigatzaileak ezin du ostalariko zerbitzaria aurkitu emandako helbidean.

      +
        +
      • Helbidea ondo begiratu mota honetako erroreak ekiditeko: ww.adibidea.eus www.adibidea.eus-en ordez.
      • +
      • Ezin baduzu inolako orririk kargatu, begiratu zure gailuaren datu- edo WiFi-konexioa.
      • +
      + ]]>
      + Helbide baliogabea + + + Ongelma sivua ladatessa + + + Yritä uudelleen + + + Siirry takaisin + + + Pyyntöä ei voi suorittaa + + + Suojattu yhteys epäonnistui + + + Suojattu yhteys epäonnistui + + + Yhteys keskeytettiin + + + Yhteys aikakatkaistiin + + + Yhdistäminen ei onnistu + + + Odottamaton vastaus palvelimelta + + + Yhteydetön tila + + + Sisältö kaatui + + + Osoitetta ei löytynyt + + + Virheellinen osoite + + Osoite ei ole kelvollinen + + + Tiedostoa ei löydy + + + Välityspalvelinta ei löytynyt + + diff --git a/components/browser/errorpages/src/main/res/values-in/strings.xml b/components/browser/errorpages/src/main/res/values-in/strings.xml index 684c1037381..f34a663fbea 100644 --- a/components/browser/errorpages/src/main/res/values-in/strings.xml +++ b/components/browser/errorpages/src/main/res/values-in/strings.xml @@ -32,15 +32,35 @@ Sambungan Aman Gagal + + +
    • Mungkin terjadi masalah dengan konfigurasi server, atau bisa saja seseorang berusaha menyamar menjadi server.
    • +
    • Jika Anda pernah tersambung dengan baik, kesalahan ini mungkin hanya sementara dan Anda dapat mencoba lagi nanti.
    • +
    + ]]>
    + Sambungan terputus + + Peramban terhubung dengan sukses, namun koneksi terganggu saat mentransfer informasi. Silakan coba lagi.

    +
      +
    • Situs ini mungkin sementara tidak sedia atau sedang sibuk. Coba lagi dalam beberapa saat.
    • +
    • Jika Anda tidak dapat memuat laman apapun, periksa koneksi data atau Wi-Fi pada perangkat Anda.
    • +
    + ]]>
    + Tenggang waktu tersambung habis Tidak dapat tersambung + + Respon tidak terduga dari server + Laman tidak teralihkan dengan benar @@ -67,6 +87,9 @@ ]]> + + Konten macet + Kesalahan Pengodean Isi (Content Encoding) @@ -105,6 +128,12 @@ Masalah situs malware + + Masalah situs yang tidak diinginkan + + + Masalah situs berbahaya + Masalah situs tipuan diff --git a/components/browser/errorpages/src/main/res/values-pa-rIN/strings.xml b/components/browser/errorpages/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..fc363e8091f --- /dev/null +++ b/components/browser/errorpages/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,85 @@ + + + + ਸਫ਼ਾ ਲੋਡ ਕਰਨ ‘ਚ ਸਮੱਸਿਆ + + + ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰੋ + + + ਪਿੱਛੇ ਜਾਓ + + + ਬੇਨਤੀ ਪੂਰੀ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ + + + ਇਸ ਸਮੱਸਿਆ ਬਾਰੇ ਵਧੀਕ ਜਾਣਕਾਰੀ ਜਾਂ ਗਲਤੀ ਇਸ ਵੇਲੇ ਉਪਲਬੱਧ ਨਹੀਂ ਹੈ।

    + ]]>
    + + + ਸੁਰੱਖਿਅਤ ਕਨੈਕਸ਼ਨ ਅਸਫ਼ਲ ਹੈ + + + ਸੁਰੱਖਿਅਤ ਕਨੈਕਸ਼ਨ ਅਸਫ਼ਲ ਹੈ + + + ਕਨੈਕਸ਼ਨ ‘ਚ ਰੁਕਾਵਟ ਆਈ ਸੀ + + + ਕਨੈਕਸ਼ਨ ਲਈ ਸਮਾਂ ਸਮਾਪਤ ਹੈ + + + ਕਨੈਕਟ ਕਰਨ ਲਈ ਅਸਮਰੱਥ ਹੈ + + + ਸਰਵਰ ਤੋਂ ਅਣਚਿਤਵਿਆ ਜਵਾਬ ਮਿਲਿਆ + + + ਸਫ਼ੇ ਲਈ ਠੀਕ ਤਰ੍ਹਾਂ ਮੁੜ-ਦਿਸ਼ਾ ਪਰਿਵਰਤਨ ਨਹੀਂ ਕੀਤਾ ਗਿਆ + + + ਆਫ਼ਲਾਈਨ ਢੰਗ + + + ਸੁਰੱਖਿਆ ਕਾਰਨਾਂ ਕਰਕੇ ਪੋਰਟ ਉੱਤੇ ਪਾਬੰਦੀ ਲਗਾਈ + + + ਕਨੈਕਸ਼ਨ ਮੁੜ-ਸੈੱਟ ਕੀਤਾ ਗਿਆ ਸੀ + + + ਅਸੁਰੱਖਿਅਤ ਫਾਈਲ ਕਿਸਮ + + +
  • ਇਸ ਸਮੱਸਿਆ ਬਾਰੇ ਜਾਣਕਾਰੀ ਦੇਣ ਲਈ ਵੈੱਬਸਾਈਟ ਦੇ ਮਾਲਕਾਂ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।
  • + + ]]>
    + + + ਨਿਕਾਰਾ ਹੋਈ ਦੀ ਸਮੱਗਰੀ ਗਲਤੀ + + + ਸਮੱਗਰੀ ਕਰੈਸ਼ ਹੋਈ + + + ਸਮੱਗਰੀ ਇੰਕੋਡਿੰਗ ਗਲਤੀ + + + ਸਿਰਨਾਵਾਂ ਨਹੀਂ ਲੱਭਿਆ + + + ਅਢੁੱਕਵਾਂ ਸਿਰਨਾਵਾਂ + + ਸਿਰਨਾਵਾਂ ਢੁੱਕਵਾਂ ਨਹੀਂ ਹੈ + + + ਅਣਪਛਾਤਾ ਪਰੋਟੋਕਾਲ + + + ਫਾਈਲ ਨਹੀਂ ਲੱਭੀ + + + ਫਾਈਲ ਲਈ ਪਹੁੰਚ ਤੋਂ ਨਾਂਹ ਕੀਤੀ + +
    diff --git a/components/browser/errorpages/src/main/res/values-sk/strings.xml b/components/browser/errorpages/src/main/res/values-sk/strings.xml index 8ca38fb60d6..c0ea52fca6b 100644 --- a/components/browser/errorpages/src/main/res/values-sk/strings.xml +++ b/components/browser/errorpages/src/main/res/values-sk/strings.xml @@ -39,6 +39,15 @@ Pripojenie bolo prerušené + + Prehliadač sa úspešne pripojil k serveru, ale spojenie bolo v priebehu prenosu údajov prerušené. Prosím, skúste to znova.

    +
      +
    • Stránka môže byť dočasne nedostupná alebo zaneprázdnená. Skúste to znova neskôr.
    • +
    • Ak sa vám nedarí načítať žiadnu stránku, skontrolujte pripojenie svojho zariadenia na internet.
    • +
    + ]]>
    + Čas pripojenia vypršal @@ -85,12 +94,35 @@ Režim offline + + Prehliadač je momentálne v režime offline a nemôže sa pripojiť na požadovaný server.

    +
      +
    • Je počítač pripojený k aktívnej sieti?
    • +
    • Kliknutím na tlačidlo „Skúsiť znova“ prejdete do režimu online a opätovne načítate obsah stránky.
    • +
    + ]]>
    + Bezpečnostné obmedzenie prístupu na port + + Zadaná adresa (URL) špecifikovala port (napr. mozilla.org:80 je port 80 na mozilla.org), ktorý je normálne určený na iné služby ako prehliadanie webu. Prehliadač požiadavku kvôli vašej ochrane a bezpečnosti neakceptoval.

    + ]]>
    + Výpadok pripojenia + + Spojenie bolo v priebehu otvárania komunikačného kanála so serverom nečakane prerušené. Skúste to znova

    +
      +
    • Stránka môže byť dočasne nedostupná alebo zaneprázdnená. Svoj pokus opakujte neskôr.
    • +
    • Ak sa nedá načítať žiadna stránka, skontrolujte pripojenie svojho zariadenia k internetu.
    • +
    + ]]>
    + Nebezpečný typ obsahu @@ -104,33 +136,144 @@ Poškodený obsah stránky + + Táto stránka nemohla byť zobrazená kvôli chybe pri prenose údajov.

    +
      +
    • Kontaktujte prevádzkovateľa webovej stránky a informujte ho o tomto probléme.
    • +
    + ]]>
    + Obsah zlyhal + Táto stránka nemohla byť zobrazená kvôli chybe pri prenose údajov.

    +
      +
    • Kontaktujte prevádzkovateľa webovej stránky a informujte ho o probléme.
    • +
    + ]]>
    + Chyba kódovania obsahu + Stránka nemôže byť zobrazená, pretože používa neplatné alebo nepodporované formátovanie.

    +
      +
    • Prosím, kontaktujte majiteľov stránky a informujte ich o tomto probléme.
    • +
    + ]]>
    + Adresa sa nenašla + + URL adresa nezodpovedá žiadnemu serveru a nie je možné ju načítať.

    +
      +
    • Skontrolujte, či ste adresu napísali správne (napr. že neobsahuje + ww.example.com namiesto + www.example.com).
    • +
    • Ak nemôžete načítať žiadnu stránku, skontrolujte pripojenie svojho zariadenia k internetu.
    • +
    + ]]>
    + Neplatná adresa + Adresa (URL) nie je platná a nemožno ju načítať. Prosím, skontrolujte text v paneli s adresou a skúste to znova.

    + ]]>
    Adresa nie je platná + + +
  • Webové adresy sú zvyčajne zadávané v tvare http://www.example.com/
  • +
  • Skontrolujte, či používate správne lomky (t.j. /).
  • + + ]]>
    + Neznámy protokol + Adresa sa začína protokolom, ktorý prehliadač nepozná. Protokol je reťazec na začiatku adresy, ako napríklad https: alebo ftp:, ktorý hovorí prehliadaču, ako sa má pripojiť ku serveru..

    +
      +
    • Chcete sa pripojiť k multimédiám alebo iným netextovým službám?
    • +
    • Niektoré protokoly vyžadujú softvér tretích strán alebo doplnky.
    • +
    + ]]>
    + Súbor nebol nájdený + +
  • Je možné, že bol odstránený, premenovaný alebo premiestnený?
  • +
  • Skontrolujte, či má adresa správny formát a či neobsahuje chyby.
  • +
  • Máte príslušné povolenia na zobrazenie daného súboru?
  • + + ]]>
    + Prístup k súboru bol zamietnutý + +
  • Mohol byť odstránený, premiestnený alebo vám v prístupe bránia oprávnenia.
  • + + ]]>
    + Proxy server odmietol spojenie + Prehliadač je nakonfigurovaný na používanie proxy servera, no tento odmietol pripojenie.

    +
      +
    • Skontrolujte nastavenia proxy servera v prehliadači a skúste to znova.
    • +
    • Má služba proxy povolený prístup k sieti?
    • +
    • Ak problémy pretrvávajú, kontaktujte, prosím, svojho správcu siete alebo poskytovateľa internetu.
    • +
    + ]]>
    + Proxy server nenájdený - + Prehliadač je nakonfigurovaný na používanie proxy servera, no tento odmietol pripojenie.

    +
      +
    • Skontrolujte nastavenia proxy servera v prehliadači a skúste to znova.
    • +
    • Je zariadenie pripojené k aktívnej sieti?
    • +
    • Ak problémy pretrvávajú, kontaktujte, prosím, svojho správcu siete alebo poskytovateľa internetu.
    • +
    + ]]>
    + + + Stránka so škodlivým softvérom + + Stránka %1$s bola označená ako nebezpečná a na základe nastavení zabezpečenia bola zablokovaná.

    + ]]>
    + + + Nežiadúca webová stránka + + Stránka %1$s bola označená ako ponúkajúca nevyžiadaný softvér a na základe nastavení zabezpečenia bola zablokovaná.

    + ]]>
    + + + Škodlivá stránka + + Stránka %1$s bola označená ako nebezpečná a na základe nastavení zabezpečenia bola zablokovaná.

    + ]]>
    + + + Podvodná stránka + + Stránka %1$s bola označená ako podvodná a na základe nastavení zabezpečenia bola zablokovaná.

    + ]]>
    + diff --git a/components/browser/menu/src/main/res/layout/mozac_browser_menu_item_toolbar.xml b/components/browser/menu/src/main/res/layout/mozac_browser_menu_item_toolbar.xml index b78bc59b1c2..00897559de7 100644 --- a/components/browser/menu/src/main/res/layout/mozac_browser_menu_item_toolbar.xml +++ b/components/browser/menu/src/main/res/layout/mozac_browser_menu_item_toolbar.xml @@ -5,6 +5,6 @@ diff --git a/components/browser/menu/src/main/res/values/dimens.xml b/components/browser/menu/src/main/res/values/dimens.xml index 8cd2f161c45..bc14dc8e1a0 100644 --- a/components/browser/menu/src/main/res/values/dimens.xml +++ b/components/browser/menu/src/main/res/values/dimens.xml @@ -6,7 +6,7 @@ 4dp 8dp 250dp - 8dp + 0dp 16sp @@ -32,4 +32,6 @@ + + 56dp diff --git a/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt b/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt index 1fc387b1b5c..6c7cd0b32ba 100644 --- a/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt +++ b/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt @@ -24,6 +24,7 @@ import kotlin.coroutines.CoroutineContext /** * This class provides access to a centralized registry of search engines. */ +@Suppress("TooManyFunctions") class SearchEngineManager( private val providers: List = listOf( AssetsSearchEngineProvider(LocaleSearchLocalizationProvider())), @@ -62,14 +63,23 @@ class SearchEngineManager( /** * Gets the localized list of search engines and a default search engine from providers. * - * If no call to load() has been made then calling this method will perform a load. + * If no previous call was made to [load] or [loadAsync] then calling this method will + * perform a blocking load. */ - @Synchronized private fun getSearchEngineList(context: Context): SearchEngineList = runBlocking { - (deferredSearchEngines ?: loadAsync(context)) - .await() + getSearchEngineListAsync(context) } + /** + * Gets the localized list of search engines and a default search engine from providers. + * + * If no previous call was made to [load] or [loadAsync] then calling this method will perform + * a load asynchronously. + */ + private suspend fun getSearchEngineListAsync(context: Context): SearchEngineList = + (deferredSearchEngines ?: loadAsync(context)) + .await() + /** * Returns all search engines. */ @@ -78,6 +88,13 @@ class SearchEngineManager( return getSearchEngineList(context).list } + /** + * Returns all search engines. + */ + suspend fun getSearchEnginesAsync(context: Context): List { + return getSearchEngineListAsync(context).list + } + /** * Returns the default search engine. * @@ -99,6 +116,26 @@ class SearchEngineManager( } } + /** + * Returns the default search engine. + * + * If defaultSearchEngine has not been set, the default engine is set by the search provider, + * (e.g. as set in `list.json`). If that is not set, then the first search engine listed is + * returned. + * + * Optionally a name can be passed to this method (e.g. from the user's preferences). If + * a matching search engine was loaded then this search engine will be returned instead. + */ + suspend fun getDefaultSearchEngineAsync(context: Context, name: String = EMPTY): SearchEngine { + val searchEngineList = getSearchEngineListAsync(context) + val providedDefault = getProvidedDefaultSearchEngineAsync(context) + + return when (name) { + EMPTY -> defaultSearchEngine ?: providedDefault + else -> searchEngineList.list.find { it.name == name } ?: providedDefault + } + } + /** * Returns the provided default search engine or the first search engine if the default * is not set. @@ -109,6 +146,15 @@ class SearchEngineManager( return searchEngineList.default ?: searchEngineList.list[0] } + /** + * Returns the provided default search engine or the first search engine if the default + * is not set. + */ + suspend fun getProvidedDefaultSearchEngineAsync(context: Context): SearchEngine { + val searchEngineList = getSearchEngineListAsync(context) + return searchEngineList.default ?: searchEngineList.list[0] + } + /** * Registers for ACTION_LOCALE_CHANGED broadcasts and automatically reloads the search engines * whenever the locale changes. diff --git a/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt b/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt index a10b00f4cf3..f1f72f3ca91 100644 --- a/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt +++ b/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt @@ -4,7 +4,9 @@ package mozilla.components.browser.search.suggestions +import android.content.Context import mozilla.components.browser.search.SearchEngine +import mozilla.components.browser.search.SearchEngineManager import org.json.JSONException import java.io.IOException @@ -16,10 +18,32 @@ typealias SearchSuggestionFetcher = suspend (url: String) -> String? /** * Provides an interface to get search suggestions from a given SearchEngine. */ -class SearchSuggestionClient( - private val searchEngine: SearchEngine, +class SearchSuggestionClient { + + private val context: Context? private val fetcher: SearchSuggestionFetcher -) { + + val searchEngineManager: SearchEngineManager? + var searchEngine: SearchEngine? = null + private set + + internal constructor( + context: Context?, + searchEngineManager: SearchEngineManager?, + searchEngine: SearchEngine?, + fetcher: SearchSuggestionFetcher + ) { + this.context = context + this.searchEngineManager = searchEngineManager + this.searchEngine = searchEngine + this.fetcher = fetcher + } + + constructor(searchEngine: SearchEngine, fetcher: SearchSuggestionFetcher) : + this (null, null, searchEngine, fetcher) + + constructor(context: Context, searchEngineManager: SearchEngineManager, fetcher: SearchSuggestionFetcher) : + this (context, searchEngineManager, null, fetcher) /** * Exception types for errors caught while getting a list of suggestions @@ -27,16 +51,24 @@ class SearchSuggestionClient( class FetchException : Exception("There was a problem fetching suggestions") class ResponseParserException : Exception("There was a problem parsing the suggestion response") - init { - if (!searchEngine.canProvideSearchSuggestions) { - throw IllegalArgumentException("SearchEngine does not support search suggestions!") - } - } - /** * Gets search suggestions for a given query */ suspend fun getSuggestions(query: String): List? { + val searchEngine = searchEngine ?: run { + requireNotNull(searchEngineManager) + requireNotNull(context) + searchEngineManager.getDefaultSearchEngineAsync(context).also { + searchEngine = it + } + } + + if (!searchEngine.canProvideSearchSuggestions) { + // This search engine doesn't support suggestions. Let's only return a default suggestion + // for the entered text. + return emptyList() + } + val suggestionsURL = searchEngine.buildSuggestionsURL(query) val parser = selectResponseParser(searchEngine) diff --git a/components/browser/search/src/test/java/mozilla/components/browser/search/SearchEngineManagerTest.kt b/components/browser/search/src/test/java/mozilla/components/browser/search/SearchEngineManagerTest.kt index 368c9dfab94..7dd874f792a 100644 --- a/components/browser/search/src/test/java/mozilla/components/browser/search/SearchEngineManagerTest.kt +++ b/components/browser/search/src/test/java/mozilla/components/browser/search/SearchEngineManagerTest.kt @@ -49,16 +49,20 @@ class SearchEngineManagerTest { manager.loadAsync(testContext) .await() - val engines = manager.getSearchEngines(testContext) - assertEquals(3, engines.size) + val verify = { engines: List -> + assertEquals(3, engines.size) - engines.assertContainsIdentifier("mozsearch") - engines.assertContainsIdentifier("google") - engines.assertContainsIdentifier("bing") + engines.assertContainsIdentifier("mozsearch") + engines.assertContainsIdentifier("google") + engines.assertContainsIdentifier("bing") + } + + verify(manager.getSearchEngines(testContext)) + verify(manager.getSearchEnginesAsync(testContext)) } @Test - fun `manager returns engines from deffered`() = runBlockingTest { + fun `manager returns engines from deferred`() = runBlockingTest { val provider = mockProvider(listOf( mockSearchEngine("mozsearch"), mockSearchEngine("google"), @@ -87,8 +91,12 @@ class SearchEngineManagerTest { val manager = SearchEngineManager(listOf(provider)) - val engines = manager.getSearchEngines(testContext) - assertEquals(3, engines.size) + val verify = { engines: List -> + assertEquals(3, engines.size) + } + + verify(manager.getSearchEngines(testContext)) + verify(manager.getSearchEnginesAsync(testContext)) } @Test @@ -100,8 +108,12 @@ class SearchEngineManagerTest { val manager = SearchEngineManager(listOf(provider)) - val default = manager.getDefaultSearchEngine(testContext, "banana") - assertEquals("mozsearch", default.identifier) + val verify = { default: SearchEngine -> + assertEquals("mozsearch", default.identifier) + } + + verify(manager.getDefaultSearchEngine(testContext, "banana")) + verify(manager.getDefaultSearchEngineAsync(testContext, "banana")) } @Test @@ -113,11 +125,12 @@ class SearchEngineManagerTest { val manager = SearchEngineManager(listOf(provider)) - val default = manager.getDefaultSearchEngine( - testContext, - "Bing Search") + val verify = { default: SearchEngine -> + assertEquals("bing", default.identifier) + } - assertEquals("bing", default.identifier) + verify(manager.getDefaultSearchEngine(testContext, "Bing Search")) + verify(manager.getDefaultSearchEngineAsync(testContext, "Bing Search")) } @Test @@ -134,8 +147,12 @@ class SearchEngineManagerTest { val manager = SearchEngineManager(listOf(provider)) - val default = manager.getDefaultSearchEngine(testContext) - assertEquals("mozsearch", default.identifier) + val verify = { default: SearchEngine -> + assertEquals("mozsearch", default.identifier) + } + + verify(manager.getDefaultSearchEngine(testContext)) + verify(manager.getDefaultSearchEngineAsync(testContext)) } @Test @@ -147,8 +164,12 @@ class SearchEngineManagerTest { val manager = SearchEngineManager(listOf(provider)) - val default = manager.getDefaultSearchEngine(testContext) - assertEquals("mozsearch", default.identifier) + val verify = { default: SearchEngine -> + assertEquals("mozsearch", default.identifier) + } + + verify(manager.getDefaultSearchEngine(testContext)) + verify(manager.getDefaultSearchEngineAsync(testContext)) } @Test @@ -164,8 +185,12 @@ class SearchEngineManagerTest { val manager = SearchEngineManager(listOf(provider)) manager.defaultSearchEngine = mockSearchEngine("bing") - val default = manager.getDefaultSearchEngine(testContext) - assertEquals("bing", default.identifier) + val verify = { default: SearchEngine -> + assertEquals("bing", default.identifier) + } + + verify(manager.getDefaultSearchEngine(testContext)) + verify(manager.getDefaultSearchEngineAsync(testContext)) } @Test @@ -181,9 +206,12 @@ class SearchEngineManagerTest { val manager = SearchEngineManager(listOf(provider)) manager.defaultSearchEngine = mockSearchEngine("bing") - val default = - manager.getDefaultSearchEngine(testContext, "Google Search") - assertEquals("google", default.identifier) + val verify = { default: SearchEngine -> + assertEquals("google", default.identifier) + } + + verify(manager.getDefaultSearchEngine(testContext, "Google Search")) + verify(manager.getDefaultSearchEngineAsync(testContext, "Google Search")) } @Test @@ -195,8 +223,12 @@ class SearchEngineManagerTest { val manager = SearchEngineManager(listOf(provider)) - val default = manager.getProvidedDefaultSearchEngine(testContext) - assertEquals("mozsearch", default.identifier) + val verify = { default: SearchEngine -> + assertEquals("mozsearch", default.identifier) + } + + verify(manager.getProvidedDefaultSearchEngine(testContext)) + verify(manager.getProvidedDefaultSearchEngineAsync(testContext)) } @Test @@ -213,8 +245,12 @@ class SearchEngineManagerTest { val manager = SearchEngineManager(listOf(provider)) - val default = manager.getProvidedDefaultSearchEngine(testContext) - assertEquals("mozsearch", default.identifier) + val verify = { default: SearchEngine -> + assertEquals("mozsearch", default.identifier) + } + + verify(manager.getProvidedDefaultSearchEngine(testContext)) + verify(manager.getProvidedDefaultSearchEngineAsync(testContext)) } @Test diff --git a/components/browser/search/src/test/java/mozilla/components/browser/search/suggestions/SearchSuggestionClientTest.kt b/components/browser/search/src/test/java/mozilla/components/browser/search/suggestions/SearchSuggestionClientTest.kt index 57647d496e5..294e8b85529 100644 --- a/components/browser/search/src/test/java/mozilla/components/browser/search/suggestions/SearchSuggestionClientTest.kt +++ b/components/browser/search/src/test/java/mozilla/components/browser/search/suggestions/SearchSuggestionClientTest.kt @@ -6,11 +6,14 @@ package mozilla.components.browser.search.suggestions import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.coroutines.runBlocking +import mozilla.components.browser.search.SearchEngineManager import mozilla.components.browser.search.SearchEngineParser +import mozilla.components.support.test.mock import mozilla.components.support.test.robolectric.testContext import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mockito.`when` import java.io.IOException @RunWith(AndroidJUnit4::class) @@ -80,12 +83,35 @@ class SearchSuggestionClientTest { } } - @Test(expected = IllegalArgumentException::class) - fun `Check that a search engine without a suggestURI will throw an exception`() { + @Test + fun `Check that a search engine without a suggestURI will return an empty suggestion list`() { val searchEngine = SearchEngineParser().load( testContext.assets, "drae", "searchplugins/drae.xml") - SearchSuggestionClient(searchEngine) { "no-op" } + val client = SearchSuggestionClient(searchEngine) { "no-op" } + runBlocking { + val results = client.getSuggestions("firefox") + assertEquals(emptyList(), results) + } + } + + @Test + fun `Default search engine is used if search engine manager provided`() { + val searchEngine = SearchEngineParser().load( + testContext.assets, + "google", "searchplugins/google-b-m.xml") + + val searchEngineManager: SearchEngineManager = mock() + val client = SearchSuggestionClient(testContext, searchEngineManager, GOOGLE_MOCK_RESPONSE) + + runBlocking { + `when`(searchEngineManager.getDefaultSearchEngineAsync(testContext)).thenReturn(searchEngine) + + val results = client.getSuggestions("firefox") + val expectedResults = listOf("firefox", "firefox for mac", "firefox quantum", "firefox update", "firefox esr", "firefox focus", "firefox addons", "firefox extensions", "firefox nightly", "firefox clear cache") + + assertEquals(expectedResults, results) + } } } diff --git a/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt b/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt index ff257e56d48..b948d096dbc 100644 --- a/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt +++ b/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt @@ -22,6 +22,8 @@ class LegacySessionManager( val engine: Engine, delegate: Observable = ObserverRegistry() ) : Observable by delegate { + // It's important that any access to `values` is synchronized; + @GuardedBy("values") private val values = mutableListOf() @GuardedBy("values") @@ -522,7 +524,9 @@ class LegacySessionManager( * Finds and returns the session with the given id. Returns null if no matching session could be * found. */ - fun findSessionById(id: String): Session? = values.find { session -> session.id == id } + fun findSessionById(id: String): Session? = synchronized(values) { + values.find { session -> session.id == id } + } /** * Informs this [SessionManager] that the OS is in low memory condition so it diff --git a/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt b/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt index 0c9b3f9be0a..0fc54f11954 100644 --- a/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt +++ b/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt @@ -31,7 +31,6 @@ import kotlinx.coroutines.launch import mozilla.components.browser.menu.BrowserMenuBuilder import mozilla.components.browser.toolbar.display.DisplayToolbar import mozilla.components.browser.toolbar.display.DisplayToolbar.Companion.BOTTOM_PROGRESS_BAR -import mozilla.components.browser.toolbar.display.SiteSecurityIcons import mozilla.components.browser.toolbar.display.TrackingProtectionIconView import mozilla.components.browser.toolbar.edit.EditToolbar import mozilla.components.concept.toolbar.AutocompleteDelegate @@ -114,12 +113,21 @@ class BrowserToolbar @JvmOverloads constructor( } /** - * Set/Get the site security icons (usually a lock or globe icon). It uses a pair of drawables - * which represent the insecure and secure colours respectively. + * Set/Get the site security icon (usually a lock and globe icon). It uses a + * [android.graphics.drawable.StateListDrawable] where "state_site_secure" represents the secure + * icon and empty state represents the insecure icon. */ - var siteSecurityIcons - get() = displayToolbar.securityIcons - set(value) { displayToolbar.securityIcons = value } + var siteSecurityIcon + get() = displayToolbar.securityIcon + set(value) { displayToolbar.securityIcon = value } + + /** + * Set/Get the site security icon colours. It uses a pair of color integers + * which represent the insecure and secure colours respectively. + */ + var siteSecurityColor: Pair + get() = displayToolbar.securityIconColor + set(value) { displayToolbar.securityIconColor = value } /** * Gets/Sets a custom view that will be drawn as behind the URL and page actions in display mode. @@ -301,11 +309,6 @@ class BrowserToolbar @JvmOverloads constructor( editToolbar.urlView.typeface = value } - fun setSiteSecurityColor(colors: Pair) { - displayToolbar.securityIcons = - displayToolbar.securityIcons.withColorFilter(colors.first, colors.second) - } - /** * Sets a listener to be invoked when focus of the URL input view (in edit mode) changed. */ @@ -474,20 +477,17 @@ class BrowserToolbar @JvmOverloads constructor( R.styleable.BrowserToolbar_browserToolbarSuggestionBackgroundColor, suggestionBackgroundColor ) - val inSecureIcon = getDrawable(R.styleable.BrowserToolbar_browserToolbarInsecureIcon) - ?: displayToolbar.securityIcons.insecure - val secureIcon = getDrawable(R.styleable.BrowserToolbar_browserToolbarSecureIcon) - ?: displayToolbar.securityIcons.secure - val inSecureColor = getColor( + siteSecurityIcon = getDrawable(R.styleable.BrowserToolbar_browserToolbarSecurityIcon) + ?: displayToolbar.securityIcon + val insecureColor = getColor( R.styleable.BrowserToolbar_browserToolbarInsecureColor, displayToolbar.defaultColor ) val secureColor = getColor( - R.styleable.BrowserToolbar_browserToolbarSecureColor, + R.styleable.BrowserToolbar_browserToolbarInsecureColor, displayToolbar.defaultColor ) - siteSecurityIcons = SiteSecurityIcons(inSecureIcon, secureIcon) - .withColorFilter(inSecureColor, secureColor) + siteSecurityColor = insecureColor to secureColor val fadingEdgeLength = getDimensionPixelSize( R.styleable.BrowserToolbar_browserToolbarFadingEdgeSize, resources.getDimensionPixelSize(R.dimen.mozac_browser_toolbar_url_fading_edge_size) diff --git a/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/DisplayToolbar.kt b/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/DisplayToolbar.kt index 278b995f380..d09d6eff133 100644 --- a/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/DisplayToolbar.kt +++ b/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/DisplayToolbar.kt @@ -6,6 +6,7 @@ package mozilla.components.browser.toolbar.display import android.annotation.SuppressLint import android.content.Context +import android.graphics.Color import android.graphics.drawable.Drawable import android.view.Gravity import android.view.View @@ -29,10 +30,10 @@ import mozilla.components.browser.toolbar.internal.wrapAction import mozilla.components.concept.toolbar.Toolbar import mozilla.components.concept.toolbar.Toolbar.SiteSecurity import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection +import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection.OFF_FOR_A_SITE +import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection.OFF_GLOBALLY import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection.ON_NO_TRACKERS_BLOCKED import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection.ON_TRACKERS_BLOCKED -import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection.OFF_GLOBALLY -import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection.OFF_FOR_A_SITE /** * Sub-component of the browser toolbar responsible for displaying the URL and related controls. @@ -127,7 +128,13 @@ internal class DisplayToolbar( private var siteTrackingProtection = OFF_GLOBALLY - internal var securityIcons = SiteSecurityIcons.getDefaultSecurityIcons(context, defaultColor) + internal var securityIcon = context.getDrawable(R.drawable.mozac_ic_site_security) + set(value) { + field = value + siteSecurityIconView.setImageDrawable(value) + } + + internal var securityIconColor = defaultColor to defaultColor set(value) { field = value setSiteSecurity(currentSiteSecurity) @@ -140,6 +147,7 @@ internal class DisplayToolbar( } internal val trackingProtectionIconView = TrackingProtectionIconView(context).apply { + id = R.id.mozac_browser_toolbar_tracking_protection_icon_view isVisible = false setImageResource(R.drawable.mozac_tracking_protection_state_list) setPadding(resources.getDimensionPixelSize(R.dimen.mozac_browser_toolbar_icon_padding)) @@ -160,11 +168,9 @@ internal class DisplayToolbar( setOnClickListener(null) } - internal val siteSecurityIconView = AppCompatImageView(context).apply { + internal val siteSecurityIconView = SiteSecurityIconView(context).apply { setPadding(resources.getDimensionPixelSize(R.dimen.mozac_browser_toolbar_icon_padding)) - setImageDrawable(securityIcons.insecure) - // Avoiding text behind the icon being selectable. If the listener is not set // with a value or null text behind the icon can be selectable. // https://github.com/mozilla-mobile/reference-browser/issues/448 @@ -305,12 +311,17 @@ internal class DisplayToolbar( * Sets the site's security icon as secure if true, else the regular globe. */ fun setSiteSecurity(secure: SiteSecurity) { - val drawable = when (secure) { - SiteSecurity.INSECURE -> securityIcons.insecure - SiteSecurity.SECURE -> securityIcons.secure + @ColorInt val color = when (secure) { + SiteSecurity.INSECURE -> securityIconColor.first + SiteSecurity.SECURE -> securityIconColor.second + } + if (color == Color.TRANSPARENT) { + siteSecurityIconView.clearColorFilter() + } else { + siteSecurityIconView.setColorFilter(color) } - siteSecurityIconView.setImageDrawable(drawable) + siteSecurityIconView.siteSecurity = secure currentSiteSecurity = secure } @@ -613,9 +624,12 @@ internal class DisplayToolbar( } } - private fun shouldTrackingProtectionViewBeVisible() = - displayTrackingProtectionIcon && (siteTrackingProtection == ON_NO_TRACKERS_BLOCKED || - siteTrackingProtection == ON_TRACKERS_BLOCKED) + private fun shouldTrackingProtectionViewBeVisible(): Boolean { + val visibleStates = arrayOf(ON_NO_TRACKERS_BLOCKED, ON_TRACKERS_BLOCKED, OFF_FOR_A_SITE) + val isAVisibleSate = visibleStates.any { it == siteTrackingProtection } + + return displayTrackingProtectionIcon && isAVisibleSate + } companion object { internal const val MEASURED_HEIGHT_THIRD_DENOMINATOR = 3 diff --git a/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIconView.kt b/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIconView.kt new file mode 100644 index 00000000000..4821b3306ca --- /dev/null +++ b/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIconView.kt @@ -0,0 +1,48 @@ +/* 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 mozilla.components.browser.toolbar.display + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import androidx.appcompat.widget.AppCompatImageView +import mozilla.components.browser.toolbar.R +import mozilla.components.concept.toolbar.Toolbar.SiteSecurity + +/** + * Internal widget to display the different icons of site security, relies on the + * [SiteSecurity] state of each page. + */ +internal class SiteSecurityIconView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : AppCompatImageView(context, attrs, defStyleAttr) { + + // We allow null here because in some situations, onCreateDrawableState is getting called from + // the super() constructor on the View class, way before this class properties get + // initialized causing a null pointer exception. + // See for more details: https://github.com/mozilla-mobile/android-components/issues/4058 + var siteSecurity: SiteSecurity? = SiteSecurity.INSECURE + set(value) { + if (value != field) { + field = value + refreshDrawableState() + } + + field = value + } + + override fun onCreateDrawableState(extraSpace: Int): IntArray { + return when (siteSecurity) { + SiteSecurity.INSECURE, null -> super.onCreateDrawableState(extraSpace) + SiteSecurity.SECURE -> { + val drawableState = super.onCreateDrawableState(extraSpace + 1) + View.mergeDrawableStates(drawableState, intArrayOf(R.attr.state_site_secure)) + drawableState + } + } + } +} diff --git a/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIcons.kt b/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIcons.kt deleted file mode 100644 index 7b0434d6bab..00000000000 --- a/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIcons.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* 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 mozilla.components.browser.toolbar.display - -import android.content.Context -import android.graphics.BlendMode -import android.graphics.BlendModeColorFilter -import android.graphics.ColorFilter -import android.graphics.PorterDuff -import android.graphics.PorterDuffColorFilter -import android.graphics.drawable.Drawable -import android.os.Build -import android.os.Build.VERSION.SDK_INT -import androidx.annotation.ColorInt -import mozilla.components.ui.icons.R - -/** - * Specifies icons to display in the toolbar representing the security of the current website. - * - * @property insecure Icon to display for HTTP sites. - * @property secure Icon to display for HTTPS sites. - */ -data class SiteSecurityIcons( - val insecure: Drawable?, - val secure: Drawable? -) { - - /** - * Returns an instance of [SiteSecurityIcons] with a color filter applied to each icon. - */ - fun withColorFilter(insecureColorFilter: ColorFilter, secureColorFilter: ColorFilter): SiteSecurityIcons { - return copy( - insecure = insecure?.apply { colorFilter = insecureColorFilter }, - secure = secure?.apply { colorFilter = secureColorFilter } - ) - } - - /** - * Returns an instance of [SiteSecurityIcons] with a color tint applied to each icon. - */ - fun withColorFilter(@ColorInt insecureColor: Int, @ColorInt secureColor: Int): SiteSecurityIcons { - val insecureColorFilter: ColorFilter = if (SDK_INT >= Build.VERSION_CODES.Q) { - BlendModeColorFilter(insecureColor, BlendMode.SRC_IN) - } else { - PorterDuffColorFilter(insecureColor, PorterDuff.Mode.SRC_IN) - } - - val secureColorFilter: ColorFilter = if (SDK_INT >= Build.VERSION_CODES.Q) { - BlendModeColorFilter(secureColor, BlendMode.SRC_IN) - } else { - PorterDuffColorFilter(secureColor, PorterDuff.Mode.SRC_IN) - } - - return withColorFilter(insecureColorFilter, secureColorFilter) - } - - companion object { - fun getDefaultSecurityIcons(context: Context, @ColorInt color: Int): SiteSecurityIcons { - return SiteSecurityIcons( - insecure = context.getDrawable(R.drawable.mozac_ic_globe), - secure = context.getDrawable(R.drawable.mozac_ic_lock) - ).withColorFilter(color, color) - } - } -} diff --git a/components/browser/toolbar/src/main/res/drawable/mozac_ic_site_security.xml b/components/browser/toolbar/src/main/res/drawable/mozac_ic_site_security.xml new file mode 100644 index 00000000000..cdba3bc2eab --- /dev/null +++ b/components/browser/toolbar/src/main/res/drawable/mozac_ic_site_security.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/components/browser/toolbar/src/main/res/values-cs/strings.xml b/components/browser/toolbar/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..ad66590b73f --- /dev/null +++ b/components/browser/toolbar/src/main/res/values-cs/strings.xml @@ -0,0 +1,8 @@ + + + + Nabídka + Vymazat + + Načítání + diff --git a/components/browser/toolbar/src/main/res/values-es-rAR/strings.xml b/components/browser/toolbar/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..53795888a22 --- /dev/null +++ b/components/browser/toolbar/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,8 @@ + + + + Menú + Eliminar + + Cargando + diff --git a/components/browser/toolbar/src/main/res/values-fi/strings.xml b/components/browser/toolbar/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..fdfa0108cc3 --- /dev/null +++ b/components/browser/toolbar/src/main/res/values-fi/strings.xml @@ -0,0 +1,8 @@ + + + + Valikko + Tyhjennä + + Ladataan + diff --git a/components/browser/toolbar/src/main/res/values-pa-rIN/strings.xml b/components/browser/toolbar/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..561ab297106 --- /dev/null +++ b/components/browser/toolbar/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,8 @@ + + + + ਮੇਨੂ + ਸਾਫ਼ ਕਰੋ + + ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ + diff --git a/components/browser/toolbar/src/main/res/values/attrs_browser_toolbar.xml b/components/browser/toolbar/src/main/res/values/attrs_browser_toolbar.xml index eef30845fda..d2a78de9e58 100644 --- a/components/browser/toolbar/src/main/res/values/attrs_browser_toolbar.xml +++ b/components/browser/toolbar/src/main/res/values/attrs_browser_toolbar.xml @@ -8,10 +8,9 @@ - - - + + @@ -29,4 +28,8 @@ + + + + diff --git a/components/browser/toolbar/src/main/res/values/ids.xml b/components/browser/toolbar/src/main/res/values/ids.xml index a349635e1da..39cf67df00e 100644 --- a/components/browser/toolbar/src/main/res/values/ids.xml +++ b/components/browser/toolbar/src/main/res/values/ids.xml @@ -6,6 +6,7 @@ --> + diff --git a/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/BrowserToolbarTest.kt b/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/BrowserToolbarTest.kt index 1f309a72662..600718a60a6 100644 --- a/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/BrowserToolbarTest.kt +++ b/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/BrowserToolbarTest.kt @@ -6,8 +6,6 @@ package mozilla.components.browser.toolbar import android.content.Context import android.graphics.Color -import android.graphics.PorterDuff -import android.graphics.PorterDuffColorFilter import android.graphics.Typeface import android.graphics.drawable.Drawable import android.util.AttributeSet @@ -908,23 +906,6 @@ class BrowserToolbarTest { assertEquals(View.VISIBLE, toolbar.displayToolbar.siteSecurityIconView.visibility) } - @Test - fun `siteSecurityColor setter`() { - val toolbar = BrowserToolbar(testContext) - - toolbar.setSiteSecurityColor(Color.RED to Color.BLUE) - assertEquals( - PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN), - toolbar.displayToolbar.siteSecurityIconView.drawable.colorFilter - ) - - toolbar.siteSecure = SiteSecurity.SECURE - assertEquals( - PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN), - toolbar.displayToolbar.siteSecurityIconView.drawable.colorFilter - ) - } - @Test fun `urlBoxView getter`() { val toolbar = BrowserToolbar(testContext) diff --git a/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/display/DisplayToolbarTest.kt b/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/display/DisplayToolbarTest.kt index abc4939c653..124d852ebcd 100644 --- a/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/display/DisplayToolbarTest.kt +++ b/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/display/DisplayToolbarTest.kt @@ -4,7 +4,9 @@ package mozilla.components.browser.toolbar.display +import android.graphics.Color import android.graphics.Rect +import android.graphics.drawable.Drawable import android.view.View import android.view.ViewGroup import android.widget.ImageButton @@ -42,19 +44,10 @@ import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.spy import org.mockito.Mockito.verify -import org.robolectric.Shadows.shadowOf @RunWith(AndroidJUnit4::class) class DisplayToolbarTest { - @Test - fun `initialized with security icon`() { - val toolbar = mock(BrowserToolbar::class.java) - val displayToolbar = DisplayToolbar(testContext, toolbar) - - assertNotNull(displayToolbar.siteSecurityIconView.drawable) - } - @Test fun `clicking on the URL switches the toolbar to editing mode`() { val toolbar = mock(BrowserToolbar::class.java) @@ -195,6 +188,14 @@ class DisplayToolbarTest { // Tracking protection views MUST be measured assertEquals(totalViewsWidth + trackingProtectionWidth + separatorWidth, view.measuredWidth) + + displayToolbar.setTrackingProtectionState(SiteTrackingProtection.OFF_FOR_A_SITE) + displayToolbar.measure(widthSpec, heightSpec) + + totalViewsWidth = urlView.measuredWidth + securityIcon.measuredWidth + + // Tracking protection views MUST be measured + assertEquals(totalViewsWidth + trackingProtectionWidth + separatorWidth, view.measuredWidth) } @Test @@ -960,45 +961,64 @@ class DisplayToolbarTest { } @Test - fun `iconView changes image resource when site security changes`() { + fun `iconView changes site secure state when site security changes`() { val toolbar = mock(BrowserToolbar::class.java) val displayToolbar = DisplayToolbar(testContext, toolbar) - var shadowDrawable = shadowOf(displayToolbar.siteSecurityIconView.drawable) - assertEquals(R.drawable.mozac_ic_globe, shadowDrawable.createdFromResId) + assertEquals(SiteSecurity.INSECURE, displayToolbar.siteSecurityIconView.siteSecurity) displayToolbar.setSiteSecurity(SiteSecurity.SECURE) - shadowDrawable = shadowOf(displayToolbar.siteSecurityIconView.drawable) - assertEquals(R.drawable.mozac_ic_lock, shadowDrawable.createdFromResId) + assertEquals(SiteSecurity.SECURE, displayToolbar.siteSecurityIconView.siteSecurity) displayToolbar.setSiteSecurity(SiteSecurity.INSECURE) - shadowDrawable = shadowOf(displayToolbar.siteSecurityIconView.drawable) - assertEquals(R.drawable.mozac_ic_globe, shadowDrawable.createdFromResId) + assertEquals(SiteSecurity.INSECURE, displayToolbar.siteSecurityIconView.siteSecurity) } @Test - fun `securityIcons is set when securityIcons changes`() { + fun `securityIcon is set when securityIcon changes`() { val toolbar = mock(BrowserToolbar::class.java) val displayToolbar = DisplayToolbar(testContext, toolbar) - val insecure = testContext.getDrawable(R.drawable.mozac_ic_globe) - val secure = testContext.getDrawable(R.drawable.mozac_ic_lock) - displayToolbar.securityIcons = SiteSecurityIcons(insecure, secure) + val icon = testContext.getDrawable(R.drawable.mozac_ic_site_security) + displayToolbar.securityIcon = icon + + assertEquals(icon, displayToolbar.securityIcon) + } + + @Test + fun `setImageDrawable is called when securityIcon changes`() { + val toolbar = BrowserToolbar(testContext) + + val icon: Drawable = mock() + assertNotEquals(icon, toolbar.displayToolbar.siteSecurityIconView.drawable) + + toolbar.siteSecurityIcon = icon + assertEquals(icon, toolbar.displayToolbar.siteSecurityIconView.drawable) + } + + @Test + fun `securityIconColor is set when securityIconColor changes`() { + val toolbar = BrowserToolbar(testContext) + + assertNull(toolbar.displayToolbar.siteSecurityIconView.colorFilter) + + toolbar.siteSecurityColor = Color.TRANSPARENT to Color.TRANSPARENT + assertNull(toolbar.displayToolbar.siteSecurityIconView.colorFilter) - assertEquals(insecure, displayToolbar.securityIcons.insecure) - assertEquals(secure, displayToolbar.securityIcons.secure) + toolbar.siteSecurityColor = Color.BLUE to Color.BLUE + assertNotNull(toolbar.displayToolbar.siteSecurityIconView.colorFilter) } @Test - fun `setSiteSecurity is called when securityIcons changes`() { + fun `setSiteSecurity is called when securityIconColor changes`() { val toolbar = BrowserToolbar(testContext) - val icons = SiteSecurityIcons(mock(), mock()) - assertNotEquals(icons, toolbar.displayToolbar.securityIcons) + val icon: Drawable = mock() + assertNotEquals(icon, toolbar.displayToolbar.securityIcon) - toolbar.siteSecurityIcons = icons - assertEquals(icons, toolbar.displayToolbar.securityIcons) + toolbar.siteSecurityIcon = icon + assertEquals(icon, toolbar.displayToolbar.securityIcon) } @Test diff --git a/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/display/SiteSecurityIconsTest.kt b/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/display/SiteSecurityIconsTest.kt deleted file mode 100644 index cd6a7596999..00000000000 --- a/components/browser/toolbar/src/test/java/mozilla/components/browser/toolbar/display/SiteSecurityIconsTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* 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 mozilla.components.browser.toolbar.display - -import android.graphics.Color -import android.graphics.ColorMatrix -import android.graphics.ColorMatrixColorFilter -import android.graphics.PorterDuff -import android.graphics.PorterDuffColorFilter -import android.graphics.drawable.Drawable -import androidx.test.ext.junit.runners.AndroidJUnit4 -import mozilla.components.support.test.mock -import mozilla.components.support.test.robolectric.testContext -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mockito.verify - -@RunWith(AndroidJUnit4::class) -class SiteSecurityIconsTest { - - @Test - fun `default returns non-null tinted icons`() { - val icons = SiteSecurityIcons.getDefaultSecurityIcons(testContext, Color.RED) - assertEquals(PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN), icons.insecure?.colorFilter) - assertEquals(PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN), icons.secure?.colorFilter) - } - - @Test - fun `withColorFilter tints existing drawables`() { - val insecure: Drawable = mock() - val secure: Drawable = mock() - val icons = SiteSecurityIcons(insecure, secure).withColorFilter(Color.BLUE, Color.RED) - - assertEquals(insecure, icons.insecure) - assertEquals(secure, icons.secure) - verify(insecure).colorFilter = PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN) - verify(secure).colorFilter = PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN) - } - - @Test - fun `withColorFilter allows custom filters to be used`() { - val insecure: Drawable = mock() - val secure: Drawable = mock() - val filter = ColorMatrixColorFilter(ColorMatrix()) - val icons = SiteSecurityIcons(insecure, secure).withColorFilter(filter, filter) - - assertEquals(insecure, icons.insecure) - assertEquals(secure, icons.secure) - verify(insecure).colorFilter = filter - verify(secure).colorFilter = filter - } -} diff --git a/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt b/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt index a3bc7aae747..f55f66d5d94 100644 --- a/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt +++ b/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt @@ -26,11 +26,17 @@ abstract class Media( */ abstract val controller: Controller + /** + * The [Metadata] + */ + abstract val metadata: Metadata + /** * Interface to be implemented by classes that want to observe a media element. */ interface Observer { fun onPlaybackStateChanged(media: Media, playbackState: PlaybackState) = Unit + fun onMetadataChanged(media: Media, metadata: Metadata) = Unit } /** @@ -129,6 +135,15 @@ abstract class Media( EMPTIED, } + /** + * Metadata associated with [Media]. + * + * @property duration Indicates the duration of the media in seconds. + */ + data class Metadata( + val duration: Double = -1.0 + ) + /** * Helper method to notify observers. */ diff --git a/components/concept/engine/src/test/java/mozilla/components/concept/engine/media/MediaTest.kt b/components/concept/engine/src/test/java/mozilla/components/concept/engine/media/MediaTest.kt index 36f690f6b43..11f116d9ce1 100644 --- a/components/concept/engine/src/test/java/mozilla/components/concept/engine/media/MediaTest.kt +++ b/components/concept/engine/src/test/java/mozilla/components/concept/engine/media/MediaTest.kt @@ -75,4 +75,5 @@ class MediaTest { private class FakeMedia : Media() { override val controller: Controller = mock() + override val metadata: Metadata = mock() } diff --git a/components/feature/app-links/src/main/res/values-cs/strings.xml b/components/feature/app-links/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..3b4af4acb55 --- /dev/null +++ b/components/feature/app-links/src/main/res/values-cs/strings.xml @@ -0,0 +1,11 @@ + + + + Otevřít v… + + Chcete odkaz otevřít v jiné aplikaci? Vaše prohlížení nemusí zůstat anonymní. + + Otevřít + + Zrušit + diff --git a/components/feature/app-links/src/main/res/values-es-rAR/strings.xml b/components/feature/app-links/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..02c2d96dff9 --- /dev/null +++ b/components/feature/app-links/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,11 @@ + + + + Abrir en… + + ¿Abrir en aplicación? Es posible que tu actividad deje de ser privada. + + Abrir + + Cancelar + diff --git a/components/feature/app-links/src/main/res/values-eu/strings.xml b/components/feature/app-links/src/main/res/values-eu/strings.xml index 9b4f0aaad6e..e3a1e6e827e 100644 --- a/components/feature/app-links/src/main/res/values-eu/strings.xml +++ b/components/feature/app-links/src/main/res/values-eu/strings.xml @@ -2,6 +2,10 @@ Ireki honekin… + + Aplikazioan ireki? Baliteke zure jarduera pribatua ez izatea hemendik aurrera. Ireki - + + Utzi + diff --git a/components/feature/app-links/src/main/res/values-fi/strings.xml b/components/feature/app-links/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..9c295ff31be --- /dev/null +++ b/components/feature/app-links/src/main/res/values-fi/strings.xml @@ -0,0 +1,11 @@ + + + + Avaa sovelluksella… + + Avaa sovelluksella? Toimesi eivät välttämättä ole enää yksityisiä. + + Avaa + + Peruuta + diff --git a/components/feature/app-links/src/main/res/values-pa-rIN/strings.xml b/components/feature/app-links/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..ceab13ad45a --- /dev/null +++ b/components/feature/app-links/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,9 @@ + + + + …ਨਾਲ ਖੋਲ੍ਹੋ + + ਖੋਲ੍ਹੋ + + ਰੱਦ ਕਰੋ + diff --git a/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt b/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt index bce05b2f3b4..466619978e0 100644 --- a/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt +++ b/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt @@ -8,6 +8,7 @@ import android.content.Context import android.view.View import mozilla.components.browser.icons.BrowserIcons import mozilla.components.browser.search.SearchEngine +import mozilla.components.browser.search.SearchEngineManager import mozilla.components.browser.session.SessionManager import mozilla.components.concept.awesomebar.AwesomeBar import mozilla.components.concept.engine.EngineView @@ -58,7 +59,7 @@ class AwesomeBarFeature( } /** - * Add a [AwesomeBar.SuggestionProvider] for search engine suggestions to the [AwesomeBar]. + * Adds a [AwesomeBar.SuggestionProvider] for search engine suggestions to the [AwesomeBar]. */ fun addSearchProvider( searchEngine: SearchEngine, @@ -71,6 +72,27 @@ class AwesomeBarFeature( return this } + /** + * Adds a [AwesomeBar.SuggestionProvider] for search engine suggestions to the [AwesomeBar]. + * If the default search engine is to be used for fetching search engine suggestions then + * this method is preferable over [addSearchProvider], as it will lazily load the default + * search engine using the provided [SearchEngineManager]. + */ + @Suppress("LongParameterList") + fun addSearchProvider( + context: Context, + searchEngineManager: SearchEngineManager, + searchUseCase: SearchUseCases.SearchUseCase, + fetchClient: Client, + limit: Int = 15, + mode: SearchSuggestionProvider.Mode = SearchSuggestionProvider.Mode.SINGLE_SUGGESTION + ): AwesomeBarFeature { + awesomeBar.addProviders( + SearchSuggestionProvider(context, searchEngineManager, searchUseCase, fetchClient, limit, mode) + ) + return this + } + /** * Add a [AwesomeBar.SuggestionProvider] for browsing history to the [AwesomeBar]. */ diff --git a/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt b/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt index 93d36f9710f..d3fb2f4bf36 100644 --- a/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt +++ b/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt @@ -4,8 +4,11 @@ package mozilla.components.feature.awesomebar.provider +import android.content.Context import android.graphics.Bitmap +import androidx.annotation.VisibleForTesting import mozilla.components.browser.search.SearchEngine +import mozilla.components.browser.search.SearchEngineManager import mozilla.components.browser.search.suggestions.SearchSuggestionClient import mozilla.components.concept.awesomebar.AwesomeBar import mozilla.components.concept.fetch.Client @@ -20,36 +23,87 @@ import java.util.concurrent.TimeUnit /** * A [AwesomeBar.SuggestionProvider] implementation that provides a suggestion containing search engine suggestions (as * chips) from the passed in [SearchEngine]. - * - * @param searchEngine The search engine to request suggestions from. - * @param searchUseCase The use case to invoke for searches. - * @param fetchClient The HTTP client for requesting suggestions from the search engine. - * @param limit The maximum number of suggestions that should be returned. It needs to be >= 1. - * @param mode Whether to return a single search suggestion (with chips) or one suggestion per item. - * @param icon The image to display next to the result. If not specified, the engine icon is used */ -class SearchSuggestionProvider( - private val searchEngine: SearchEngine, - private val searchUseCase: SearchUseCases.SearchUseCase, - private val fetchClient: Client, - private val limit: Int = 15, - private val mode: Mode = Mode.SINGLE_SUGGESTION, - private val icon: Bitmap? = null -) : AwesomeBar.SuggestionProvider { +class SearchSuggestionProvider : AwesomeBar.SuggestionProvider { override val id: String = UUID.randomUUID().toString() - private val client = if (searchEngine.canProvideSearchSuggestions) { - SearchSuggestionClient(searchEngine) { - url -> fetch(url) - } - } else { - null - } - - init { + @VisibleForTesting + internal val client: SearchSuggestionClient + + private val searchUseCase: SearchUseCases.SearchUseCase + private val limit: Int + private val mode: Mode + private val icon: Bitmap? + + private constructor( + client: SearchSuggestionClient, + searchUseCase: SearchUseCases.SearchUseCase, + limit: Int = 15, + mode: Mode = Mode.SINGLE_SUGGESTION, + icon: Bitmap? = null + ) { require(limit >= 1) { "limit needs to be >= 1" } + + this.client = client + this.searchUseCase = searchUseCase + this.limit = limit + this.mode = mode + this.icon = icon } + /** + * Creates a [SearchSuggestionProvider] for the provided [SearchEngine]. + * + * @param searchEngine The search engine to request suggestions from. + * @param searchUseCase The use case to invoke for searches. + * @param fetchClient The HTTP client for requesting suggestions from the search engine. + * @param limit The maximum number of suggestions that should be returned. It needs to be >= 1. + * @param mode Whether to return a single search suggestion (with chips) or one suggestion per item. + * @param icon The image to display next to the result. If not specified, the engine icon is used + */ + constructor( + searchEngine: SearchEngine, + searchUseCase: SearchUseCases.SearchUseCase, + fetchClient: Client, + limit: Int = 15, + mode: Mode = Mode.SINGLE_SUGGESTION, + icon: Bitmap? = null + ) : this ( + SearchSuggestionClient(searchEngine) { url -> fetch(fetchClient, url) }, + searchUseCase, + limit, + mode, + icon + ) + + /** + * Creates a [SearchSuggestionProvider] using the default engine as returned by the provided + * [SearchEngineManager]. + * + * @param context the activity or application context, required to load search engines. + * @param searchEngineManager The search engine manager to look up search engines. + * @param searchUseCase The use case to invoke for searches. + * @param fetchClient The HTTP client for requesting suggestions from the search engine. + * @param limit The maximum number of suggestions that should be returned. It needs to be >= 1. + * @param mode Whether to return a single search suggestion (with chips) or one suggestion per item. + * @param icon The image to display next to the result. If not specified, the engine icon is used + */ + constructor( + context: Context, + searchEngineManager: SearchEngineManager, + searchUseCase: SearchUseCases.SearchUseCase, + fetchClient: Client, + limit: Int = 15, + mode: Mode = Mode.SINGLE_SUGGESTION, + icon: Bitmap? = null + ) : this ( + SearchSuggestionClient(context, searchEngineManager) { url -> fetch(fetchClient, url) }, + searchUseCase, + limit, + mode, + icon + ) + @Suppress("ReturnCount") override suspend fun onInputChanged(text: String): List { if (text.isEmpty()) { @@ -65,12 +119,6 @@ class SearchSuggestionProvider( } private suspend fun fetchSuggestions(text: String): List? { - if (client == null) { - // This search engine doesn't support suggestions. Let's only return a default suggestion - // for the entered text. - return emptyList() - } - return try { client.getSuggestions(text) } catch (e: SearchSuggestionClient.FetchException) { @@ -98,9 +146,9 @@ class SearchSuggestionProvider( // We always use the same ID for the entered text so that this suggestion gets replaced "in place". id = if (item == text) ID_OF_ENTERED_TEXT else item, title = item, - description = searchEngine.name, + description = client.searchEngine?.name, icon = { _, _ -> - icon ?: searchEngine.icon + icon ?: client.searchEngine?.icon }, score = Int.MAX_VALUE - index, onSuggestionClicked = { @@ -127,11 +175,11 @@ class SearchSuggestionProvider( return listOf(AwesomeBar.Suggestion( provider = this, id = text, - title = searchEngine.name, + title = client.searchEngine?.name, chips = chips, score = Int.MAX_VALUE, icon = { _, _ -> - icon ?: searchEngine.icon + icon ?: client.searchEngine?.icon }, onChipClicked = { chip -> searchUseCase.invoke(chip.title) @@ -148,34 +196,34 @@ class SearchSuggestionProvider( MULTIPLE_SUGGESTIONS } - @Suppress("ReturnCount", "TooGenericExceptionCaught") - private fun fetch(url: String): String? { - try { - val request = Request( - url = url, - readTimeout = Pair(READ_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS), - connectTimeout = Pair(CONNECT_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS) - ) - - val response = fetchClient.fetch(request) - if (!response.isSuccess) { - return null - } - - return response.use { it.body.string() } - } catch (e: IOException) { - return null - } catch (e: ArrayIndexOutOfBoundsException) { - // On some devices we are seeing an ArrayIndexOutOfBoundsException being thrown - // somewhere inside AOSP/okhttp. - // See: https://github.com/mozilla-mobile/android-components/issues/964 - return null - } - } - companion object { private const val READ_TIMEOUT_IN_MS = 2000L private const val CONNECT_TIMEOUT_IN_MS = 1000L private const val ID_OF_ENTERED_TEXT = "<@@@entered_text_id@@@>" + + @Suppress("ReturnCount", "TooGenericExceptionCaught") + private fun fetch(fetchClient: Client, url: String): String? { + try { + val request = Request( + url = url, + readTimeout = Pair(READ_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS), + connectTimeout = Pair(CONNECT_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS) + ) + + val response = fetchClient.fetch(request) + if (!response.isSuccess) { + return null + } + + return response.use { it.body.string() } + } catch (e: IOException) { + return null + } catch (e: ArrayIndexOutOfBoundsException) { + // On some devices we are seeing an ArrayIndexOutOfBoundsException being thrown + // somewhere inside AOSP/okhttp. + // See: https://github.com/mozilla-mobile/android-components/issues/964 + return null + } + } } } diff --git a/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/AwesomeBarFeatureTest.kt b/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/AwesomeBarFeatureTest.kt index 809e8a83942..ed9677b427c 100644 --- a/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/AwesomeBarFeatureTest.kt +++ b/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/AwesomeBarFeatureTest.kt @@ -6,13 +6,18 @@ package mozilla.components.feature.awesomebar import android.view.View import androidx.test.ext.junit.runners.AndroidJUnit4 +import mozilla.components.browser.search.SearchEngine +import mozilla.components.browser.search.SearchEngineManager import mozilla.components.concept.awesomebar.AwesomeBar import mozilla.components.concept.toolbar.Toolbar +import mozilla.components.feature.awesomebar.provider.SearchSuggestionProvider import mozilla.components.support.test.any +import mozilla.components.support.test.argumentCaptor import mozilla.components.support.test.mock import mozilla.components.support.test.robolectric.testContext import org.junit.Assert.assertFalse import org.junit.Assert.assertNotNull +import org.junit.Assert.assertSame import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith @@ -89,16 +94,36 @@ class AwesomeBarFeatureTest { } @Test - fun `addSearchProvider adds provider`() { + fun `addSearchProvider adds provider with specified search engine`() { val awesomeBar: AwesomeBar = mock() val feature = AwesomeBarFeature(awesomeBar, mock()) verify(awesomeBar, never()).addProviders(any()) - feature.addSearchProvider(mock(), mock(), mock()) + val searchEngine: SearchEngine = mock() + feature.addSearchProvider(searchEngine, mock(), mock()) - verify(awesomeBar).addProviders(any()) + val provider = argumentCaptor() + verify(awesomeBar).addProviders(provider.capture()) + assertSame(searchEngine, provider.value.client.searchEngine) + } + + @Test + fun `addSearchProvider adds provider for default search engine`() { + val awesomeBar: AwesomeBar = mock() + + val feature = AwesomeBarFeature(awesomeBar, mock()) + + verify(awesomeBar, never()).addProviders(any()) + + val context = testContext + val searchEngineManager: SearchEngineManager = mock() + feature.addSearchProvider(context, searchEngineManager, mock(), mock()) + + val provider = argumentCaptor() + verify(awesomeBar).addProviders(provider.capture()) + assertSame(searchEngineManager, provider.value.client.searchEngineManager) } @Test diff --git a/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProviderTest.kt b/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProviderTest.kt index 1f153417923..ae1defff663 100644 --- a/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProviderTest.kt +++ b/components/feature/awesomebar/src/test/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProviderTest.kt @@ -52,7 +52,7 @@ class SearchSuggestionProviderTest { doReturn("google").`when`(searchEngine).name val searchEngineManager: SearchEngineManager = mock() - doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngine(any(), any()) + doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngineAsync(any(), any()) val useCase = spy(SearchUseCases( testContext, @@ -108,7 +108,7 @@ class SearchSuggestionProviderTest { doReturn("google").`when`(searchEngine).name val searchEngineManager: SearchEngineManager = mock() - doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngine(any(), any()) + doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngineAsync(any(), any()) val useCase = spy(SearchUseCases( testContext, @@ -168,7 +168,7 @@ class SearchSuggestionProviderTest { doReturn("google").`when`(searchEngine).name val searchEngineManager: SearchEngineManager = mock() - doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngine(any(), any()) + doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngineAsync(any(), any()) val useCase = spy(SearchUseCases( testContext, @@ -217,7 +217,7 @@ class SearchSuggestionProviderTest { doReturn("google").`when`(searchEngine).name val searchEngineManager: SearchEngineManager = mock() - doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngine(any(), any()) + doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngineAsync(any(), any()) val useCase = spy(SearchUseCases( testContext, @@ -348,7 +348,7 @@ class SearchSuggestionProviderTest { doReturn("google").`when`(searchEngine).name val searchEngineManager: SearchEngineManager = mock() - doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngine(any(), any()) + doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngineAsync(any(), any()) val useCase = spy(SearchUseCases( testContext, @@ -382,7 +382,7 @@ class SearchSuggestionProviderTest { doReturn("google").`when`(searchEngine).name val searchEngineManager: SearchEngineManager = mock() - doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngine(any(), any()) + doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngineAsync(any(), any()) val useCase = spy(SearchUseCases( testContext, @@ -421,7 +421,7 @@ class SearchSuggestionProviderTest { doReturn("google").`when`(searchEngine).name val searchEngineManager: SearchEngineManager = mock() - doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngine(any(), any()) + doReturn(searchEngine).`when`(searchEngineManager).getDefaultSearchEngineAsync(any(), any()) val useCase = spy(SearchUseCases( testContext, diff --git a/components/feature/contextmenu/src/main/res/values-cs/strings.xml b/components/feature/contextmenu/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..d18e1d79618 --- /dev/null +++ b/components/feature/contextmenu/src/main/res/values-cs/strings.xml @@ -0,0 +1,25 @@ + + + + Otevřít odkaz v novém panelu + + Otevřít odkaz v anonymním panelu + + Otevřít obrázek v novém panelu + + Sdílet odkaz + + Kopírovat odkaz + + Kopírovat adresu obrázku + + Uložit obrázek + + Nový panel otevřen + + Nový anonymní panel otevřen + + Text zkopírován do schránky + + Přepnout + diff --git a/components/feature/contextmenu/src/main/res/values-es-rAR/strings.xml b/components/feature/contextmenu/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..59c775a001b --- /dev/null +++ b/components/feature/contextmenu/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,25 @@ + + + + Abrir enlace en una pestaña nueva + + Abrir enlace en una pestaña privada + + Abrir la imagen en una pestaña nueva + + Compartir enlace + + Copiar enlace + + Copiar ubicación de la imagen + + Guardar imagen + + Se abrió una pestaña nueva + + Se abrió una nueva pestaña privada + + Texto copiado al portapapeles + + Intercambiar + diff --git a/components/feature/contextmenu/src/main/res/values-eu/strings.xml b/components/feature/contextmenu/src/main/res/values-eu/strings.xml new file mode 100644 index 00000000000..ff2fba65e77 --- /dev/null +++ b/components/feature/contextmenu/src/main/res/values-eu/strings.xml @@ -0,0 +1,25 @@ + + + + Ireki lotura fitxa berrian + + Ireki lotura fitxa pribatuan + + Ireki irudia fitxa berrian + + Partekatu lotura + + Kopiatu lotura + + Kopiatu irudiaren helbidea + + Gorde irudia + + Fitxa berria ireki da + + Fitxa pribatu berria ireki da + + Testua arbelera kopiatu da + + Aldatu + diff --git a/components/feature/contextmenu/src/main/res/values-fi/strings.xml b/components/feature/contextmenu/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..b8f896399eb --- /dev/null +++ b/components/feature/contextmenu/src/main/res/values-fi/strings.xml @@ -0,0 +1,25 @@ + + + + Avaa linkki uuteen välilehteen + + Avaa linkki uuteen yksityiseen välilehteen + + Avaa kuva uuteen välilehteen + + Jaa linkki + + Kopioi linkki + + Kopioi kuvan sijainti + + Tallenna kuva + + Uusi välilehti avattu + + Uusi yksityinen välilehti avattu + + Teksti kopioitu leikepöydälle + + Vaihda + diff --git a/components/feature/contextmenu/src/main/res/values-pa-rIN/strings.xml b/components/feature/contextmenu/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..36f969e06bd --- /dev/null +++ b/components/feature/contextmenu/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,25 @@ + + + + ਨਵੀਂ ਟੈਬ ‘ਚ ਲਿੰਕ ਖੋਲ੍ਹੋ + + ਲਿੰਕ ਪ੍ਰਾਈਵੇਟ ਟੈਬ ‘ਚ ਖੋਲ੍ਹੋ + + ਚਿੱਤਰ ਨਵੀਂ ਟੈਬ ‘ਚ ਖੋਲ੍ਹੋ + + ਲਿੰਕ ਸਾਂਝਾ ਕਰੋ + + ਲਿੰਕ ਕਾਪੀ ਕਰੋ + + ਚਿੱਤਰ ਟਿਕਾਣਾ ਕਾਪੀ ਕਰੋ + + ਚਿੱਤਰ ਸੰਭਾਲੋ + + ਨਵੀਂ ਟੈਬ ਖੋਲ੍ਹੀ + + ਨਵੀਂ ਪ੍ਰਾਈਵੈਟ ਟੈਬ ਖੋਲ੍ਹੀ + + ਲਿਖਤ ਨੂੰ ਕਲਿੱਪਬੋਰਡ ‘ਚ ਨਕਲ ਕੀਤਾ + + ਬਦਲੋ + diff --git a/components/feature/customtabs/src/main/java/mozilla/components/feature/customtabs/CustomTabsToolbarFeature.kt b/components/feature/customtabs/src/main/java/mozilla/components/feature/customtabs/CustomTabsToolbarFeature.kt index 055663d9f0d..705a139ae9e 100644 --- a/components/feature/customtabs/src/main/java/mozilla/components/feature/customtabs/CustomTabsToolbarFeature.kt +++ b/components/feature/customtabs/src/main/java/mozilla/components/feature/customtabs/CustomTabsToolbarFeature.kt @@ -101,7 +101,7 @@ class CustomTabsToolbarFeature( toolbar.setBackgroundColor(color) toolbar.textColor = readableColor toolbar.titleColor = readableColor - toolbar.setSiteSecurityColor(readableColor to readableColor) + toolbar.siteSecurityColor = readableColor to readableColor toolbar.menuViewColor = readableColor window?.setStatusBarTheme(color) diff --git a/components/feature/customtabs/src/main/res/values-cs/strings.xml b/components/feature/customtabs/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..0a6027a0ec3 --- /dev/null +++ b/components/feature/customtabs/src/main/res/values-cs/strings.xml @@ -0,0 +1,5 @@ + + + Návrat do předchozí aplikace + Sdílet odkaz + diff --git a/components/feature/customtabs/src/main/res/values-es-rAR/strings.xml b/components/feature/customtabs/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..ec4b3f66e2d --- /dev/null +++ b/components/feature/customtabs/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,5 @@ + + + Volver a la aplicación anterior + Compartir enlace + diff --git a/components/feature/customtabs/src/main/res/values-eu/strings.xml b/components/feature/customtabs/src/main/res/values-eu/strings.xml new file mode 100644 index 00000000000..0494ad16ad9 --- /dev/null +++ b/components/feature/customtabs/src/main/res/values-eu/strings.xml @@ -0,0 +1,5 @@ + + + Itzuli aurreko aplikaziora + Partekatu lotura + diff --git a/components/feature/customtabs/src/main/res/values-fi/strings.xml b/components/feature/customtabs/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..9eb780ce768 --- /dev/null +++ b/components/feature/customtabs/src/main/res/values-fi/strings.xml @@ -0,0 +1,5 @@ + + + Palaa edelliseen sovellukseen + Jaa linkki + diff --git a/components/feature/customtabs/src/main/res/values-pa-rIN/strings.xml b/components/feature/customtabs/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..9a2a887cabf --- /dev/null +++ b/components/feature/customtabs/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,5 @@ + + + ਪਿਛਲੀ ਐਪ ‘ਤੇ ਜਾਓ + ਲਿੰਕ ਸਾਂਝਾ ਕਰੋ + diff --git a/components/feature/downloads/src/main/res/values-cs/strings.xml b/components/feature/downloads/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..714cc1b9207 --- /dev/null +++ b/components/feature/downloads/src/main/res/values-cs/strings.xml @@ -0,0 +1,19 @@ + + + + Stahování + + Stahování + + + Probíhá stahování + + + Stáhnout soubor + + Stáhnout + + Zrušit + + %1$s nemůže stáhnout tento typ souboru + diff --git a/components/feature/downloads/src/main/res/values-es-rAR/strings.xml b/components/feature/downloads/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..191c089b044 --- /dev/null +++ b/components/feature/downloads/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,18 @@ + + + + Descargas + + Descargando + + Descarga en proceso + + + Descargar archivo + + Descargar + + Cancelar + + %1$s no puede descargar este tipo de archivo + diff --git a/components/feature/downloads/src/main/res/values-eu/strings.xml b/components/feature/downloads/src/main/res/values-eu/strings.xml new file mode 100644 index 00000000000..7aa4ea0c635 --- /dev/null +++ b/components/feature/downloads/src/main/res/values-eu/strings.xml @@ -0,0 +1,18 @@ + + + + Deskargak + + Deskargatzen + + Deskargatzen ari da + + + Deskargatu fitxategia + + Deskargatu + + Utzi + + %1$s(e)k ezin du fitxategi mota hau deskargatu + diff --git a/components/feature/downloads/src/main/res/values-fi/strings.xml b/components/feature/downloads/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..eb670402cf8 --- /dev/null +++ b/components/feature/downloads/src/main/res/values-fi/strings.xml @@ -0,0 +1,18 @@ + + + + Lataukset + + Ladataan + + Lataus meneillään + + + Lataa tiedosto + + Lataa + + Peruuta + + %1$s ei voi ladata tätä tiedostotyyppiä + diff --git a/components/feature/downloads/src/main/res/values-pa-rIN/strings.xml b/components/feature/downloads/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..04b652a66bd --- /dev/null +++ b/components/feature/downloads/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,18 @@ + + + + ਡਾਊਨਲੋਡ + + ਡਾਊਨਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ + + ਡਾਊਨਲੋਡ ਜਾਰੀ ਹੈ + + + ਫਾਈਲ ਡਾਊਨਲੋਡ + + ਡਾਊਨਲੋਡ ਕਰੋ + + ਰੱਦ ਕਰੋ + + %1$s ਇਹ ਫਾਈਲ ਕਿਸਮ ਡਾਊਨਲੋਡ ਨਹੀਂ ਕਰ ਸਕਦਾ ਹੈ + diff --git a/components/feature/findinpage/src/main/res/values-cs/strings.xml b/components/feature/findinpage/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..f03ea222502 --- /dev/null +++ b/components/feature/findinpage/src/main/res/values-cs/strings.xml @@ -0,0 +1,24 @@ + + + + + Najít na stránce + + + %1$d/%2$d + + + %1$d z %2$d + + + Najít další + + + Najít předchozí + + + Ukončit hledání na stránce + + diff --git a/components/feature/findinpage/src/main/res/values-es-rAR/strings.xml b/components/feature/findinpage/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..77b5b926a64 --- /dev/null +++ b/components/feature/findinpage/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,24 @@ + + + + + Buscar en la página + + + %1$d/%2$d + + + %1$d de %2$d + + + Buscar resultado siguiente + + + Buscar resultado anterior + + + Descartar la búsqueda en la página + + diff --git a/components/feature/findinpage/src/main/res/values-eu/strings.xml b/components/feature/findinpage/src/main/res/values-eu/strings.xml new file mode 100644 index 00000000000..99aa6f857ac --- /dev/null +++ b/components/feature/findinpage/src/main/res/values-eu/strings.xml @@ -0,0 +1,24 @@ + + + + + Bilatu orrian + + + %2$d/%1$d + + + %2$d(e)tik %1$d + + + Bilatu hurrengo emaitza + + + Bilatu aurreko emaitza + + + Baztertu orrian bilatzea + + diff --git a/components/feature/findinpage/src/main/res/values-fi/strings.xml b/components/feature/findinpage/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..872cfd6b87b --- /dev/null +++ b/components/feature/findinpage/src/main/res/values-fi/strings.xml @@ -0,0 +1,17 @@ + + + + + Etsi sivulta + + + %1$d/%2$d + + + Etsi seuraava osuma + + + Etsi edellinen osuma + + diff --git a/components/feature/findinpage/src/main/res/values-pa-rIN/strings.xml b/components/feature/findinpage/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..f7483188f6b --- /dev/null +++ b/components/feature/findinpage/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,21 @@ + + + + + ਸਫ਼ੇ ‘ਚ ਲੱਭੋ + + + %1$d/%2$d + + + %2$d ‘ਚੋਂ %1$d + + + ਅਗਲਾ ਨਤੀਜਾ ਲੱਭੋ + + + ਪਿਛਲਾ ਨਤੀਜਾ ਲੱਭੋ + + diff --git a/components/feature/media/src/main/java/mozilla/components/feature/media/MediaFeature.kt b/components/feature/media/src/main/java/mozilla/components/feature/media/MediaFeature.kt index 3e96bf2c260..ef3eb76f7b5 100644 --- a/components/feature/media/src/main/java/mozilla/components/feature/media/MediaFeature.kt +++ b/components/feature/media/src/main/java/mozilla/components/feature/media/MediaFeature.kt @@ -5,6 +5,7 @@ package mozilla.components.feature.media import android.content.Context +import mozilla.components.feature.media.ext.hasMediaWithSufficientLongDuration import mozilla.components.feature.media.service.MediaService import mozilla.components.feature.media.state.MediaState import mozilla.components.feature.media.state.MediaStateMachine @@ -22,35 +23,46 @@ import mozilla.components.feature.media.state.MediaStateMachine class MediaFeature( private val context: Context ) { - private var serviceRunning = false + private var serviceStarted = false + private var observer = object : MediaStateMachine.Observer { + override fun onStateChanged(state: MediaState) { + notifyService(state) + } + } /** * Enables the feature. */ fun enable() { - MediaStateMachine.register(MediaObserver(this)) - } + MediaStateMachine.register(observer) - internal fun startMediaService() { - MediaService.updateState(context) - serviceRunning = true + // MediaStateMachine will only notify us about state changes but not pass the current state + // to us - which might already be "playing". So let's process the current state now. + notifyService(MediaStateMachine.state) } - internal fun stopMediaService() { - if (serviceRunning) { - MediaService.updateState(context) - } - } -} + @Suppress("LongMethod") + private fun notifyService(state: MediaState) { + when (state) { + is MediaState.Playing -> { + if (state.hasMediaWithSufficientLongDuration()) { + MediaService.updateState(context) + serviceStarted = true + } + } + + is MediaState.Paused -> { + if (serviceStarted) { + MediaService.updateState(context) + } + } -internal class MediaObserver( - private val feature: MediaFeature -) : MediaStateMachine.Observer { - override fun onStateChanged(state: MediaState) { - if (state is MediaState.Playing || state is MediaState.Paused) { - feature.startMediaService() - } else if (state is MediaState.None) { - feature.stopMediaService() + is MediaState.None -> { + if (serviceStarted) { + MediaService.updateState(context) + serviceStarted = false + } + } } } } diff --git a/components/feature/media/src/main/java/mozilla/components/feature/media/ext/MediaState.kt b/components/feature/media/src/main/java/mozilla/components/feature/media/ext/MediaState.kt index 5084c49e7ab..51703005bfa 100644 --- a/components/feature/media/src/main/java/mozilla/components/feature/media/ext/MediaState.kt +++ b/components/feature/media/src/main/java/mozilla/components/feature/media/ext/MediaState.kt @@ -4,11 +4,15 @@ package mozilla.components.feature.media.ext -import android.media.session.PlaybackState import android.support.v4.media.session.PlaybackStateCompat import mozilla.components.concept.engine.media.Media import mozilla.components.feature.media.state.MediaState +/** + * The minimum duration (in seconds) for media so that we bother with showing a media notification. + */ +private const val MINIMUM_DURATION_SECONDS = 5 + /** * Gets the list of [Media] associated with this [MediaState]. */ @@ -32,8 +36,8 @@ internal fun MediaState.toPlaybackState() = .setState( when (this) { is MediaState.Playing -> PlaybackStateCompat.STATE_PLAYING - is MediaState.Paused -> PlaybackState.STATE_PAUSED - is MediaState.None -> PlaybackState.STATE_NONE + is MediaState.Paused -> PlaybackStateCompat.STATE_PAUSED + is MediaState.None -> PlaybackStateCompat.STATE_NONE }, // Time state not exposed yet: // https://github.com/mozilla-mobile/android-components/issues/2458 @@ -63,3 +67,17 @@ internal fun MediaState.playIfPaused() { media.play() } } + +internal fun MediaState.hasMediaWithSufficientLongDuration(): Boolean { + getMedia().forEach { media -> + if (media.metadata.duration < 0) { + return true + } + + if (media.metadata.duration > MINIMUM_DURATION_SECONDS) { + return true + } + } + + return false +} diff --git a/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocus.kt b/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocus.kt index 6935fe826d7..3bce3879367 100644 --- a/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocus.kt +++ b/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocus.kt @@ -4,9 +4,6 @@ package mozilla.components.feature.media.focus -import android.content.Context -import android.media.AudioAttributes -import android.media.AudioFocusRequest import android.media.AudioManager import android.os.Build import mozilla.components.feature.media.ext.getMedia @@ -23,19 +20,34 @@ import mozilla.components.support.base.log.logger.Logger * https://developer.android.com/guide/topics/media-apps/audio-focus */ internal class AudioFocus( - private val context: Context + val audioManager: AudioManager ) : AudioManager.OnAudioFocusChangeListener { private val logger = Logger("AudioFocus") private var playDelayed = false private var resumeOnFocusGain = false + private val audioFocusController = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + AudioFocusControllerV26(audioManager, this) + } else { + AudioFocusControllerV21(audioManager, this) + } + @Synchronized fun request(state: MediaState) { - val result = requestAudioFocusCompat(context, this) + val result = audioFocusController.request() processAudioFocusResult(state, result) } + @Synchronized + fun abandon() { + audioFocusController.abandon() + playDelayed = false + resumeOnFocusGain = false + } + private fun processAudioFocusResult(state: MediaState, result: Int) { + logger.debug("processAudioFocusResult($result)") + when (result) { AudioManager.AUDIOFOCUS_REQUEST_GRANTED -> { // Granted: Gecko already started playing media. @@ -60,6 +72,8 @@ internal class AudioFocus( @Synchronized override fun onAudioFocusChange(focusChange: Int) { + logger.debug("onAudioFocusChange($focusChange)") + val state = MediaStateMachine.state when (focusChange) { @@ -93,32 +107,3 @@ internal class AudioFocus( } } } - -private fun requestAudioFocusCompat( - context: Context, - listener: AudioManager.OnAudioFocusChangeListener -): Int { - val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager - - return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - @Suppress("DEPRECATION") - audioManager.requestAudioFocus( - listener, - AudioManager.STREAM_MUSIC, - AudioManager.AUDIOFOCUS_GAIN - ) - } else { - audioManager.requestAudioFocus( - AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) - .setAudioAttributes( - AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_MEDIA) - .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) - .build() - ) - .setWillPauseWhenDucked(false) - .setOnAudioFocusChangeListener(listener) - .build() - ) - } -} diff --git a/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusController.kt b/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusController.kt new file mode 100644 index 00000000000..d8da73b9166 --- /dev/null +++ b/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusController.kt @@ -0,0 +1,13 @@ +/* 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 mozilla.components.feature.media.focus + +/** + * A controller that knows how to request and abandon audio focus. + */ +internal interface AudioFocusController { + fun request(): Int + fun abandon() +} diff --git a/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusControllerV21.kt b/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusControllerV21.kt new file mode 100644 index 00000000000..f9bfd5da509 --- /dev/null +++ b/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusControllerV21.kt @@ -0,0 +1,28 @@ +/* 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 mozilla.components.feature.media.focus + +import android.media.AudioManager + +/** + * [AudioFocusController] implementation for Android API 21+. + */ +@Suppress("DEPRECATION") +internal class AudioFocusControllerV21( + private val audioManager: AudioManager, + private val listener: AudioManager.OnAudioFocusChangeListener +) : AudioFocusController { + override fun request(): Int { + return audioManager.requestAudioFocus( + listener, + AudioManager.STREAM_MUSIC, + AudioManager.AUDIOFOCUS_GAIN + ) + } + + override fun abandon() { + audioManager.abandonAudioFocus(listener) + } +} diff --git a/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusControllerV26.kt b/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusControllerV26.kt new file mode 100644 index 00000000000..f5061f75dd3 --- /dev/null +++ b/components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusControllerV26.kt @@ -0,0 +1,40 @@ +/* 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 mozilla.components.feature.media.focus + +import android.annotation.TargetApi +import android.media.AudioAttributes +import android.media.AudioFocusRequest +import android.media.AudioManager + +import android.os.Build + +/** + * [AudioFocusController] implementation for Android API 26+. + */ +@TargetApi(Build.VERSION_CODES.O) +internal class AudioFocusControllerV26( + private val audioManager: AudioManager, + listener: AudioManager.OnAudioFocusChangeListener +) : AudioFocusController { + private val request = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) + .setAudioAttributes( + AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) + .build() + ) + .setWillPauseWhenDucked(false) + .setOnAudioFocusChangeListener(listener) + .build() + + override fun request(): Int { + return audioManager.requestAudioFocus(request) + } + + override fun abandon() { + audioManager.abandonAudioFocusRequest(request) + } +} diff --git a/components/feature/media/src/main/java/mozilla/components/feature/media/notification/MediaNotification.kt b/components/feature/media/src/main/java/mozilla/components/feature/media/notification/MediaNotification.kt index 062c0f06ace..5c2b5da26bc 100644 --- a/components/feature/media/src/main/java/mozilla/components/feature/media/notification/MediaNotification.kt +++ b/components/feature/media/src/main/java/mozilla/components/feature/media/notification/MediaNotification.kt @@ -16,8 +16,6 @@ import mozilla.components.feature.media.R import mozilla.components.feature.media.service.MediaService import mozilla.components.feature.media.state.MediaState -private const val NOTIFICATION_CHANNEL_ID = "Media" - /** * Helper to display a notification for web content playing media. */ @@ -27,35 +25,45 @@ internal class MediaNotification( /** * Creates a new [Notification] for the given [state]. */ + @Suppress("LongMethod") fun create(state: MediaState, mediaSession: MediaSessionCompat): Notification { - MediaNotificationChannel.ensureChannelExists(context) + val channel = MediaNotificationChannel.ensureChannelExists(context) val intent = context.packageManager.getLaunchIntentForPackage(context.packageName) val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0) val data = state.toNotificationData(context) - return NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) + val builder = NotificationCompat.Builder(context, channel) .setSmallIcon(data.icon) .setContentTitle(data.title) .setContentText(data.description) - .setContentIntent(pendingIntent) .setLargeIcon(data.largeIcon) .addAction(data.action) + .setPriority(NotificationCompat.PRIORITY_LOW) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setStyle(androidx.media.app.NotificationCompat.MediaStyle() .setMediaSession(mediaSession.sessionToken) .setShowActionsInCompactView(0)) - .build() + + if (!state.isForExternalApp()) { + // We only set a content intent if this media notification is not for an "external app" + // like a custom tab. Currently we can't route the user to that particular activity: + // https://github.com/mozilla-mobile/android-components/issues/3986 + builder.setContentIntent(pendingIntent) + } + + return builder.build() } } private fun MediaState.toNotificationData(context: Context): NotificationData { return when (this) { is MediaState.Playing -> NotificationData( - title = session.titleOrUrl, - description = session.url, + title = session.getTitleOrUrl(context), + description = session.nonPrivateUrl, icon = R.drawable.mozac_feature_media_playing, - largeIcon = session.icon, + largeIcon = session.nonPrivateIcon, action = NotificationCompat.Action.Builder( R.drawable.mozac_feature_media_action_pause, context.getString(R.string.mozac_feature_media_notification_action_pause), @@ -67,10 +75,10 @@ private fun MediaState.toNotificationData(context: Context): NotificationData { ).build() ) is MediaState.Paused -> NotificationData( - title = session.titleOrUrl, - description = session.url, + title = session.getTitleOrUrl(context), + description = session.nonPrivateUrl, icon = R.drawable.mozac_feature_media_paused, - largeIcon = session.icon, + largeIcon = session.nonPrivateIcon, action = NotificationCompat.Action.Builder( R.drawable.mozac_feature_media_action_play, context.getString(R.string.mozac_feature_media_notification_action_play), @@ -85,8 +93,17 @@ private fun MediaState.toNotificationData(context: Context): NotificationData { } } -private val Session.titleOrUrl - get() = if (title.isNotEmpty()) title else url +private fun Session.getTitleOrUrl(context: Context): String = when { + private -> context.getString(R.string.mozac_feature_media_notification_private_mode) + title.isNotEmpty() -> title + else -> url +} + +private val Session.nonPrivateUrl + get() = if (private) "" else url + +private val Session.nonPrivateIcon: Bitmap? + get() = if (private) null else icon private data class NotificationData( val title: String, @@ -95,3 +112,11 @@ private data class NotificationData( val largeIcon: Bitmap? = null, val action: NotificationCompat.Action ) + +private fun MediaState.isForExternalApp(): Boolean { + return when (this) { + is MediaState.Playing -> session.isCustomTabSession() + is MediaState.Paused -> session.isCustomTabSession() + is MediaState.None -> false + } +} diff --git a/components/feature/media/src/main/java/mozilla/components/feature/media/notification/MediaNotificationChannel.kt b/components/feature/media/src/main/java/mozilla/components/feature/media/notification/MediaNotificationChannel.kt index 8d05394cf83..2ab0c60b346 100644 --- a/components/feature/media/src/main/java/mozilla/components/feature/media/notification/MediaNotificationChannel.kt +++ b/components/feature/media/src/main/java/mozilla/components/feature/media/notification/MediaNotificationChannel.kt @@ -8,9 +8,11 @@ import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context import android.os.Build +import androidx.core.app.NotificationCompat import mozilla.components.feature.media.R -private const val NOTIFICATION_CHANNEL_ID = "Media" +private const val NOTIFICATION_CHANNEL_ID = "mozac.feature.media.generic" +private const val LEGACY_NOTIFICATION_CHANNEL_ID = "Media" internal object MediaNotificationChannel { /** @@ -27,10 +29,15 @@ internal object MediaNotificationChannel { val channel = NotificationChannel( NOTIFICATION_CHANNEL_ID, context.getString(R.string.mozac_feature_media_notification_channel), - NotificationManager.IMPORTANCE_DEFAULT + NotificationManager.IMPORTANCE_LOW ) + channel.setShowBadge(false) + channel.lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC notificationManager.createNotificationChannel(channel) + + // We can't just change a channel. So we had to re-create the channel with a new name. + notificationManager.deleteNotificationChannel(LEGACY_NOTIFICATION_CHANNEL_ID) } return NOTIFICATION_CHANNEL_ID diff --git a/components/feature/media/src/main/java/mozilla/components/feature/media/service/MediaService.kt b/components/feature/media/src/main/java/mozilla/components/feature/media/service/MediaService.kt index c3915f358eb..4648dcd913c 100644 --- a/components/feature/media/src/main/java/mozilla/components/feature/media/service/MediaService.kt +++ b/components/feature/media/src/main/java/mozilla/components/feature/media/service/MediaService.kt @@ -8,6 +8,7 @@ import android.app.Service import android.content.ComponentName import android.content.Context import android.content.Intent +import android.media.AudioManager import android.os.IBinder import android.support.v4.media.MediaMetadataCompat import android.support.v4.media.session.MediaSessionCompat @@ -36,7 +37,7 @@ internal class MediaService : Service() { private val logger = Logger("MediaService") private val notification = MediaNotification(this) private val mediaSession by lazy { MediaSessionCompat(this, "MozacMedia") } - private val audioFocus = AudioFocus(this) + private val audioFocus by lazy { AudioFocus(getSystemService(Context.AUDIO_SERVICE) as AudioManager) } override fun onCreate() { super.onCreate() @@ -102,6 +103,7 @@ internal class MediaService : Service() { } private fun shutdown() { + audioFocus.abandon() mediaSession.release() stopSelf() } diff --git a/components/feature/media/src/main/res/values-cs/strings.xml b/components/feature/media/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..3d03ef09b5e --- /dev/null +++ b/components/feature/media/src/main/res/values-cs/strings.xml @@ -0,0 +1,12 @@ + + + + Média + + + Kamera je zapnuta + + Mikrofon je zapnut + + Kamera a mikrofon jsou zapnuty + diff --git a/components/feature/media/src/main/res/values-es-rAR/strings.xml b/components/feature/media/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..44bb2668c0d --- /dev/null +++ b/components/feature/media/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,12 @@ + + + + Medios + + + La cámara está encendida + + El micrófono está encendido + + La cámara y el micrófono están encendidos + diff --git a/components/feature/media/src/main/res/values-eu/strings.xml b/components/feature/media/src/main/res/values-eu/strings.xml new file mode 100644 index 00000000000..16c663713a8 --- /dev/null +++ b/components/feature/media/src/main/res/values-eu/strings.xml @@ -0,0 +1,12 @@ + + + + Media + + + Kamera piztuta dago + + Mikrofonoa piztuta dago + + Kamera eta mikrofonoa piztuta daude + diff --git a/components/feature/media/src/main/res/values-fi/strings.xml b/components/feature/media/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..4c20dcc05e3 --- /dev/null +++ b/components/feature/media/src/main/res/values-fi/strings.xml @@ -0,0 +1,12 @@ + + + + Media + + + Kamera on päällä + + Mikrofoni on päällä + + Kamera ja mikrofoni ovat päällä + diff --git a/components/feature/media/src/main/res/values-pa-rIN/strings.xml b/components/feature/media/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..b3eaa295d36 --- /dev/null +++ b/components/feature/media/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,13 @@ + + + + + ਮੀਡਿਆ + + + ਕੈਮਰਾ ਚਾਲੂ ਹੈ + + ਮਾਈਕਰੋਫੋਨ ਚਾਲੂ ਹੈ + + ਕੈਮਰਾ ਤੇ ਮਾਈਕਰੋਫ਼ੋਨ ਚਾਲ ਹਨ + diff --git a/components/feature/media/src/main/res/values/strings.xml b/components/feature/media/src/main/res/values/strings.xml index 7b9a11ae9f9..b033297bd49 100644 --- a/components/feature/media/src/main/res/values/strings.xml +++ b/components/feature/media/src/main/res/values/strings.xml @@ -18,4 +18,7 @@ Pause + + + A site is playing media diff --git a/components/feature/media/src/test/java/mozilla/components/feature/media/MediaFeatureTest.kt b/components/feature/media/src/test/java/mozilla/components/feature/media/MediaFeatureTest.kt index db63e536cbd..87e397187f3 100644 --- a/components/feature/media/src/test/java/mozilla/components/feature/media/MediaFeatureTest.kt +++ b/components/feature/media/src/test/java/mozilla/components/feature/media/MediaFeatureTest.kt @@ -10,13 +10,13 @@ import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.concept.engine.media.Media import mozilla.components.feature.media.state.MediaStateMachine -import mozilla.components.feature.media.state.MockMedia import mozilla.components.support.test.any import mozilla.components.support.test.mock import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mockito.doReturn import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify @@ -45,6 +45,7 @@ class MediaFeatureTest { // A media object gets added to the session val media = MockMedia(Media.PlaybackState.UNKNOWN) + doReturn(30.0).`when`(media.metadata).duration session.media = listOf(media) media.playbackState = Media.PlaybackState.WAITING @@ -58,10 +59,42 @@ class MediaFeatureTest { verify(context).startService(any()) } + @Test + fun `Media with short duration will not start service`() { + val context: Context = mock() + val sessionManager = SessionManager(engine = mock()) + + MediaStateMachine.start(sessionManager) + + val feature = MediaFeature(context) + feature.enable() + + // A session gets added + val session = Session("https://www.mozilla.org") + sessionManager.add(session) + + // A media object gets added to the session + val media = MockMedia(Media.PlaybackState.UNKNOWN) + doReturn(2.0).`when`(media.metadata).duration + session.media = listOf(media) + + media.playbackState = Media.PlaybackState.WAITING + + // So far nothing has happened yet + verify(context, never()).startService(any()) + + // Media starts playing! + media.playbackState = Media.PlaybackState.PLAYING + + // Service still not started since duration is too short + verify(context, never()).startService(any()) + } + @Test fun `Media switching from playing to pause send Intent to service`() { val context: Context = mock() val media = MockMedia(Media.PlaybackState.PLAYING) + doReturn(30.0).`when`(media.metadata).duration val sessionManager = SessionManager(engine = mock()).apply { add(Session("https://www.mozilla.org").also { it.media = listOf(media) }) @@ -84,6 +117,7 @@ class MediaFeatureTest { fun `Media stopping to play will notify service`() { val context: Context = mock() val media = MockMedia(Media.PlaybackState.UNKNOWN) + doReturn(30.0).`when`(media.metadata).duration val sessionManager = SessionManager(engine = mock()).apply { add(Session("https://www.mozilla.org").also { it.media = listOf(media) }) diff --git a/components/feature/media/src/test/java/mozilla/components/feature/media/MockMedia.kt b/components/feature/media/src/test/java/mozilla/components/feature/media/MockMedia.kt new file mode 100644 index 00000000000..11a1bad77cd --- /dev/null +++ b/components/feature/media/src/test/java/mozilla/components/feature/media/MockMedia.kt @@ -0,0 +1,17 @@ +package mozilla.components.feature.media + +import mozilla.components.concept.engine.media.Media +import mozilla.components.support.test.mock + +internal class MockMedia( + initialState: PlaybackState +) : Media() { + init { + playbackState = initialState + } + + override val controller: Controller = + mock() + override val metadata: Metadata = + mock() +} \ No newline at end of file diff --git a/components/feature/media/src/test/java/mozilla/components/feature/media/focus/AudioFocusTest.kt b/components/feature/media/src/test/java/mozilla/components/feature/media/focus/AudioFocusTest.kt index a3de16f8988..5e696faf888 100644 --- a/components/feature/media/src/test/java/mozilla/components/feature/media/focus/AudioFocusTest.kt +++ b/components/feature/media/src/test/java/mozilla/components/feature/media/focus/AudioFocusTest.kt @@ -4,17 +4,15 @@ package mozilla.components.feature.media.focus -import android.content.Context import android.media.AudioManager import androidx.test.ext.junit.runners.AndroidJUnit4 import mozilla.components.browser.session.Session import mozilla.components.concept.engine.media.Media +import mozilla.components.feature.media.MockMedia import mozilla.components.feature.media.state.MediaState import mozilla.components.feature.media.state.MediaStateMachine -import mozilla.components.feature.media.state.MockMedia import mozilla.components.support.test.any import mozilla.components.support.test.mock -import mozilla.components.support.test.robolectric.testContext import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -22,18 +20,14 @@ import org.mockito.Mockito.doReturn import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions -import java.lang.IllegalStateException @RunWith(AndroidJUnit4::class) class AudioFocusTest { - private lateinit var context: Context private lateinit var audioManager: AudioManager @Before fun setUp() { - context = spy(testContext) audioManager = mock() - doReturn(audioManager).`when`(context).getSystemService(Context.AUDIO_SERVICE) } @Test @@ -45,7 +39,7 @@ class AudioFocusTest { Session("https://www.mozilla.org"), listOf(MockMedia(Media.PlaybackState.PLAYING)))) - val audioFocus = AudioFocus(context) + val audioFocus = AudioFocus(audioManager) audioFocus.request(state) verify(audioManager).requestAudioFocus(any()) @@ -63,7 +57,7 @@ class AudioFocusTest { Session("https://www.mozilla.org"), listOf(media))) - val audioFocus = AudioFocus(context) + val audioFocus = AudioFocus(audioManager) audioFocus.request(state) verify(audioManager).requestAudioFocus(any()) @@ -81,7 +75,7 @@ class AudioFocusTest { Session("https://www.mozilla.org"), listOf(media))) - val audioFocus = AudioFocus(context) + val audioFocus = AudioFocus(audioManager) audioFocus.request(state) verify(audioManager).requestAudioFocus(any()) @@ -95,7 +89,7 @@ class AudioFocusTest { doReturn(AudioManager.AUDIOFOCUS_REQUEST_GRANTED) .`when`(audioManager).requestAudioFocus(any()) - val audioFocus = AudioFocus(context) + val audioFocus = AudioFocus(audioManager) verifyNoMoreInteractions(media.controller) @@ -125,7 +119,7 @@ class AudioFocusTest { val media = MockMedia(Media.PlaybackState.PLAYING) - val audioFocus = AudioFocus(context) + val audioFocus = AudioFocus(audioManager) audioFocus.request(MediaState.Playing( Session("https://www.mozilla.org"), listOf(media))) @@ -150,7 +144,7 @@ class AudioFocusTest { Session("https://www.mozilla.org"), listOf(MockMedia(Media.PlaybackState.PLAYING)))) - val audioFocus = AudioFocus(context) + val audioFocus = AudioFocus(audioManager) audioFocus.request(state) } @@ -161,7 +155,7 @@ class AudioFocusTest { doReturn(AudioManager.AUDIOFOCUS_REQUEST_GRANTED) .`when`(audioManager).requestAudioFocus(any()) - val audioFocus = AudioFocus(context) + val audioFocus = AudioFocus(audioManager) verifyNoMoreInteractions(media.controller) @@ -179,7 +173,7 @@ class AudioFocusTest { val media = MockMedia(Media.PlaybackState.PLAYING) - val audioFocus = AudioFocus(context) + val audioFocus = AudioFocus(audioManager) audioFocus.request(MediaState.Playing( Session("https://www.mozilla.org"), listOf(media))) diff --git a/components/feature/media/src/test/java/mozilla/components/feature/media/notification/MediaNotificationTest.kt b/components/feature/media/src/test/java/mozilla/components/feature/media/notification/MediaNotificationTest.kt index e4afa2ad6d7..9d0c5d84470 100644 --- a/components/feature/media/src/test/java/mozilla/components/feature/media/notification/MediaNotificationTest.kt +++ b/components/feature/media/src/test/java/mozilla/components/feature/media/notification/MediaNotificationTest.kt @@ -9,6 +9,7 @@ import androidx.core.app.NotificationCompat import androidx.test.ext.junit.runners.AndroidJUnit4 import mozilla.components.browser.session.Session import mozilla.components.concept.engine.media.Media +import mozilla.components.feature.media.MockMedia import mozilla.components.feature.media.R import mozilla.components.feature.media.state.MediaState import mozilla.components.support.test.mock @@ -84,16 +85,44 @@ class MediaNotificationTest { assertEquals(R.drawable.mozac_feature_media_playing, notification.iconResource) } -} -internal class MockMedia( - initialState: PlaybackState -) : Media() { - init { - playbackState = initialState + @Test + fun `media notification for playing state in private mode`() { + val state = MediaState.Playing( + Session("https://www.mozilla.org", private = true).apply { + title = "Mozilla" + }, + listOf( + MockMedia(Media.PlaybackState.PLAYING) + )) + + val notification = MediaNotification(testContext) + .create(state, mock()) + + assertEquals("", notification.text) + assertEquals("A site is playing media", notification.title) + + assertEquals(R.drawable.mozac_feature_media_playing, notification.iconResource) } - override val controller: Controller = mock() + @Test + fun `media notification for paused state in private mode`() { + val state = MediaState.Paused( + Session("https://www.mozilla.org", private = true).apply { + title = "Mozilla" + }, + listOf( + MockMedia(Media.PlaybackState.PAUSE) + )) + + val notification = MediaNotification(testContext) + .create(state, mock()) + + assertEquals("", notification.text) + assertEquals("A site is playing media", notification.title) + + assertEquals(R.drawable.mozac_feature_media_paused, notification.iconResource) + } } private val Notification.text: String? diff --git a/components/feature/media/src/test/java/mozilla/components/feature/media/service/MediaServiceTest.kt b/components/feature/media/src/test/java/mozilla/components/feature/media/service/MediaServiceTest.kt index 4dca54237b8..a01d0c80266 100644 --- a/components/feature/media/src/test/java/mozilla/components/feature/media/service/MediaServiceTest.kt +++ b/components/feature/media/src/test/java/mozilla/components/feature/media/service/MediaServiceTest.kt @@ -9,8 +9,8 @@ import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.concept.engine.media.Media import mozilla.components.feature.media.MediaFeature +import mozilla.components.feature.media.MockMedia import mozilla.components.feature.media.state.MediaStateMachine -import mozilla.components.feature.media.state.MockMedia import mozilla.components.support.test.any import mozilla.components.support.test.mock import mozilla.components.support.test.robolectric.testContext diff --git a/components/feature/media/src/test/java/mozilla/components/feature/media/state/MediaStateMachineTest.kt b/components/feature/media/src/test/java/mozilla/components/feature/media/state/MediaStateMachineTest.kt index f0bb6c2ef90..553d0df24c1 100644 --- a/components/feature/media/src/test/java/mozilla/components/feature/media/state/MediaStateMachineTest.kt +++ b/components/feature/media/src/test/java/mozilla/components/feature/media/state/MediaStateMachineTest.kt @@ -7,6 +7,7 @@ package mozilla.components.feature.media.state import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.concept.engine.media.Media +import mozilla.components.feature.media.MockMedia import mozilla.components.support.test.mock import org.junit.After import org.junit.Assert.assertEquals @@ -156,13 +157,3 @@ class MediaStateMachineTest { assertEquals(MediaState.None, MediaStateMachine.state) } } - -class MockMedia( - initialState: PlaybackState -) : Media() { - init { - playbackState = initialState - } - - override val controller: Controller = mock() -} diff --git a/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptAbuserDetector.kt b/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptAbuserDetector.kt new file mode 100644 index 00000000000..3fd76051cdd --- /dev/null +++ b/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptAbuserDetector.kt @@ -0,0 +1,64 @@ +/* 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 mozilla.components.feature.prompts + +import java.util.Date + +/** + * Helper class to identify if a website has shown many dialogs. + */ +internal class PromptAbuserDetector { + + internal var jsAlertCount = 0 + internal var lastDialogShownAt = Date() + var shouldShowMoreDialogs = true + private set + + fun resetJSAlertAbuseState() { + jsAlertCount = 0 + shouldShowMoreDialogs = true + } + + fun updateJSDialogAbusedState() { + if (!areDialogsAbusedByTime()) { + jsAlertCount = 0 + } + ++jsAlertCount + lastDialogShownAt = Date() + } + + fun userWantsMoreDialogs(checkBox: Boolean) { + shouldShowMoreDialogs = checkBox + } + + fun areDialogsBeingAbused(): Boolean { + return areDialogsAbusedByTime() || areDialogsAbusedByCount() + } + + internal fun areDialogsAbusedByTime(): Boolean { + return if (jsAlertCount == 0) { + false + } else { + val now = Date() + val diffInSeconds = (now.time - lastDialogShownAt.time) / SECOND_MS + diffInSeconds < MAX_SUCCESSIVE_DIALOG_SECONDS_LIMIT + } + } + + internal fun areDialogsAbusedByCount(): Boolean { + return jsAlertCount > MAX_SUCCESSIVE_DIALOG_COUNT + } + + companion object { + // Maximum number of successive dialogs before we prompt users to disable dialogs. + internal const val MAX_SUCCESSIVE_DIALOG_COUNT: Int = 2 + + // Minimum time required between dialogs in seconds before enabling the stop dialog. + internal const val MAX_SUCCESSIVE_DIALOG_SECONDS_LIMIT: Int = 3 + + // Number of milliseconds in 1 second. + internal const val SECOND_MS: Int = 1000 + } +} diff --git a/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt b/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt index 313177320ea..8cb60b86b44 100644 --- a/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt +++ b/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt @@ -68,6 +68,7 @@ internal const val FRAGMENT_TAG = "mozac_feature_prompt_dialog" * need to be requested before a prompt (e.g. a file picker) can be displayed. * Once the request is completed, [onPermissionsResult] needs to be invoked. */ +@Suppress("TooManyFunctions") class PromptFeature( private val activity: Activity? = null, private val fragment: Fragment? = null, @@ -76,6 +77,7 @@ class PromptFeature( private val fragmentManager: FragmentManager, onNeedToRequestPermissions: OnNeedToRequestPermissions ) : LifecycleAwareFeature, PermissionsFeature { + internal val promptAbuserDetector = PromptAbuserDetector() constructor( activity: Activity, @@ -123,6 +125,7 @@ class PromptFeature( * and displays a dialog when needed. */ override fun start() { + promptAbuserDetector.resetJSAlertAbuseState() observer.observeIdOrSelected(sessionId) fragmentManager.findFragmentByTag(FRAGMENT_TAG)?.let { fragment -> @@ -208,7 +211,11 @@ class PromptFeature( when (it) { is TimeSelection -> it.onConfirm(value as Date) is Color -> it.onConfirm(value as String) - is Alert -> it.onConfirm(value as Boolean) + is Alert -> { + val shouldNotShowMoreDialogs = value as Boolean + promptAbuserDetector.userWantsMoreDialogs(!shouldNotShowMoreDialogs) + it.onConfirm(!shouldNotShowMoreDialogs) + } is SingleChoice -> it.onConfirm(value as Choice) is MenuChoice -> it.onConfirm(value as Choice) is PromptRequest.Popup -> it.onAllow() @@ -221,18 +228,23 @@ class PromptFeature( is TextPrompt -> { val pair = value as Pair - it.onConfirm(pair.first, pair.second) + + val shouldNotShowMoreDialogs = pair.first + promptAbuserDetector.userWantsMoreDialogs(!shouldNotShowMoreDialogs) + it.onConfirm(!shouldNotShowMoreDialogs, pair.second) } is PromptRequest.Confirm -> { val pair = value as Pair + val isCheckBoxChecked = pair.first + promptAbuserDetector.userWantsMoreDialogs(!isCheckBoxChecked) when (pair.second) { MultiButtonDialogFragment.ButtonType.POSITIVE -> - it.onConfirmPositiveButton(pair.first) + it.onConfirmPositiveButton(!isCheckBoxChecked) MultiButtonDialogFragment.ButtonType.NEGATIVE -> - it.onConfirmNegativeButton(pair.first) + it.onConfirmNegativeButton(!isCheckBoxChecked) MultiButtonDialogFragment.ButtonType.NEUTRAL -> - it.onConfirmNeutralButton(pair.first) + it.onConfirmNeutralButton(!isCheckBoxChecked) } } } @@ -295,7 +307,12 @@ class PromptFeature( is Alert -> { with(promptRequest) { - AlertDialogFragment.newInstance(session.id, title, message, hasShownManyDialogs) + AlertDialogFragment.newInstance( + session.id, + title, + message, + promptAbuserDetector.areDialogsBeingAbused() + ) } } @@ -321,7 +338,13 @@ class PromptFeature( is TextPrompt -> { with(promptRequest) { - TextPromptDialogFragment.newInstance(session.id, title, inputLabel, inputValue, hasShownManyDialogs) + TextPromptDialogFragment.newInstance( + session.id, + title, + inputLabel, + inputValue, + promptAbuserDetector.areDialogsBeingAbused() + ) } } @@ -360,13 +383,24 @@ class PromptFeature( is PromptRequest.Confirm -> { with(promptRequest) { + val positiveButton = if (positiveButtonTitle.isEmpty()) { + context.getString(R.string.mozac_feature_prompts_ok) + } else { + positiveButtonTitle + } + val negativeButton = if (positiveButtonTitle.isEmpty()) { + context.getString(R.string.mozac_feature_prompts_cancel) + } else { + positiveButtonTitle + } + MultiButtonDialogFragment.newInstance( session.id, title, message, - hasShownManyDialogs, - positiveButtonTitle, - negativeButtonTitle, + promptAbuserDetector.areDialogsBeingAbused(), + positiveButton, + negativeButton, neutralButtonTitle ) } @@ -376,7 +410,27 @@ class PromptFeature( } dialog.feature = this - dialog.show(fragmentManager, FRAGMENT_TAG) + + if (canShowThisPrompt(promptRequest)) { + dialog.show(fragmentManager, FRAGMENT_TAG) + } else { + (promptRequest as PromptRequest.Dismissible).onDismiss() + } + promptAbuserDetector.updateJSDialogAbusedState() + } + + private fun canShowThisPrompt(promptRequest: PromptRequest): Boolean { + return when (promptRequest) { + is SingleChoice, + is MultipleChoice, + is MenuChoice, + is TimeSelection, + is File, + is Color, + is Authentication, + is PromptRequest.Popup -> true + is Alert, is TextPrompt, is PromptRequest.Confirm -> promptAbuserDetector.shouldShowMoreDialogs + } } /** @@ -392,6 +446,12 @@ class PromptFeature( feature.onPromptRequested(session, promptRequest) return false } + + override fun onLoadingStateChanged(session: Session, loading: Boolean) { + if (!loading) { + feature.promptAbuserDetector.resetJSAlertAbuseState() + } + } } companion object { diff --git a/components/feature/prompts/src/main/res/values-cs/strings.xml b/components/feature/prompts/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..2f0a941c1c7 --- /dev/null +++ b/components/feature/prompts/src/main/res/values-cs/strings.xml @@ -0,0 +1,28 @@ + + + + OK + + Zrušit + + Zabránit stránce ve vytváření dalších dialogů + + Nastavit + + Vymazat + + Přihlášení + + Uživatelské jméno + + Heslo + + + Štítek vstupního pole pro zadání textu + + Vyberte barvu + + Povolit + + Zakázat + diff --git a/components/feature/prompts/src/main/res/values-es-rAR/strings.xml b/components/feature/prompts/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..29ace017748 --- /dev/null +++ b/components/feature/prompts/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,28 @@ + + + + Aceptar + + Cancelar + + Impedir que esta página cree diálogos adicionales + + Establecer + + Eliminar + + Iniciar sesión + + Nombre de usuario + + Contraseña + + + Etiqueta para ingresar un campo de entrada de texto + + Elija un color + + Permitir + + Denegar + diff --git a/components/feature/prompts/src/main/res/values-eu/strings.xml b/components/feature/prompts/src/main/res/values-eu/strings.xml new file mode 100644 index 00000000000..e5f9f16368b --- /dev/null +++ b/components/feature/prompts/src/main/res/values-eu/strings.xml @@ -0,0 +1,28 @@ + + + + Ados + + Utzi + + Eragotzi orri honi elkarrizketa-koadro gehiago sortzea + + Ezarri + + Garbitu + + Hasi saioa + + Erabiltzaile-izena + + Pasahitza + + + Testua idazteko eremua sartzeko etiketa + + Aukeratu kolore bat + + Baimendu + + Ukatu + diff --git a/components/feature/prompts/src/main/res/values-fi/strings.xml b/components/feature/prompts/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..5e5e8f42467 --- /dev/null +++ b/components/feature/prompts/src/main/res/values-fi/strings.xml @@ -0,0 +1,21 @@ + + + + OK + + Peruuta + + Estä tätä sivua luomasta lisäikkunoita + + Kirjaudu sisään + + Käyttäjätunnus + + Salasana + + Valitse väri + + Salli + + Estä + diff --git a/components/feature/prompts/src/main/res/values-pa-rIN/strings.xml b/components/feature/prompts/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..f9e159772b6 --- /dev/null +++ b/components/feature/prompts/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,28 @@ + + + + ਠੀਕ ਹੈ + + ਰੱਦ ਕਰੋ + + ਇਸ ਸਫ਼ੇ ਨੂੰ ਹੋਰ ਡਾਈਲਾਗ ਬਣਾਉਣ ਤੋਂ ਰੋਕੋ + + ਨਿਯਤ ਕਰੋ + + ਸਾਫ਼ ਕਰੋ + + ਸਾਈਨ ਇਨ + + ਵਰਤੋਂਕਾਰ ਨਾਂ + + ਪਾਸਵਰਡ + + + ਲਿਖਤ ਦਰਜ ਕਰਨ ਲਈ ਖੇਤਰ ਲਈ ਲੇਬਲ + + ਰੰਗ ਚੁਣੋ + + ਆਗਿਆ ਦਿਓ + + ਇਨਕਾਰ ਕਰੋ + diff --git a/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/PromptFeatureTest.kt b/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/PromptFeatureTest.kt index efd8771bc04..150bf008d07 100644 --- a/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/PromptFeatureTest.kt +++ b/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/PromptFeatureTest.kt @@ -33,6 +33,7 @@ import mozilla.components.support.base.observer.Consumable import mozilla.components.support.test.any import mozilla.components.support.test.mock import mozilla.components.support.test.robolectric.testContext +import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -64,6 +65,11 @@ class PromptFeatureTest { promptFeature = PromptFeature(mock(), mockSessionManager, null, mockFragmentManager) { } } + @After + fun tearDown() { + promptFeature.promptAbuserDetector.resetJSAlertAbuseState() + } + @Test fun `PromptFeatures act on a given session or the selected session`() { val session = Session("custom-tab") @@ -687,6 +693,57 @@ class PromptFeatureTest { session.promptRequest = Consumable.from(promptRequest) } + @Test + fun `When dialogs are been abused prompts must not be allow to be displayed`() { + val session = getSelectedSession() + var onDismissWasCalled: Boolean + val onDismiss = { onDismissWasCalled = true } + val mockAlertRequest = Alert("", "", false, onDismiss, {}) + val mockTextRequest = TextPrompt("", "", "", false, onDismiss) { _, _ -> } + val mockConfirmRequest = + PromptRequest.Confirm("", "", false, "", "", "", {}, {}, {}, onDismiss) + + val promptRequest = arrayOf(mockAlertRequest, mockTextRequest, mockConfirmRequest) + + stubContext() + promptFeature.start() + promptFeature.promptAbuserDetector.userWantsMoreDialogs(false) + + promptRequest.forEach { _ -> + onDismissWasCalled = false + session.promptRequest = Consumable.from(mockAlertRequest) + + verify(mockFragmentManager, never()).beginTransaction() + assertTrue(onDismissWasCalled) + } + } + + @Test + fun `When dialogs are been abused but the page is refreshed prompts must be allow to be displayed`() { + val session = getSelectedSession() + var onDismissWasCalled = false + val onDismiss = { onDismissWasCalled = true } + val mockAlertRequest = Alert("", "", false, onDismiss, {}) + + stubContext() + promptFeature.start() + promptFeature.promptAbuserDetector.userWantsMoreDialogs(false) + + session.promptRequest = Consumable.from(mockAlertRequest) + + verify(mockFragmentManager, never()).beginTransaction() + assertTrue(onDismissWasCalled) + + session.notifyObservers { + onLoadingStateChanged(session, false) + } + + session.promptRequest = Consumable.from(mockAlertRequest) + + verify(mockFragmentManager).beginTransaction() + assertTrue(promptFeature.promptAbuserDetector.shouldShowMoreDialogs) + } + private fun getSelectedSession(): Session { val session = Session("") mockSessionManager.add(session) diff --git a/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt b/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt index 212fa5fc11e..864d5b12af2 100644 --- a/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt +++ b/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt @@ -205,6 +205,11 @@ class AutoPushFeature( /** * Returns subscription information for the push type if available. + * + * Implementation notes: We need to connect this to the device constellation so that we update our subscriptions + * when notified by FxA. See [#3859][0]. + * + * [0]: https://github.com/mozilla-mobile/android-components/issues/3859 */ fun unsubscribeForType(type: PushType) { DeliveryManager.with(connection) { @@ -231,6 +236,11 @@ class AutoPushFeature( /** * Deletes the registration token locally so that it forces the service to get a new one the * next time hits it's messaging server. + * + * Implementation notes: This shouldn't need to be used unless we're certain. When we introduce + * [a polling service][0] to check if endpoints are expired, we would invoke this. + * + * [0]: https://github.com/mozilla-mobile/android-components/issues/3173 */ fun forceRegistrationRenewal() { // Remove the cached token we have. diff --git a/components/feature/readerview/src/main/res/values-cs/strings.xml b/components/feature/readerview/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..473300dc971 --- /dev/null +++ b/components/feature/readerview/src/main/res/values-cs/strings.xml @@ -0,0 +1,29 @@ + + + + Bezpatkové + + Bezpatkové písmo + + Patkové + + Patkové písmo + + + Zmenšení velikost písma + + + Zvětšení velikost písma + + Tmavé + + Tmavé barvy + + Sépie + + Sépiové barvy + + Světlé + + Světlé barvy + diff --git a/components/feature/readerview/src/main/res/values-es-rAR/strings.xml b/components/feature/readerview/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..e37f09be5fc --- /dev/null +++ b/components/feature/readerview/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,29 @@ + + + + Sans-serif + + Fuente Sans Serif + + Serif + + Fuente Serif + + + Disminución del tamaño de la fuente + + + Aumento del tamaño de la fuente + + Oscuro + + Esquema de color oscuro + + Sepia + + Esquema de color sepia + + Claro + + Esquema de color claro + diff --git a/components/feature/readerview/src/main/res/values-eu/strings.xml b/components/feature/readerview/src/main/res/values-eu/strings.xml new file mode 100644 index 00000000000..df496fd857e --- /dev/null +++ b/components/feature/readerview/src/main/res/values-eu/strings.xml @@ -0,0 +1,29 @@ + + + + Sans serif + + Sans Serif letra-tipoa + + Serif + + Serif letra-tipoa + + + Txikiagotu letra tamaina + + + Handiagotu letra tamaina + + Iluna + + Kolore-eskema iluna + + Sepia + + Sepia kolore-eskema + + Argia + + Kolore-eskema argia + diff --git a/components/feature/readerview/src/main/res/values-fi/strings.xml b/components/feature/readerview/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..bfca791af6d --- /dev/null +++ b/components/feature/readerview/src/main/res/values-fi/strings.xml @@ -0,0 +1,16 @@ + + + + + Tumma + + Tumma väriteema + + Seepia + + Seepiamainen väriteema + + Vaalea + + Vaalea väriteema + diff --git a/components/feature/readerview/src/main/res/values-pa-rIN/strings.xml b/components/feature/readerview/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..69275e8e21a --- /dev/null +++ b/components/feature/readerview/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + ਸਨਜ ਸੈਰੀਫ਼ + + ਸਨਜ ਸੈਰੀਫ਼ ਫ਼ੋਂਟ + + ਸੈਰੀਫ਼ + + ਸੈਰੀਫ਼ ਫ਼ੋਂਟ + + + ਗੂੜ੍ਹਾ + + ਹਲਕਾ + + ਹਲਕੀ ਰੰਗ ਸਕੀਮ + diff --git a/components/feature/sendtab/build.gradle b/components/feature/sendtab/build.gradle index d3d088bf3c5..d3d31ff59a9 100644 --- a/components/feature/sendtab/build.gradle +++ b/components/feature/sendtab/build.gradle @@ -31,7 +31,10 @@ dependencies { implementation project(':service-firefox-accounts') implementation project(':support-ktx') implementation project(':support-base') + implementation project(':concept-push') + implementation project(':feature-push') + implementation Dependencies.androidx_work_runtime implementation Dependencies.kotlin_stdlib implementation Dependencies.kotlin_coroutines diff --git a/components/feature/sendtab/src/main/java/mozilla/components/feature/sendtab/SendTabFeature.kt b/components/feature/sendtab/src/main/java/mozilla/components/feature/sendtab/SendTabFeature.kt new file mode 100644 index 00000000000..8b4541e2b32 --- /dev/null +++ b/components/feature/sendtab/src/main/java/mozilla/components/feature/sendtab/SendTabFeature.kt @@ -0,0 +1,140 @@ +/* + * 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 mozilla.components.feature.sendtab + +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.ProcessLifecycleOwner +import mozilla.components.concept.push.Bus +import mozilla.components.concept.push.PushService +import mozilla.components.concept.sync.AccountObserver as SyncAccountObserver +import mozilla.components.concept.sync.Device +import mozilla.components.concept.sync.DeviceConstellation +import mozilla.components.concept.sync.DeviceEvent +import mozilla.components.concept.sync.DeviceEventsObserver +import mozilla.components.concept.sync.DevicePushSubscription +import mozilla.components.concept.sync.OAuthAccount +import mozilla.components.concept.sync.TabData +import mozilla.components.feature.push.AutoPushFeature +import mozilla.components.feature.push.AutoPushSubscription +import mozilla.components.feature.push.PushSubscriptionObserver +import mozilla.components.feature.push.PushType +import mozilla.components.service.fxa.manager.FxaAccountManager +import mozilla.components.support.base.log.logger.Logger + +/** + * A feature that uses the [FxaAccountManager] to send and receive tabs with optional push support + * for receiving tabs from the [AutoPushFeature] and a [PushService]. + * + * If the push components are not used, the feature can still function while tabs would only be + * received when refreshing the device state. + * + * @param accountManager Firefox account manager. + * @param pushFeature The [AutoPushFeature] if that is setup for observing push events. + * @param owner Android lifecycle owner for the observers. Defaults to the [ProcessLifecycleOwner] + * so that we can always observe events throughout the application lifecycle. + * @param autoPause whether or not the observer should automatically be + * paused/resumed with the bound lifecycle. + * @param onTabsReceived the callback invoked with new tab(s) are received. + */ +class SendTabFeature( + accountManager: FxaAccountManager, + pushFeature: AutoPushFeature? = null, + owner: LifecycleOwner = ProcessLifecycleOwner.get(), + autoPause: Boolean = false, + onTabsReceived: (Device?, List) -> Unit +) { + init { + val accountObserver = AccountObserver(pushFeature) + val pushObserver = PushObserver(accountManager) + val deviceObserver = DeviceObserver(onTabsReceived) + + // Always observe the account for device events. + accountManager.registerForDeviceEvents(deviceObserver, owner, autoPause) + + pushFeature?.apply { + registerForPushMessages(PushType.Services, pushObserver, owner, autoPause) + registerForSubscriptions(pushObserver, owner, autoPause) + + // observe the account only if we have the push feature (service is optional) + accountManager.register(accountObserver, owner, autoPause) + } + } +} + +internal class PushObserver( + private val accountManager: FxaAccountManager +) : Bus.Observer, PushSubscriptionObserver { + private val logger = Logger("PushObserver") + + override fun onSubscriptionAvailable(subscription: AutoPushSubscription) { + logger.debug("Received new push subscription from $subscription.type") + + if (subscription.type == PushType.Services) { + accountManager.withConstellation { + it.setDevicePushSubscriptionAsync( + DevicePushSubscription( + endpoint = subscription.endpoint, + publicKey = subscription.publicKey, + authKey = subscription.authKey + ) + ) + } + } + } + + override fun onEvent(type: PushType, message: String) { + logger.debug("Received new push message for $type") + + accountManager.withConstellation { + it.processRawEventAsync(message) + } + } +} + +internal class DeviceObserver( + private val onTabsReceived: (Device?, List) -> Unit +) : DeviceEventsObserver { + private val logger = Logger("DeviceObserver") + + override fun onEvents(events: List) { + events.asSequence() + .filterIsInstance() + .forEach { event -> + logger.debug("Showing ${event.entries.size} tab(s) received from deviceID=${event.from?.id}") + + onTabsReceived(event.from, event.entries) + } + } +} + +internal class AccountObserver( + private val feature: AutoPushFeature? +) : SyncAccountObserver { + private val logger = Logger("AccountObserver") + + override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { + // We need a new subscription only when we have a new account. + // This is removed when an account logs out. + if (newAccount) { + logger.debug("Subscribing for ${PushType.Services} events.") + + feature?.subscribeForType(PushType.Services) + } + } + + override fun onLoggedOut() { + logger.debug("Unsubscribing for ${PushType.Services} events.") + + feature?.unsubscribeForType(PushType.Services) + } +} + +internal inline fun FxaAccountManager.withConstellation(block: (DeviceConstellation) -> Unit) { + authenticatedAccount()?.let { + block(it.deviceConstellation()) + } +} diff --git a/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/AccountObserverTest.kt b/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/AccountObserverTest.kt new file mode 100644 index 00000000000..f92c9107291 --- /dev/null +++ b/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/AccountObserverTest.kt @@ -0,0 +1,72 @@ +/* + * 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 mozilla.components.feature.sendtab + +import mozilla.components.feature.push.AutoPushFeature +import mozilla.components.feature.push.PushType +import mozilla.components.support.test.mock +import org.junit.Test +import org.mockito.Mockito.verify +import org.mockito.Mockito.verifyNoMoreInteractions + +class AccountObserverTest { + @Test + fun `feature and service invoked on new account authenticated`() { + val feature: AutoPushFeature = mock() + val observer = AccountObserver(feature) + + observer.onAuthenticated(mock(), true) + + verify(feature).subscribeForType(PushType.Services) + + verifyNoMoreInteractions(feature) + } + + @Test + fun `feature and service are not invoked if not provided`() { + val feature: AutoPushFeature = mock() + val observer = AccountObserver(null) + + observer.onAuthenticated(mock(), true) + observer.onLoggedOut() + + verifyNoMoreInteractions(feature) + } + + @Test + fun `feature does not subscribe if not a new account`() { + val feature: AutoPushFeature = mock() + val observer = AccountObserver(feature) + + observer.onAuthenticated(mock(), false) + + verifyNoMoreInteractions(feature) + } + + @Test + fun `feature and service invoked on logout`() { + val feature: AutoPushFeature = mock() + val observer = AccountObserver(feature) + + observer.onLoggedOut() + + verify(feature).unsubscribeForType(PushType.Services) + + verifyNoMoreInteractions(feature) + } + + @Test + fun `feature and service not invoked for any other callback`() { + val feature: AutoPushFeature = mock() + val observer = AccountObserver(feature) + + observer.onAuthenticationProblems() + observer.onProfileUpdated(mock()) + + verifyNoMoreInteractions(feature) + } +} \ No newline at end of file diff --git a/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/DeviceObserverTest.kt b/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/DeviceObserverTest.kt new file mode 100644 index 00000000000..4add6e0e925 --- /dev/null +++ b/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/DeviceObserverTest.kt @@ -0,0 +1,49 @@ +/* + * 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 mozilla.components.feature.sendtab + +import mozilla.components.concept.sync.Device +import mozilla.components.concept.sync.DeviceEvent +import mozilla.components.concept.sync.TabData +import mozilla.components.support.test.any +import mozilla.components.support.test.eq +import mozilla.components.support.test.mock +import org.junit.Test +import org.mockito.Mockito.times +import org.mockito.Mockito.verify + +class DeviceObserverTest { + @Test + fun `events are delivered successfully`() { + val callback: (Device?, List) -> Unit = mock() + val observer = DeviceObserver(callback) + val events = listOf(DeviceEvent.TabReceived(mock(), mock())) + + observer.onEvents(events) + + verify(callback).invoke(any(), any()) + + observer.onEvents(listOf(DeviceEvent.TabReceived(null, mock()))) + + verify(callback).invoke(eq(null), any()) + } + + @Test + fun `only TabReceived events are delivered`() { + // we don't have other event types right now so this is a basic test. + val callback: (Device?, List) -> Unit = mock() + val observer = DeviceObserver(callback) + val events = listOf( + DeviceEvent.TabReceived(mock(), mock()), + DeviceEvent.TabReceived(mock(), mock()) + ) + + observer.onEvents(events) + + verify(callback, times(2)).invoke(any(), any()) + } +} \ No newline at end of file diff --git a/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/PushObserverTest.kt b/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/PushObserverTest.kt new file mode 100644 index 00000000000..3956ad61683 --- /dev/null +++ b/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/PushObserverTest.kt @@ -0,0 +1,90 @@ +/* + * 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 mozilla.components.feature.sendtab + +import mozilla.components.concept.sync.DeviceConstellation +import mozilla.components.concept.sync.OAuthAccount +import mozilla.components.feature.push.AutoPushSubscription +import mozilla.components.feature.push.PushType +import mozilla.components.service.fxa.manager.FxaAccountManager +import mozilla.components.support.test.any +import mozilla.components.support.test.mock +import org.junit.Test +import org.mockito.Mockito.`when` +import org.mockito.Mockito.never +import org.mockito.Mockito.verify + +class PushObserverTest { + + @Test + fun `subscription is forwarded to account manager`() { + val manager: FxaAccountManager = mock() + val account: OAuthAccount = mock() + val constellation: DeviceConstellation = mock() + val observer = PushObserver(manager) + val subscription = generateSubscription(PushType.Services) + + `when`(manager.authenticatedAccount()).thenReturn(account) + `when`(account.deviceConstellation()).thenReturn(constellation) + + observer.onSubscriptionAvailable(subscription) + + verify(constellation).setDevicePushSubscriptionAsync(any()) + } + + @Test + fun `subscription is not forwarded if it's not for fxa`() { + val manager: FxaAccountManager = mock() + val account: OAuthAccount = mock() + val constellation: DeviceConstellation = mock() + val observer = PushObserver(manager) + val subscription = generateSubscription(PushType.WebPush) + + `when`(manager.authenticatedAccount()).thenReturn(account) + `when`(account.deviceConstellation()).thenReturn(constellation) + + observer.onSubscriptionAvailable(subscription) + + verify(constellation, never()).setDevicePushSubscriptionAsync(any()) + } + + @Test + fun `messages are forwarded to account manager`() { + val manager: FxaAccountManager = mock() + val account: OAuthAccount = mock() + val constellation: DeviceConstellation = mock() + val observer = PushObserver(manager) + + `when`(manager.authenticatedAccount()).thenReturn(account) + `when`(account.deviceConstellation()).thenReturn(constellation) + + observer.onEvent(PushType.Services, "foobar") + + verify(constellation).processRawEventAsync("foobar") + } + + @Test + fun `account manager is not invoked if no account is available`() { + val manager: FxaAccountManager = mock() + val constellation: DeviceConstellation = mock() + val observer = PushObserver(manager) + val subscription = generateSubscription(PushType.Services) + + observer.onSubscriptionAvailable(subscription) + observer.onEvent(PushType.Services, "foobar") + + verify(constellation, never()).setDevicePushSubscriptionAsync(any()) + verify(constellation, never()).processRawEventAsync("foobar") + } + + private fun generateSubscription(type: PushType) = AutoPushSubscription( + type = type, + endpoint = "https://endpoint.push.mozilla.com", + publicKey = "1234", + authKey = "myKey" + ) +} \ No newline at end of file diff --git a/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/SendTabFeatureKtTest.kt b/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/SendTabFeatureKtTest.kt new file mode 100644 index 00000000000..2095d552785 --- /dev/null +++ b/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/SendTabFeatureKtTest.kt @@ -0,0 +1,78 @@ +/* + * 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 mozilla.components.feature.sendtab + +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runBlockingTest +import mozilla.components.concept.sync.DeviceConstellation +import mozilla.components.concept.sync.OAuthAccount +import mozilla.components.feature.push.AutoPushFeature +import mozilla.components.service.fxa.manager.FxaAccountManager +import mozilla.components.support.test.any +import mozilla.components.support.test.mock +import org.junit.Test +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.Mockito.`when` +import org.mockito.Mockito.never +import org.mockito.Mockito.verify + +@ExperimentalCoroutinesApi +class SendTabFeatureKtTest { + @Test + fun `feature register all observers`() = runBlockingTest { + val accountManager: FxaAccountManager = mock() + val pushFeature: AutoPushFeature = mock() + + SendTabFeature( + accountManager = accountManager, + pushFeature = pushFeature, + onTabsReceived = mock() + ) + + verify(accountManager).register(any(), any(), anyBoolean()) + verify(accountManager).registerForDeviceEvents(any(), any(), anyBoolean()) + + verify(pushFeature).registerForPushMessages(any(), any(), any(), anyBoolean()) + verify(pushFeature).registerForSubscriptions(any(), any(), anyBoolean()) + } + + @Test + fun `feature registers only the device observer`() { + val accountManager: FxaAccountManager = mock() + val pushFeature: AutoPushFeature = mock() + + SendTabFeature( + accountManager = accountManager, + onTabsReceived = mock() + ) + + verify(accountManager).registerForDeviceEvents(any(), any(), anyBoolean()) + + verify(accountManager, never()).register(any(), any(), anyBoolean()) + verify(pushFeature, never()).registerForPushMessages(any(), any(), any(), anyBoolean()) + verify(pushFeature, never()).registerForSubscriptions(any(), any(), anyBoolean()) + } + + @Test + fun `block is executed only account is available`() { + val accountManager: FxaAccountManager = mock() + val block: (DeviceConstellation) -> Unit = mock() + val account: OAuthAccount = mock() + val constellation: DeviceConstellation = mock() + + accountManager.withConstellation(block) + + verify(block, never()).invoke(constellation) + + `when`(accountManager.authenticatedAccount()).thenReturn(account) + `when`(account.deviceConstellation()).thenReturn(constellation) + + accountManager.withConstellation(block) + + verify(block).invoke(constellation) + } +} \ No newline at end of file diff --git a/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/SendTabUseCasesTest.kt b/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/SendTabUseCasesTest.kt index da4af5cbe55..287fb8c5da6 100644 --- a/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/SendTabUseCasesTest.kt +++ b/components/feature/sendtab/src/test/java/mozilla/components/feature/sendtab/SendTabUseCasesTest.kt @@ -222,27 +222,25 @@ class SendTabUseCasesTest { } @Test - fun `SendTabUseCase - result is false if any send tab action fails`() { - val useCases = SendTabUseCases(manager) + fun `SendTabUseCase - result is false if any send tab action fails`() = runBlockingTest { + val useCases = SendTabUseCases(manager, coroutineContext) val device: Device = mock() val tab = TabData("Title", "http://example.com") - runBlocking { - useCases.sendToDeviceAsync("123", listOf(tab, tab)) + useCases.sendToDeviceAsync("123", listOf(tab, tab)) - verify(constellation, never()).sendEventToDeviceAsync(any(), any()) + verify(constellation, never()).sendEventToDeviceAsync(any(), any()) - `when`(device.id).thenReturn("123") - `when`(state.otherDevices).thenReturn(listOf(device)) - `when`(constellation.sendEventToDeviceAsync(any(), any())) - .thenReturn(CompletableDeferred(true)) - .thenReturn(CompletableDeferred(true)) + `when`(device.id).thenReturn("123") + `when`(state.otherDevices).thenReturn(listOf(device)) + `when`(constellation.sendEventToDeviceAsync(any(), any())) + .thenReturn(CompletableDeferred(true)) + .thenReturn(CompletableDeferred(true)) - val result = useCases.sendToDeviceAsync("123", listOf(tab, tab)) + val result = useCases.sendToDeviceAsync("123", listOf(tab, tab)) - verify(constellation, never()).sendEventToDeviceAsync(any(), any()) - Assert.assertFalse(result.await()) - } + verify(constellation, never()).sendEventToDeviceAsync(any(), any()) + Assert.assertFalse(result.await()) } @Test diff --git a/components/feature/sitepermissions/src/main/res/values-cs/strings.xml b/components/feature/sitepermissions/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..0067af4668c --- /dev/null +++ b/components/feature/sitepermissions/src/main/res/values-cs/strings.xml @@ -0,0 +1,34 @@ + + + + Chcete serveru %1$s povolit zasílat vám oznámení? + + Chcete serveru %1$s povolit používat vaši kameru? + + Chcete serveru %1$s povolit používat váš mikrofon? + + Chcete serveru %1$s povolit přístup k vaší poloze? + + Chcete serveru %1$s povolit používat vaši kameru a mikrofon? + + Mikrofon 1 + + Zadní kamera + + Přední kamera + + Povolit + + Nepovolit + + Pamatovat si pro tento server + + Vždy + + Nikdy + diff --git a/components/feature/sitepermissions/src/main/res/values-es-rAR/strings.xml b/components/feature/sitepermissions/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..dd8a1b72441 --- /dev/null +++ b/components/feature/sitepermissions/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,34 @@ + + + + ¿Permitir que %1$s envíe notificaciones? + + ¿Permitir que %1$s use la cámara? + + ¿Permitir que %1$s use el micrófono? + + ¿Permitir que %1$s use tu ubicación? + + ¿Permitir que %1$s use la cámara y el micrófono? + + Micrófono 1 + + Cámara trasera + + Cámara frontal + + Permitir + + No permitir + + Recordar para este sitio + + Siempre + + Nunca + diff --git a/components/feature/sitepermissions/src/main/res/values-eu/strings.xml b/components/feature/sitepermissions/src/main/res/values-eu/strings.xml index 37c90f9dfc0..2723eb8d6e0 100644 --- a/components/feature/sitepermissions/src/main/res/values-eu/strings.xml +++ b/components/feature/sitepermissions/src/main/res/values-eu/strings.xml @@ -1,5 +1,32 @@ + + Baimendu %1$s(r)i jakinarazpenak bidaltzea? + + Baimendu %1$s(r)i zure kamera erabiltzea? + + Baimendu %1$s(r)i zure mikrofonoa erabiltzea? + + Baimendu %1$s(r)i zure kokapena erabiltzea? + + Baimendu %1$s(r)i zure kamera eta mikrofonoa erabiltzea? + + 1 Mikrofonoa + + Atzealdeko kamera + + Aurreko kamera + + Baimendu + + Ez baimendu + + Gogoratu erabakia gune honetarako Beti diff --git a/components/feature/sitepermissions/src/main/res/values-fi/strings.xml b/components/feature/sitepermissions/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..a2cebbb6e03 --- /dev/null +++ b/components/feature/sitepermissions/src/main/res/values-fi/strings.xml @@ -0,0 +1,24 @@ + + + + Mikrofoni 1 + + Takakamera + + Etukamera + + Salli + + Älä salli + + Muista valinta tälle sivustolle + + Aina + + Ei koskaan + diff --git a/components/feature/sitepermissions/src/main/res/values-pa-rIN/strings.xml b/components/feature/sitepermissions/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..b9c1110ed68 --- /dev/null +++ b/components/feature/sitepermissions/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,34 @@ + + + + %1$s ਨੂੰ ਸੂਚਨਾਵਾਂ ਦੇਣ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ? + + %1$s ਨੂੰ ਆਪਣਾ ਕੈਮਰਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ? + + %1$s ਨੂੰ ਆਪਣਾ ਮਾਈਕਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ? + + %1$s ਨੂੰ ਆਪਣਾ ਟਿਕਾਣਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ? + + %1$s ਨੂੰ ਆਪਣਾ ਕੈਮਰਾ ਅਤੇ ਮਾਈਕਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ? + + ਮਾਈਕਰੋਫ਼ੋਨ 1 + + ਪਿਛਲੇ ਪਾਸੇ ਵਾਲਾ ਕੈਮਰਾ + + ਅੱਗੇ ਪਾਸੇ ਵਾਲਾ ਕੈਮਰਾ + + ਆਗਿਆ ਦਿਓ + + ਆਗਿਆ ਨਾ ਦਿਓ + + ਇਸ ਸਾਈਟ ਲਈ ਫ਼ੈਸਲਾ ਯਾਦ ਰੱਖੋ + + ਹਮੇਸ਼ਾਂ + + ਕਦੇ ਨਹੀਂ + diff --git a/components/feature/tabs/src/main/res/values-cs/strings.xml b/components/feature/tabs/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..1e585bd5677 --- /dev/null +++ b/components/feature/tabs/src/main/res/values-cs/strings.xml @@ -0,0 +1,5 @@ + + + + Panely + diff --git a/components/feature/tabs/src/main/res/values-es-rAR/strings.xml b/components/feature/tabs/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..e1481954ae2 --- /dev/null +++ b/components/feature/tabs/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,5 @@ + + + + Pestañas + diff --git a/components/feature/tabs/src/main/res/values-fi/strings.xml b/components/feature/tabs/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..43d0a4b9ee6 --- /dev/null +++ b/components/feature/tabs/src/main/res/values-fi/strings.xml @@ -0,0 +1,5 @@ + + + + Välilehdet + diff --git a/components/feature/tabs/src/main/res/values-pa-rIN/strings.xml b/components/feature/tabs/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..b4afae05513 --- /dev/null +++ b/components/feature/tabs/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,5 @@ + + + + ਟੈਬਾਂ + diff --git a/components/lib/crash/src/main/res/values-cs/strings.xml b/components/lib/crash/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..4e49f6acb89 --- /dev/null +++ b/components/lib/crash/src/main/res/values-cs/strings.xml @@ -0,0 +1,21 @@ + + + + Promiňte. V aplikaci %1$s nastal problém a spadla. + + + Poslat hlášení o pádu společnosti %1$s + + + Zavřít + + + Restartovat aplikaci %s + + + Pády + + + Nahlásit + + diff --git a/components/lib/crash/src/main/res/values-es-rAR/strings.xml b/components/lib/crash/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..98cece0127b --- /dev/null +++ b/components/lib/crash/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,21 @@ + + + + Disculpá. %1$s tuvo un problema y falló. + + + Enviar informe del fallo a %1$s + + + Cerrar + + + Reiniciar %1$s + + + Fallos + + + Informar + + diff --git a/components/lib/crash/src/main/res/values-fi/strings.xml b/components/lib/crash/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..e81b6248d7a --- /dev/null +++ b/components/lib/crash/src/main/res/values-fi/strings.xml @@ -0,0 +1,19 @@ + + + + + Lähetä kaatumisraportti %1$slle + + + Sulje + + + Käynnistä %1$s uudelleen + + + Kaatumiset + + + Lähetä raportti + + diff --git a/components/lib/crash/src/main/res/values-in/strings.xml b/components/lib/crash/src/main/res/values-in/strings.xml index 241b414b0de..366ea560820 100644 --- a/components/lib/crash/src/main/res/values-in/strings.xml +++ b/components/lib/crash/src/main/res/values-in/strings.xml @@ -10,6 +10,12 @@ Tutup + + Mulai Ulang %1$s + + + Mogok + Laporkan diff --git a/components/lib/crash/src/main/res/values-pa-rIN/strings.xml b/components/lib/crash/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..808c17c9d30 --- /dev/null +++ b/components/lib/crash/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,22 @@ + + + + + ਅਫ਼ਸੋਸ ਹੈ। %1$s ਨੂੰ ਸਮੱਸਿਆ ਆਈ ਤੇ ਕਰੈਸ਼ ਹੋ ਗਿਆ ਹੈ। + + + ਕਰੈਸ਼ ਰਿਪੋਰਟ %1$s ਨੂੰ ਭੇਜੋ + + + ਬੰਦ ਕਰੋ + + + %1$s ਮੁੜ-ਚਾਲੂ ਕਰੋ + + + ਕਰੈਸ਼ + + + ਰਿਪੋਰਟ + + diff --git a/components/lib/publicsuffixlist/src/main/assets/publicsuffixes b/components/lib/publicsuffixlist/src/main/assets/publicsuffixes index ef889ddae44..b1ec6eca7fb 100644 Binary files a/components/lib/publicsuffixlist/src/main/assets/publicsuffixes and b/components/lib/publicsuffixlist/src/main/assets/publicsuffixes differ diff --git a/components/service/experiments/KintoSchema.md b/components/service/experiments/KintoSchema.md new file mode 100644 index 00000000000..5a3d9338358 --- /dev/null +++ b/components/service/experiments/KintoSchema.md @@ -0,0 +1,375 @@ +# Kinto Schema + +This document contains the information about the Kinto schema and UI schema needed to run dev experiments +on the "Dev" Kinto instance located at https://kinto.dev.mozaws.net. + +## JSON Schema + +```JSON +{ + "type": "object", + "required": [ + "id", + "description", + "match", + "buckets", + "branches" + ], + "properties": { + "id": { + "title": "Experiment id", + "type": "string", + "minLength": 1, + "maxLength": 100 + }, + "description": { + "title": "Description", + "type": "string" + }, + "buckets": { + "title": "Buckets", + "type": "object", + "description": "Each user is assigned a random bucket from 0 to 999. Select the bucket ranges here to control the enrolled population size.", + "required": [ + "start", + "count" + ], + "properties": { + "start": { + "mininum": 0, + "maximum": 999, + "type": "number" + }, + "count": { + "mininum": 0, + "maximum": 1000, + "type": "number" + } + } + }, + "branches": { + "title": "Branches", + "type": "array", + "required": [ + "name", + "ratio" + ], + "default": [], + "uniqueItems": true, + "minItems": 1, + "description": "Each experiment needs to specify one or more branches. Each branch has a name and a ratio. An enrolled user is assigned one branch randomly, with the probabilities weighted per the ratio.", + "items": { + "description": "One experiment branch.", + "title": "Branch", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The branch name. This is what product code uses to decide which branch logic to execute.", + "minLength": 1, + "maxLength": 100 + }, + "ratio": { + "type": "number", + "description": "The branches ratio is the probabilistic weight for random branch assignment.", + "mininum": 1, + "maximum": 1000, + "default": 1 + } + } + } + }, + "match": { + "title": "Matching", + "type": "object", + "description": "A list of optional matchers, which allow restricting the experiment to e.g. specific application ids.", + "properties": { + "app_id": { + "type": "string", + "description": "Match specific application ids. A regex. E.g.: ^org.mozilla.fennec|org.mozilla.firefox_beta|org.mozilla.firefox$", + "minLength": 1, + "maxLength": 1000 + }, + "app_display_version": { + "description": "The application's version number. A regex. E.g.: '47.0a1', '46.0'", + "type": "string" + }, + "app_min_version": { + "description": "The application's minimum version number. E.g.: '47.0.11', '46.0'", + "type": "string" + }, + "app_max_version": { + "description": "The application's maximum version number. E.g.: '47.0.11', '46.0'", + "type": "string" + }, + "locale_country": { + "description": "Match country, pulled from the default locale. A regex. E.g.: USA|ITA", + "type": "string", + "minLength": 1, + "maxLength": 1000 + }, + "locale_language": { + "description": "Language, pulled from the default locale. A regex. E.g.: eng|esp", + "type": "string", + "minLength": 1, + "maxLength": 1000 + }, + "device_model": { + "description": "Device name. A regex.", + "type": "string", + "minLength": 1, + "maxLength": 1000 + }, + "device_manufacturer": { + "description": "Device manufacturer", + "type": "string", + "minLength": 1, + "maxLength": 1000 + }, + "regions": { + "default": [], + "description": "Compared with GeoIP lookup, where supported.", + "items": { + "default": "", + "description": "Similar to a GeoIP lookup", + "minLength": 1, + "maxLength": 1000, + "title": "Regions", + "type": "string" + }, + "title": "Regions", + "type": "array", + "uniqueItems": true + }, + "debug_tags": { + "default": [], + "description": "Target specific debug tags only. This allows testing of experiments for only specific active users for QA etc.", + "items": { + "default": "", + "description": "A debug tag set through the libraries debug activity.", + "minLength": 1, + "title": "Debug tag", + "type": "string" + }, + "title": "Debug tags", + "type": "array", + "uniqueItems": true + } + } + } + } +} +``` + +## UI Schema + +```JSON +{ + "sort": "-last_modified", + "displayFields": [ + "id", + "description" + ], + "attachment": { + "enabled": false, + "required": false + }, + "schema": { + "properties": { + "id": { + "type": "string", + "maxLength": 100, + "title": "Experiment id", + "minLength": 1 + }, + "buckets": { + "description": "Each user is assigned a random bucket from 0 to 999. Select the bucket ranges here to control the enrolled population size.", + "properties": { + "start": { + "type": "number", + "mininum": 0, + "maximum": 999 + }, + "count": { + "type": "number", + "mininum": 0, + "maximum": 1000 + } + }, + "type": "object", + "required": [ + "start", + "count" + ], + "title": "Buckets" + }, + "description": { + "type": "string", + "title": "Description" + }, + "branches": { + "description": "Each experiment needs to specify one or more branches. Each branch has a name and a ratio. An enrolled user is assigned one branch randomly, with the probabilities weighted per the ratio.", + "required": [ + "name", + "ratio" + ], + "title": "Branches", + "items": { + "description": "One experiment branch.", + "properties": { + "ratio": { + "description": "The branches ratio is the probabilistic weight for random branch assignment.", + "type": "number", + "default": 1, + "mininum": 1, + "maximum": 1000 + }, + "name": { + "description": "The branch name. This is what product code uses to decide which branch logic to execute.", + "type": "string", + "maxLength": 100, + "minLength": 1 + } + }, + "type": "object", + "title": "Branch" + }, + "type": "array", + "minItems": 1, + "uniqueItems": true, + "default": [] + }, + "match": { + "description": "A list of optional matchers, which allow restricting the experiment to e.g. specific application ids.", + "properties": { + "app_id": { + "description": "Match specific application ids. A regex. E.g.: ^org.mozilla.fennec|org.mozilla.firefox_beta|org.mozilla.firefox$", + "type": "string", + "maxLength": 1000, + "minLength": 1 + }, + "app_display_version": { + "description": "The application's version number. A regex. E.g.: '47.0a1', '46.0'", + "type": "string" + }, + "app_min_version": { + "description": "The application's minimum version number. E.g.: '47.0.11', '46.0'", + "type": "string" + }, + "app_max_version": { + "description": "The application's maximum version number. E.g.: '47.0.11', '46.0'", + "type": "string" + }, + "device_manufacturer": { + "description": "Device manufacturer", + "type": "string", + "maxLength": 1000, + "minLength": 1 + }, + "debug_tags": { + "description": "Target specific debug tags only. This allows testing of experiments for only specific active users for QA etc.", + "title": "Debug tags", + "items": { + "description": "A debug tag set through the libraries debug activity.", + "type": "string", + "title": "Debug tag", + "default": "", + "minLength": 1 + }, + "type": "array", + "uniqueItems": true, + "default": [] + }, + "locale_country": { + "description": "Match country, pulled from the default locale. A regex. E.g.: USA|ITA", + "type": "string", + "maxLength": 1000, + "minLength": 1 + }, + "regions": { + "description": "Compared with GeoIP lookup, where supported.", + "title": "Regions", + "items": { + "description": "Similar to a GeoIP lookup", + "maxLength": 1000, + "title": "Regions", + "type": "string", + "minLength": 1, + "default": "" + }, + "type": "array", + "uniqueItems": true, + "default": [] + }, + "device_model": { + "description": "Device name. A regex.", + "type": "string", + "maxLength": 1000, + "minLength": 1 + }, + "locale_language": { + "description": "Language, pulled from the default locale. A regex. E.g.: eng|esp", + "type": "string", + "maxLength": 1000, + "minLength": 1 + } + }, + "type": "object", + "title": "Matching" + } + }, + "type": "object", + "required": [ + "id", + "description", + "match", + "buckets", + "branches" + ] + }, + "uiSchema": { + "buckets": { + "ui:order": [ + "start", + "count" + ] + }, + "description": { + "ui:widget": "textarea" + }, + "match": { + "ui:order": [ + "app_id", + "app_display_version", + "app_min_version", + "app_max_version", + "locale_language", + "locale_country", + "device_model", + "device_manufacturer", + "regions", + "debug_tags" + ] + }, + "ui:order": [ + "id", + "description", + "buckets", + "branches", + "match" + ] + }, + "cache_expires": 0 +} +``` + +## Where to add this + +For testing create a collection `mobile-experiments` in the `main` bucket on the [Kinto dev server](https://kinto.dev.mozaws.net/v1/admin/). + +## Records list columns + +What's added in "Records list columns" is what get's shown in the record lists overview. +We want: +- id +- description \ No newline at end of file diff --git a/components/service/experiments/README.md b/components/service/experiments/README.md index a93420882ed..8d7730ca88e 100644 --- a/components/service/experiments/README.md +++ b/components/service/experiments/README.md @@ -18,15 +18,15 @@ implementation "org.mozilla.components:service-experiments:{latest-version}" ``` ### Initializing the Experiments library -In order to use the library, first you have to initialize it by calling `Experiments.initialize()`. You do this once per app launch -(typically in your `Application` class `onCreate` method). You simply have to call `Experiments.initialize()` and -provide the `applicationContext` (and optionally a `Configuration` object), like this: + +In order to use the library, first you have to initialize it by calling `Experiments.initialize()`. +You do this once per app launch (typically in your `Application` class `onCreate` method). You +simply have to call `Experiments.initialize()` and provide the `applicationContext` (and optionally +a `Configuration` object), like this: ```Kotlin class SampleApp : Application() { override fun onCreate() { - // Glean needs to be initialized first. - Glean.initialize(/* ... */) Experiments.initialize( applicationContext, configuration // This is optional, e.g. for overriding the fetch client. @@ -35,21 +35,26 @@ class SampleApp : Application() { } ``` -Note that this library depends on the Glean library, which has to be initialized first. See the [Glean README](../glean/README.md) for more details. +This library makes use of [Glean](https://mozilla.github.io/glean/book/index.html) for reporting +experiment enrollment. If Glean is not used and initialized by the application, the recording +methods are a no-op. ### Updating of experiments -The library updates it's list of experiments automatically and async from Kinto on library initialization. As this is asynchronous, it will not have immediate effect. +The library updates its list of experiments automatically and asynchronously from Kinto on library +initialization. As this is asynchronous, it will not have immediate effect. -Afterwards, the list of experiments will be updated every 6 hours. +Afterwards, the list of experiments will be updated in the background every 6 hours. ### Checking if a user is part of an experiment -In order to check if a user is part of a specific experiment, `Experiments` provides a Kotlin-friendly -`withExperiment` API. You pass the id of the experiment you want to check and if the client is in the experiment, you get the selected branch name passed: + +In order to check if a user is part of a specific experiment, `Experiments` provides a +Kotlin-friendly `withExperiment` API. You pass the id of the experiment you want to check and if the +client is in the experiment, you get the selected branch name passed: ```Kotlin -Experiments.withExperiment("button-color-experiment") { - when(it) { // `it` is the branch name. +Experiments.withExperiment("button-color-experiment") { branchName -> + when(branchName) { "red" -> button.setBackgroundColor(Color.RED) "control" -> button.setBackgroundColor(DEFAULT_COLOR) } @@ -64,14 +69,15 @@ For any technical tests, we do have a Kinto dev server available, which can be f The admin interface is [here](https://kinto.dev.mozaws.net/v1/admin/). For setting up a testing setup we can: - [Create a collection in the main bucket](https://kinto.dev.mozaws.net/v1/admin/#/buckets/main/collections/create). - The *collection id* should be `mobile-experiments`. - - The *JSON schema* should have [this content](https://gist.github.com/travis79/c112d803dfcd84cb5f854f5b22bfcd0f#file-json-schema-json). - - The *UI schema* should have [this content](https://gist.github.com/travis79/c112d803dfcd84cb5f854f5b22bfcd0f#file-ui-schema-json). + - The *JSON schema* should have [this content](KintoSchema.md#JSON-Schema) + - The *UI schema* should have [this content](KintoSchema.md#UI-Schema) - The *Records list columns* should contain `id` and `description`. - Click *Create collection* - In the [`mobile-experiments` record list](https://kinto.dev.mozaws.net/v1/admin/#/buckets/main/collections/mobile-experiments/records), create new entries for experiments as needed. - In the mobile application, use the debug commands below to switch to the `dev` endpoint. ### ExperimentsDebugActivity usage + Experiments exports the [`ExperimentsDebugActivity`](src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt) that can be used to trigger functionality or toggle debug features on or off. Users can invoke this special activity, at run-time, using the following [`adb`](https://developer.android.com/studio/command-line/adb) command: @@ -163,6 +169,7 @@ An individual experiment record looks e.g. like this: ``` ### Experiment fields + The experiments records in Kinto contain the following properties: | Name | Type | Required | Description | Example | diff --git a/components/service/experiments/src/main/java/mozilla/components/service/experiments/Configuration.kt b/components/service/experiments/src/main/java/mozilla/components/service/experiments/Configuration.kt index ad1b049dc5a..8e894f32237 100644 --- a/components/service/experiments/src/main/java/mozilla/components/service/experiments/Configuration.kt +++ b/components/service/experiments/src/main/java/mozilla/components/service/experiments/Configuration.kt @@ -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 = lazy { HttpURLConnectionClient() }, diff --git a/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt b/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt index ca65b6a18b6..68e9fbe3f4a 100644 --- a/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt +++ b/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt @@ -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 diff --git a/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt b/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt index 79b773b9207..870dc2f5059 100644 --- a/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt +++ b/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt @@ -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) diff --git a/components/service/glean/build.gradle b/components/service/glean/build.gradle index dbc244f9818..d8f70eba898 100644 --- a/components/service/glean/build.gradle +++ b/components/service/glean/build.gradle @@ -14,7 +14,7 @@ apply plugin: 'kotlin-android' * created during unit testing. * This uses a specific version of the schema identified by a git commit hash. */ -String GLEAN_PING_SCHEMA_GIT_HASH = "64b852c" +String GLEAN_PING_SCHEMA_GIT_HASH = "441076d" String GLEAN_PING_SCHEMA_URL = "https://raw.githubusercontent.com/mozilla-services/mozilla-pipeline-schemas/$GLEAN_PING_SCHEMA_GIT_HASH/schemas/glean/baseline/baseline.1.schema.json" android { diff --git a/components/service/glean/scripts/sdk_generator.gradle b/components/service/glean/scripts/sdk_generator.gradle index 65dba172d6f..8ee109b6e0e 100644 --- a/components/service/glean/scripts/sdk_generator.gradle +++ b/components/service/glean/scripts/sdk_generator.gradle @@ -21,7 +21,7 @@ import org.gradle.api.internal.artifacts.ArtifactAttributes // so that it will be shared between all libraries that use Glean. This is // important because it is approximately 300MB in installed size. -String GLEAN_PARSER_VERSION = "1.1.0" +String GLEAN_PARSER_VERSION = "1.2.1" // The version of Miniconda is explicitly specified. // Miniconda3-4.5.12 is known to not work on Windows. String MINICONDA_VERSION = "4.5.11" diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt index 580230b3643..af1e21b9027 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt @@ -10,7 +10,6 @@ import android.content.pm.PackageManager import android.os.Build import androidx.annotation.VisibleForTesting import androidx.lifecycle.ProcessLifecycleOwner -import androidx.work.WorkManager import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll import mozilla.components.service.glean.GleanMetrics.GleanBaseline @@ -24,7 +23,6 @@ import mozilla.components.service.glean.ping.PingMaker import mozilla.components.service.glean.private.PingType import mozilla.components.service.glean.scheduler.GleanLifecycleObserver import mozilla.components.service.glean.scheduler.MetricsPingScheduler -import mozilla.components.service.glean.scheduler.MetricsPingWorker import mozilla.components.service.glean.scheduler.PingUploadWorker import mozilla.components.service.glean.storages.StorageEngineManager import mozilla.components.service.glean.storages.PingStorageEngine @@ -213,12 +211,12 @@ open class GleanInternalAPI internal constructor () { } /** - * Cancel any pending [PingUploadWorker] objects that have been enqueued. + * Cancel any pending [PingUploadWorker] objects that have been enqueued so that we don't + * accidentally upload or collect data after the upload has been disabled. */ private fun cancelPingWorkers() { - val workManager = WorkManager.getInstance() - workManager.cancelUniqueWork(PingUploadWorker.PING_WORKER_TAG) - workManager.cancelUniqueWork(MetricsPingWorker.TAG) + MetricsPingScheduler.cancel() + PingUploadWorker.cancel() } /** diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt index cd9501e0b4e..97d8b35be8c 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt @@ -46,13 +46,14 @@ data class Configuration internal constructor( // constructor and only initialized with a proper default when calling the primary // constructor from the secondary, public one, below. constructor( + serverEndpoint: String = DEFAULT_TELEMETRY_ENDPOINT, connectionTimeout: Long = DEFAULT_CONNECTION_TIMEOUT, readTimeout: Long = DEFAULT_READ_TIMEOUT, maxEvents: Int = DEFAULT_MAX_EVENTS, httpClient: Lazy = lazy { HttpURLConnectionClient() }, channel: String? = null ) : this ( - serverEndpoint = DEFAULT_TELEMETRY_ENDPOINT, + serverEndpoint = serverEndpoint, userAgent = DEFAULT_USER_AGENT, connectionTimeout = connectionTimeout, readTimeout = readTimeout, diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/histogram/FunctionalHistogram.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/histogram/FunctionalHistogram.kt new file mode 100644 index 00000000000..5e716e4a58f --- /dev/null +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/histogram/FunctionalHistogram.kt @@ -0,0 +1,194 @@ +/* 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 mozilla.components.service.glean.histogram + +import mozilla.components.support.ktx.android.org.json.tryGetLong +import org.json.JSONObject +import java.lang.Math.pow +import kotlin.math.log + +/** + * This class represents a histogram where the bucketing is performed by a + * function, rather than pre-computed buckets. It is meant to help serialize + * and deserialize data to the correct format for transport and storage, as well + * as performing the calculations to determine the correct bucket for each sample. + * + * The bucket index of a given sample is determined with the following function: + * + * i = ⌊n log₂(𝑥)⌋ + * + * In other words, there are n buckets for each power of 2 magnitude. + * + * @param values a map containing the minimum bucket value mapped to the accumulated count + * @param sum the accumulated sum of all the samples in the histogram + */ +data class FunctionalHistogram( + val logBase: Double, + val bucketsPerMagnitude: Double, + // map from bucket limits to accumulated values + val values: MutableMap = mutableMapOf(), + var sum: Long = 0 +) { + private val exponent = pow(logBase, 1.0 / bucketsPerMagnitude) + + companion object { + /** + * Factory function that takes stringified JSON and converts it back into a + * [FunctionalHistogram]. + * + * @param json Stringified JSON value representing a [FunctionalHistogram] object + * @return A [FunctionalHistogram] or null if unable to rebuild from the string. + */ + @Suppress("ReturnCount", "ComplexMethod", "NestedBlockDepth") + internal fun fromJsonString(json: String): FunctionalHistogram? { + val jsonObject: JSONObject + try { + jsonObject = JSONObject(json) + } catch (e: org.json.JSONException) { + return null + } + + val logBase = try { + jsonObject.getDouble("log_base") + } catch (e: org.json.JSONException) { + return null + } + val bucketsPerMagnitude = try { + jsonObject.getDouble("buckets_per_magnitude") + } catch (e: org.json.JSONException) { + return null + } + + // Attempt to parse the values map, if it fails then something is wrong and we need to + // return null. + val values = try { + val mapData = jsonObject.getJSONObject("values") + val valueMap: MutableMap = mutableMapOf() + mapData.keys().forEach { key -> + mapData.tryGetLong(key)?.let { + valueMap[key.toLong()] = it + } + } + valueMap + } catch (e: org.json.JSONException) { + // This should only occur if there isn't a key/value pair stored for "values" + return null + } + val sum = jsonObject.tryGetLong("sum") ?: return null + + return FunctionalHistogram( + logBase = logBase, + bucketsPerMagnitude = bucketsPerMagnitude, + values = values, + sum = sum + ) + } + } + + /** + * Maps a sample to a "bucket index" that it belongs in. + * A "bucket index" is the consecutive integer index of each bucket, useful as a + * mathematical concept, even though the internal representation is stored and + * sent using the minimum value in each bucket. + * + * @param sample The data sample + * @return The bucket index the sample belongs in + */ + internal fun sampleToBucketIndex(sample: Long): Long { + return log(sample.toDouble() + 1, exponent).toLong() + } + + /** + * Determines the minimum value of a bucket, given a bucket index. + * + * @param bucketIndex The ordinal index of a bucket + * @return The minimum value of the bucket + */ + internal fun bucketIndexToBucketMinimum(bucketIndex: Long): Long { + return pow(exponent, bucketIndex.toDouble()).toLong() + } + + /** + * Maps a sample to the minimum value of the bucket it belongs in. + * + * @param sample The sample value + * @return the minimum value of the bucket the sample belongs in + */ + internal fun sampleToBucketMinimum(sample: Long): Long { + return if (sample == 0L) { + 0L + } else { + bucketIndexToBucketMinimum(sampleToBucketIndex(sample)) + } + } + + // This is a calculated read-only property that returns the total count of accumulated values + val count: Long + get() = values.map { it.value }.sum() + + /** + * Accumulates a sample to the correct bucket. + * If a value doesn't exist for this bucket yet, one is created. + * + * @param sample Long value representing the sample that is being accumulated + */ + internal fun accumulate(sample: Long) { + var bucketMinimum = sampleToBucketMinimum(sample) + values[bucketMinimum] = (values[bucketMinimum] ?: 0) + 1 + sum += sample + } + + /** + * Helper function to build the [FunctionalHistogram] into a JSONObject for serialization + * purposes. + * + * @return The histogram as [JSONObject] for persistence + */ + internal fun toJsonObject(): JSONObject { + return JSONObject(mapOf( + "log_base" to logBase, + "buckets_per_magnitude" to bucketsPerMagnitude, + "values" to values.mapKeys { "${it.key}" }, + "sum" to sum + )) + } + + /** + * Helper function to build the [FunctionalHistogram] into a JSONObject for sending in the + * ping payload. + * + * All buckets [min, max + 1] are included in the histogram, even if the have zero values. + * + * @return The histogram as [JSONObject] for a ping payload + */ + internal fun toJsonPayloadObject(): JSONObject { + val completeValues = if (values.size != 0) { + // A bucket range is defined by its own key, and the key of the next + // highest bucket. This explicitly adds any empty buckets (even if they have values + // of 0) between the lowest and highest bucket so that the backend knows the + // bucket ranges even without needing to know that function that was used to + // create the buckets. + val minBucket = sampleToBucketIndex(values.keys.min()!!) + val maxBucket = sampleToBucketIndex(values.keys.max()!!) + 1 + + var completeValues: MutableMap = mutableMapOf() + + for (i in minBucket..maxBucket) { + val bucketMinimum = bucketIndexToBucketMinimum(i) + val bucketSum = values.get(bucketMinimum)?.let { it } ?: 0 + completeValues[bucketMinimum.toString()] = bucketSum + } + + completeValues + } else { + values + } + + return JSONObject(mapOf( + "values" to completeValues, + "sum" to sum + )) + } +} diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/histogram/PrecomputedHistogram.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/histogram/PrecomputedHistogram.kt new file mode 100644 index 00000000000..3438d2b36d8 --- /dev/null +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/histogram/PrecomputedHistogram.kt @@ -0,0 +1,276 @@ +/* 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 mozilla.components.service.glean.histogram + +import mozilla.components.service.glean.private.HistogramType +import mozilla.components.support.ktx.android.org.json.tryGetInt +import mozilla.components.support.ktx.android.org.json.tryGetLong +import mozilla.components.support.ktx.android.org.json.tryGetString +import org.json.JSONArray +import org.json.JSONObject + +/** + * This class represents the structure of a custom distribution. It is meant + * to help serialize and deserialize data to the correct format for transport and + * storage, as well as including helper functions to calculate the bucket sizes. + * + * @param rangeMin the minimum value that can be represented + * @param rangeMax the maximum value that can be represented + * @param bucketCount total number of buckets + * @param histogramType the [HistogramType] representing the bucket layout + * @param values a map containing the bucket index mapped to the accumulated count + * @param sum the accumulated sum of all the samples in the custom distribution + */ +data class PrecomputedHistogram( + val rangeMin: Long, + val rangeMax: Long, + val bucketCount: Int, + val histogramType: HistogramType, + // map from bucket limits to accumulated values + val values: MutableMap = mutableMapOf(), + var sum: Long = 0 +) { + companion object { + /** + * Factory function that takes stringified JSON and converts it back into a + * [PrecomputedHistogram]. + * + * @param json Stringified JSON value representing a [PrecomputedHistogram] object + * @return A [PrecomputedHistogram] or null if unable to rebuild from the string. + */ + @Suppress("ReturnCount", "ComplexMethod") + internal fun fromJsonString(json: String): PrecomputedHistogram? { + val jsonObject: JSONObject + try { + jsonObject = JSONObject(json) + } catch (e: org.json.JSONException) { + return null + } + + val bucketCount = jsonObject.tryGetInt("bucket_count") ?: return null + // If 'range' isn't present, JSONException is thrown + val range = try { + val array = jsonObject.getJSONArray("range") + // Range must have exactly 2 values + if (array.length() == 2) { + // The getLong() function throws JSONException if we can't convert to a Long, so + // the catch should return null if either value isn't a valid Long + array.getLong(0) + array.getLong(1) + // This returns the JSONArray to the assignment if everything checks out + array + } else { + return null + } + } catch (e: org.json.JSONException) { + return null + } + val rawHistogramType = jsonObject.tryGetString("histogram_type") ?: return null + val histogramType = try { + HistogramType.valueOf(rawHistogramType.capitalize()) + } catch (e: IllegalArgumentException) { + return null + } + // Attempt to parse the values map, if it fails then something is wrong and we need to + // return null. + val values = try { + val mapData = jsonObject.getJSONObject("values") + val valueMap: MutableMap = mutableMapOf() + mapData.keys().forEach { key -> + valueMap[key.toLong()] = mapData.tryGetLong(key) ?: 0L + } + valueMap + } catch (e: org.json.JSONException) { + // This should only occur if there isn't a key/value pair stored for "values" + return null + } + val sum = jsonObject.tryGetLong("sum") ?: return null + + return PrecomputedHistogram( + bucketCount = bucketCount, + rangeMin = range.getLong(0), + rangeMax = range.getLong(1), + histogramType = histogramType, + values = values, + sum = sum + ) + } + } + + // This is a calculated read-only property that returns the total count of accumulated values + val count: Long + get() = values.map { it.value }.sum() + + // This is a list of limits for the buckets. Instantiated lazily to ensure that the range and + // bucket counts are set first. + internal val buckets: List by lazy { getBuckets() } + + /** + * Finds the correct bucket, using a binary search to locate the index of the + * bucket where the sample is bigger than or equal to the bucket limit. + * + * @param sample Long value representing the sample that is being accumulated + */ + internal fun findBucket(sample: Long): Long { + var under = 0 + var over = bucketCount + var mid: Int + + do { + mid = under + (over - under) / 2 + if (mid == under) { + break + } + + if (buckets[mid] <= sample) { + under = mid + } else { + over = mid + } + } while (true) + + return buckets[mid] + } + + /** + * Accumulates a sample to the correct bucket. + * If a value doesn't exist for this bucket yet, one is created. + * + * @param sample Long value representing the sample that is being accumulated + */ + internal fun accumulate(sample: Long) { + val limit = findBucket(sample) + values[limit] = (values[limit] ?: 0) + 1 + sum += sample + } + + /** + * Helper function to build the [PrecomputedHistogram] into a JSONObject for serialization + * purposes. + * + * @return The histogram as JSON for persistence + */ + internal fun toJsonObject(): JSONObject { + return JSONObject(mapOf( + "bucket_count" to bucketCount, + "range" to JSONArray(arrayOf(rangeMin, rangeMax)), + "histogram_type" to histogramType.toString().toLowerCase(), + "values" to values.mapKeys { "${it.key}" }, + "sum" to sum + )) + } + + /** + * Helper function to build the [PrecomputedHistogram] into a JSONObject for sending in the + * ping payload. Compared to [toJsonObject] which is designed for lossless roundtripping: + * + * - this does not include the bucketing parameters + * - all buckets [min, max + 1] are inserted into values + * + * @return The histogram as JSON to send in a ping payload + */ + internal fun toJsonPayloadObject(): JSONObject { + // Include all buckets [min, max + 1], where max is the maximum bucket with + // any value recorded. + val contiguousValues = if (!values.isEmpty()) { + val bucketMax = values.keys.max()!! + val contiguousValues = mutableMapOf() + for (bucketMin in buckets) { + contiguousValues["$bucketMin"] = values.getOrElse(bucketMin) { 0L } + if (bucketMin > bucketMax) { + break + } + } + contiguousValues + } else { + values + } + + return JSONObject(mapOf( + "values" to contiguousValues, + "sum" to sum + )) + } + + /** + * Helper function to generate the list of linear bucket min values used when accumulating + * to the correct buckets. + * + * @return List containing the bucket limits + */ + @Suppress("MagicNumber") + private fun getBucketsLinear(): List { + // Written to match the bucket generation on legacy desktop telemetry: + // https://searchfox.org/mozilla-central/rev/e0b0c38ee83f99d3cf868bad525ace4a395039f1/toolkit/components/telemetry/build_scripts/mozparsers/parse_histograms.py#65 + + val result: MutableList = mutableListOf(0L) + + val dmin = rangeMin.toDouble() + val dmax = rangeMax.toDouble() + + for (i in (1 until bucketCount)) { + val linearRange = (dmin * (bucketCount - 1 - i) + dmax * (i - 1)) / (bucketCount - 2) + result.add((linearRange + 0.5).toLong()) + } + + return result + } + + /** + * Helper function to generate the list of exponential bucket min values used when accumulating + * to the correct buckets. + * + * @return List containing the bucket limits + */ + private fun getBucketsExponential(): List { + // Written to match the bucket generation on legacy desktop telemetry: + // https://searchfox.org/mozilla-central/rev/e0b0c38ee83f99d3cf868bad525ace4a395039f1/toolkit/components/telemetry/build_scripts/mozparsers/parse_histograms.py#75 + + // This algorithm calculates the bucket sizes using a natural log approach to get + // `bucketCount` number of buckets, exponentially spaced between `range[MIN]` and + // `range[MAX]`. + // + // Bucket limits are the minimal bucket value. + // That means values in a bucket `i` are `range[i] <= value < range[i+1]`. + // It will always contain an underflow bucket (`< 1`). + val logMax = Math.log(rangeMax.toDouble()) + val result: MutableList = mutableListOf() + var current = rangeMin + if (current == 0L) { + current = 1L + } + + // underflow bucket + result.add(0) + result.add(current) + + for (i in 2 until bucketCount) { + val logCurrent = Math.log(current.toDouble()) + val logRatio = (logMax - logCurrent) / (bucketCount - i) + val logNext = logCurrent + logRatio + val nextValue = Math.round(Math.exp(logNext)) + if (nextValue > current) { + current = nextValue + } else { + ++current + } + result.add(current) + } + return result.sorted() + } + + /** + * Helper function to generate the list of bucket min values used when accumulating + * to the correct buckets. + * + * @return List containing the bucket limits + */ + private fun getBuckets(): List { + return when (histogramType) { + HistogramType.Linear -> getBucketsLinear() + HistogramType.Exponential -> getBucketsExponential() + } + } +} diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt new file mode 100644 index 00000000000..a4091201356 --- /dev/null +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt @@ -0,0 +1,106 @@ +/* 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 mozilla.components.service.glean.private + +import androidx.annotation.VisibleForTesting +import mozilla.components.service.glean.Dispatchers +import mozilla.components.service.glean.histogram.PrecomputedHistogram +import mozilla.components.service.glean.storages.CustomDistributionsStorageEngine +import mozilla.components.support.base.log.logger.Logger + +/** + * This implements the developer facing API for recording custom distribution metrics. + * + * Custom distributions are histograms with the following parameters that are settable on a + * per-metric basis: + * + * - `rangeMin`/`rangeMax`: The minimum and maximum values + * - `bucketCount`: The number of histogram buckets + * - `histogramType`: Whether the bucketing is linear or exponential + * + * This metric exists primarily for backward compatibility with histograms in + * legacy (pre-Glean) telemetry, and its use is not recommended for newly-created + * metrics. + * + * Instances of this class type are automatically generated by the parsers at build time, + * allowing developers to record values that were previously registered in the metrics.yaml file. + */ +data class CustomDistributionMetricType( + override val disabled: Boolean, + override val category: String, + override val lifetime: Lifetime, + override val name: String, + override val sendInPings: List, + val rangeMin: Long, + val rangeMax: Long, + val bucketCount: Int, + val histogramType: HistogramType +) : CommonMetricData, HistogramMetricBase { + + private val logger = Logger("glean/CustomDistributionMetricType") + + /** + * Accumulates the provided samples in the metric. + * + * The unit of the samples is entirely defined by the user. We encourage the author of the + * metric to provide a `unit` parameter in the `metrics.yaml` file, but that has no effect + * in the client and there is no unit conversion performed here. + * + * @param samples the [LongArray] holding the samples to be recorded by the metric. + */ + override fun accumulateSamples(samples: LongArray) { + if (!shouldRecord(logger)) { + return + } + + @Suppress("EXPERIMENTAL_API_USAGE") + Dispatchers.API.launch { + CustomDistributionsStorageEngine.accumulateSamples( + metricData = this@CustomDistributionMetricType, + samples = samples, + rangeMin = rangeMin, + rangeMax = rangeMax, + bucketCount = bucketCount, + histogramType = histogramType + ) + } + } + + /** + * Tests whether a value is stored for the metric for testing purposes only. This function will + * attempt to await the last task (if any) writing to the the metric's storage engine before + * returning a value. + * + * @param pingName represents the name of the ping to retrieve the metric for. Defaults + * to the either the first value in [defaultStorageDestinations] or the first + * value in [sendInPings] + * @return true if metric value exists, otherwise false + */ + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + fun testHasValue(pingName: String = sendInPings.first()): Boolean { + @Suppress("EXPERIMENTAL_API_USAGE") + Dispatchers.API.assertInTestingMode() + + return CustomDistributionsStorageEngine.getSnapshot(pingName, false)?.get(identifier) != null + } + + /** + * Returns the stored value for testing purposes only. This function will attempt to await the + * last task (if any) writing to the the metric's storage engine before returning a value. + * + * @param pingName represents the name of the ping to retrieve the metric for. Defaults + * to the either the first value in [defaultStorageDestinations] or the first + * value in [sendInPings] + * @return value of the stored metric + * @throws [NullPointerException] if no value is stored + */ + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + fun testGetValue(pingName: String = sendInPings.first()): PrecomputedHistogram { + @Suppress("EXPERIMENTAL_API_USAGE") + Dispatchers.API.assertInTestingMode() + + return CustomDistributionsStorageEngine.getSnapshot(pingName, false)!![identifier]!! + } +} diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/private/HistogramBase.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/private/HistogramMetricBase.kt similarity index 59% rename from components/service/glean/src/main/java/mozilla/components/service/glean/private/HistogramBase.kt rename to components/service/glean/src/main/java/mozilla/components/service/glean/private/HistogramMetricBase.kt index dc0b4439f8f..beb41c2f580 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/private/HistogramBase.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/private/HistogramMetricBase.kt @@ -8,16 +8,10 @@ package mozilla.components.service.glean.private * A common interface to be implemented by all the histogram-like metric types * supported by the Glean SDK. */ -interface HistogramBase { +interface HistogramMetricBase { /** * Accumulates the provided samples in the metric. * - * Please note that this assumes that the provided samples are already in the - * "unit" declared by the instance of the implementing metric type (e.g. if the - * implementing class is a [TimingDistributionMetricType] and the instance this - * method was called on is using [TimeUnit.Second], then `samples` are assumed - * to be in that unit). - * * @param samples the [LongArray] holding the samples to be recorded by the metric. */ fun accumulateSamples(samples: LongArray) diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/private/MemoryDistributionMetricType.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/private/MemoryDistributionMetricType.kt new file mode 100644 index 00000000000..a80f4b55ee7 --- /dev/null +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/private/MemoryDistributionMetricType.kt @@ -0,0 +1,112 @@ +/* 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 mozilla.components.service.glean.private + +import androidx.annotation.VisibleForTesting +import mozilla.components.service.glean.Dispatchers +import mozilla.components.service.glean.histogram.FunctionalHistogram +import mozilla.components.service.glean.storages.MemoryDistributionsStorageEngine +import mozilla.components.support.base.log.logger.Logger + +/** + * This implements the developer facing API for recording memory distribution metrics. + * + * To prevent the number of buckets from being unbounded, values larger than 1 TB + * are truncated to 1 TB. + * + * Instances of this class type are automatically generated by the parsers at build time, + * allowing developers to record values that were previously registered in the metrics.yaml file. + */ +data class MemoryDistributionMetricType( + override val disabled: Boolean, + override val category: String, + override val lifetime: Lifetime, + override val name: String, + override val sendInPings: List, + val memoryUnit: MemoryUnit +) : CommonMetricData, HistogramMetricBase { + + private val logger = Logger("glean/MemoryDistributionMetricType") + + /** + * Record a single value, in the unit specified by `memoryUnit`, to the distribution. + * + * @param sample the value + */ + fun accumulate(sample: Long) { + if (!shouldRecord(logger)) { + return + } + + @Suppress("EXPERIMENTAL_API_USAGE") + Dispatchers.API.launch { + // Delegate storing the value to the storage engine. + MemoryDistributionsStorageEngine.accumulate( + metricData = this@MemoryDistributionMetricType, + sample = sample, + memoryUnit = memoryUnit + ) + } + } + + /** + * Accumulates the provided samples, in the unit specified by `memoryUnit`, + * to the distribution. + * + * This function is intended for GeckoView use only. + * + * @param samples the [LongArray] holding the samples to be recorded by the metric. + */ + override fun accumulateSamples(samples: LongArray) { + if (!shouldRecord(logger)) { + return + } + + @Suppress("EXPERIMENTAL_API_USAGE") + Dispatchers.API.launch { + MemoryDistributionsStorageEngine.accumulateSamples( + metricData = this@MemoryDistributionMetricType, + samples = samples, + memoryUnit = memoryUnit + ) + } + } + + /** + * Tests whether a value is stored for the metric for testing purposes only. This function will + * attempt to await the last task (if any) writing to the the metric's storage engine before + * returning a value. + * + * @param pingName represents the name of the ping to retrieve the metric for. Defaults + * to the either the first value in [defaultStorageDestinations] or the first + * value in [sendInPings] + * @return true if metric value exists, otherwise false + */ + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + fun testHasValue(pingName: String = sendInPings.first()): Boolean { + @Suppress("EXPERIMENTAL_API_USAGE") + Dispatchers.API.assertInTestingMode() + + return MemoryDistributionsStorageEngine.getSnapshot(pingName, false)?.get(identifier) != null + } + + /** + * Returns the stored value for testing purposes only. This function will attempt to await the + * last task (if any) writing to the the metric's storage engine before returning a value. + * + * @param pingName represents the name of the ping to retrieve the metric for. Defaults + * to the either the first value in [defaultStorageDestinations] or the first + * value in [sendInPings] + * @return value of the stored metric + * @throws [NullPointerException] if no value is stored + */ + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + fun testGetValue(pingName: String = sendInPings.first()): FunctionalHistogram { + @Suppress("EXPERIMENTAL_API_USAGE") + Dispatchers.API.assertInTestingMode() + + return MemoryDistributionsStorageEngine.getSnapshot(pingName, false)!![identifier]!! + } +} diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/private/MemoryUnit.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/private/MemoryUnit.kt new file mode 100644 index 00000000000..9e2bcea839e --- /dev/null +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/private/MemoryUnit.kt @@ -0,0 +1,17 @@ +/* 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 mozilla.components.service.glean.private + +/** + * Enumeration of different resolutions supported by the MemoryDistribution metric type. + * + * These use the power-of-2 values of these units, that is, Kilobyte is pedantically a Kibibyte. + */ +enum class MemoryUnit { + Byte, // 1 + Kilobyte, // 2^10 + Megabyte, // 2^20 + Gigabyte, // 2^30 +} diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt index e77d9785d21..4f27be8a66c 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt @@ -6,7 +6,7 @@ package mozilla.components.service.glean.private import androidx.annotation.VisibleForTesting import mozilla.components.service.glean.Dispatchers -import mozilla.components.service.glean.storages.TimingDistributionData +import mozilla.components.service.glean.histogram.FunctionalHistogram import mozilla.components.service.glean.storages.TimingDistributionsStorageEngine import mozilla.components.service.glean.timing.GleanTimerId import mozilla.components.service.glean.timing.TimingManager @@ -15,6 +15,13 @@ import mozilla.components.support.base.log.logger.Logger /** * This implements the developer facing API for recording timing distribution metrics. * + * The `timeUnit` parameter is only used when the values are set directly + * through `accumulateSamples`, which is used for bringing in GeckoView metrics, + * and not for normal use. + * + * To prevent the number of buckets from being unbounded, timings longer than 10 minutes + * are truncated to 10 minutes. + * * Instances of this class type are automatically generated by the parsers at build time, * allowing developers to record values that were previously registered in the metrics.yaml file. */ @@ -25,7 +32,7 @@ data class TimingDistributionMetricType( override val name: String, override val sendInPings: List, val timeUnit: TimeUnit -) : CommonMetricData, HistogramBase { +) : CommonMetricData, HistogramMetricBase { private val logger = Logger("glean/TimingDistributionMetricType") @@ -63,8 +70,7 @@ data class TimingDistributionMetricType( // Delegate storing the string to the storage engine. TimingDistributionsStorageEngine.accumulate( metricData = this@TimingDistributionMetricType, - sample = elapsedNanos, - timeUnit = timeUnit + sample = elapsedNanos ) } } @@ -85,6 +91,17 @@ data class TimingDistributionMetricType( TimingManager.cancel(this, timerId) } + /** + * Accumulates the provided samples in the metric. + * + * Please note that this assumes that the provided samples are already in the + * "unit" declared by the instance of the implementing metric type (e.g. if the + * implementing class is a [TimingDistributionMetricType] and the instance this + * method was called on is using [TimeUnit.Second], then `samples` are assumed + * to be in that unit). + * + * @param samples the [LongArray] holding the samples to be recorded by the metric. + */ override fun accumulateSamples(samples: LongArray) { if (!shouldRecord(logger)) { return @@ -129,7 +146,7 @@ data class TimingDistributionMetricType( * @throws [NullPointerException] if no value is stored */ @VisibleForTesting(otherwise = VisibleForTesting.NONE) - fun testGetValue(pingName: String = sendInPings.first()): TimingDistributionData { + fun testGetValue(pingName: String = sendInPings.first()): FunctionalHistogram { @Suppress("EXPERIMENTAL_API_USAGE") Dispatchers.API.assertInTestingMode() diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/scheduler/MetricsPingScheduler.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/scheduler/MetricsPingScheduler.kt index 8b22c0c8fc4..e20c7b181e6 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/scheduler/MetricsPingScheduler.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/scheduler/MetricsPingScheduler.kt @@ -51,6 +51,13 @@ internal class MetricsPingScheduler(val applicationContext: Context) : Lifecycle const val DUE_HOUR_OF_THE_DAY = 4 @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal var isInForeground = false + + /** + * Function to cancel any pending metrics ping workers + */ + internal fun cancel() { + WorkManager.getInstance().cancelUniqueWork(MetricsPingWorker.TAG) + } } init { diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/scheduler/PingUploadWorker.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/scheduler/PingUploadWorker.kt index be55855d6ee..d8b80388266 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/scheduler/PingUploadWorker.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/scheduler/PingUploadWorker.kt @@ -43,7 +43,7 @@ class PingUploadWorker(context: Context, params: WorkerParameters) : Worker(cont * @return [OneTimeWorkRequest] representing the task for the [WorkManager] to enqueue and run */ internal fun buildWorkRequest(): OneTimeWorkRequest = OneTimeWorkRequestBuilder() - .addTag(PingUploadWorker.PING_WORKER_TAG) + .addTag(PING_WORKER_TAG) .setConstraints(buildConstraints()) .build() @@ -52,9 +52,9 @@ class PingUploadWorker(context: Context, params: WorkerParameters) : Worker(cont */ internal fun enqueueWorker() { WorkManager.getInstance().enqueueUniqueWork( - PingUploadWorker.PING_WORKER_TAG, + PING_WORKER_TAG, ExistingWorkPolicy.KEEP, - PingUploadWorker.buildWorkRequest()) + buildWorkRequest()) } /** @@ -63,12 +63,16 @@ class PingUploadWorker(context: Context, params: WorkerParameters) : Worker(cont * * @return true if process was successful */ - internal fun uploadPings(): Boolean { - if (Glean.getUploadEnabled()) { - val httpPingUploader = HttpPingUploader() - return Glean.pingStorageEngine.process(httpPingUploader::upload) - } - return false + private fun uploadPings(): Boolean { + val httpPingUploader = HttpPingUploader() + return Glean.pingStorageEngine.process(httpPingUploader::upload) + } + + /** + * Function to cancel any pending ping upload workers + */ + internal fun cancel() { + WorkManager.getInstance().cancelUniqueWork(PING_WORKER_TAG) } } @@ -85,10 +89,10 @@ class PingUploadWorker(context: Context, params: WorkerParameters) : Worker(cont * @return The [androidx.work.ListenableWorker.Result] of the computation */ override fun doWork(): Result { - if (!uploadPings()) { - return Result.retry() + return when { + !Glean.getUploadEnabled() -> Result.failure() + !uploadPings() -> Result.retry() + else -> Result.success() } - - return Result.success() } } diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt new file mode 100644 index 00000000000..31fb8177acd --- /dev/null +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt @@ -0,0 +1,120 @@ +/* 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 mozilla.components.service.glean.storages + +import android.content.SharedPreferences +import mozilla.components.service.glean.error.ErrorRecording +import mozilla.components.service.glean.histogram.PrecomputedHistogram +import mozilla.components.service.glean.private.CommonMetricData +import mozilla.components.service.glean.private.HistogramType + +import mozilla.components.support.base.log.logger.Logger +import org.json.JSONObject + +/** + * This singleton handles the in-memory storage logic for custom distributions. It is meant to be + * used by the Custom Distribution API and the ping assembling objects. + */ +internal object CustomDistributionsStorageEngine : CustomDistributionsStorageEngineImplementation() + +internal open class CustomDistributionsStorageEngineImplementation( + override val logger: Logger = Logger("glean/CustomDistributionsStorageEngine") +) : GenericStorageEngine() { + + override fun deserializeSingleMetric(metricName: String, value: Any?): PrecomputedHistogram? { + return try { + (value as? String)?.let { + PrecomputedHistogram.fromJsonString(it) + } + } catch (e: org.json.JSONException) { + null + } + } + + override fun serializeSingleMetric( + userPreferences: SharedPreferences.Editor?, + storeName: String, + value: PrecomputedHistogram, + extraSerializationData: Any? + ) { + val json = value.toJsonObject() + userPreferences?.putString(storeName, json.toString()) + } + + /** + * Accumulate an array of samples for the provided metric. + * + * @param metricData the metric information for the custom distribution + * @param samples the values to accumulate + */ + @Suppress("LongParameterList") + @Synchronized + fun accumulateSamples( + metricData: CommonMetricData, + samples: LongArray, + rangeMin: Long, + rangeMax: Long, + bucketCount: Int, + histogramType: HistogramType + ) { + val validSamples = samples.filter { sample -> sample >= 0 } + val numNegativeSamples = samples.size - validSamples.size + if (numNegativeSamples > 0) { + ErrorRecording.recordError( + metricData, + ErrorRecording.ErrorType.InvalidValue, + "Accumulate $numNegativeSamples negative samples", + logger, + numNegativeSamples + ) + return + } + + // Since the custom combiner closure captures this value, we need to just create a dummy + // value here that won't be used by the combine function, and create a fresh + // PrecomputedHistogram for each value that doesn't have an existing current value. + val dummy = PrecomputedHistogram( + rangeMin = rangeMin, + rangeMax = rangeMax, + bucketCount = bucketCount, + histogramType = histogramType + ) + validSamples.forEach { sample -> + super.recordMetric(metricData, dummy, null) { currentValue, _ -> + currentValue?.let { + it.accumulate(sample) + it + } ?: let { + val newTD = PrecomputedHistogram( + rangeMin = rangeMin, + rangeMax = rangeMax, + bucketCount = bucketCount, + histogramType = histogramType + ) + newTD.accumulate(sample) + return@let newTD + } + } + } + } + + /** + * Get a snapshot of the stored data as a JSON object. + * + * @param storeName the name of the desired store + * @param clearStore whether or not to clearStore the requested store + * + * @return the [JSONObject] containing the recorded data. + */ + override fun getSnapshotAsJSON(storeName: String, clearStore: Boolean): Any? { + return getSnapshot(storeName, clearStore)?.let { dataMap -> + val jsonObj = JSONObject() + dataMap.forEach { + jsonObj.put(it.key, it.value.toJsonPayloadObject()) + } + return jsonObj + } + } +} diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/storages/MemoryDistributionsStorageEngine.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/storages/MemoryDistributionsStorageEngine.kt new file mode 100644 index 00000000000..918f36b28fc --- /dev/null +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/storages/MemoryDistributionsStorageEngine.kt @@ -0,0 +1,167 @@ +/* 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 mozilla.components.service.glean.storages + +import android.content.SharedPreferences +import mozilla.components.service.glean.error.ErrorRecording +import mozilla.components.service.glean.histogram.FunctionalHistogram +import mozilla.components.service.glean.private.CommonMetricData +import mozilla.components.service.glean.private.MemoryUnit +import mozilla.components.service.glean.utils.memoryToBytes + +import mozilla.components.support.base.log.logger.Logger +import org.json.JSONObject + +/** + * This singleton handles the in-memory storage logic for memory distributions. It is meant to be + * used by the Memory Distribution API and the ping assembling objects. + */ +internal object MemoryDistributionsStorageEngine : MemoryDistributionsStorageEngineImplementation() + +internal open class MemoryDistributionsStorageEngineImplementation( + override val logger: Logger = Logger("glean/MemoryDistributionsStorageEngine") +) : GenericStorageEngine() { + + companion object { + // The base of the logarithm used to determine bucketing + internal const val LOG_BASE = 2.0 + + // The buckets per each order of magnitude of the logarithm. + internal const val BUCKETS_PER_MAGNITUDE = 16.0 + + // Set a maximum recordable value of 1 terabyte so the buckets aren't + // completely unbounded. + internal const val MAX_BYTES: Long = 1L shl 40 + } + + override fun deserializeSingleMetric(metricName: String, value: Any?): FunctionalHistogram? { + return try { + (value as? String)?.let { + FunctionalHistogram.fromJsonString(it) + } + } catch (e: org.json.JSONException) { + null + } + } + + override fun serializeSingleMetric( + userPreferences: SharedPreferences.Editor?, + storeName: String, + value: FunctionalHistogram, + extraSerializationData: Any? + ) { + val json = value.toJsonObject() + userPreferences?.putString(storeName, json.toString()) + } + + /** + * Accumulate value for the provided metric. + * + * Samples greater than 1TB are truncated to 1TB. + * + * @param metricData the metric information for the memory distribution + * @param sample the value to accumulate + * @param memoryUnit the unit of the sample + */ + @Synchronized + fun accumulate( + metricData: CommonMetricData, + sample: Long, + memoryUnit: MemoryUnit + ) { + accumulateSamples(metricData, longArrayOf(sample), memoryUnit) + } + + /** + * Accumulate an array of samples for the provided metric. + * + * Samples greater than 1TB are truncated to 1TB. + * + * @param metricData the metric information for the memory distribution + * @param samples the values to accumulate, in the given `memoryUnit` + * @param memoryUnit the unit that the given samples are in + */ + @Suppress("ComplexMethod") + @Synchronized + fun accumulateSamples( + metricData: CommonMetricData, + samples: LongArray, + memoryUnit: MemoryUnit + ) { + // Remove invalid samples, and convert to bytes + var numTooLongSamples = 0 + var numNegativeSamples = 0 + var factor = memoryToBytes(memoryUnit, 1) + val validSamples = samples.map { sample -> + if (sample < 0) { + numNegativeSamples += 1 + 0 + } else { + val sampleInBytes = sample * factor + if (sampleInBytes > MAX_BYTES) { + numTooLongSamples += 1 + MAX_BYTES + } else { + sampleInBytes + } + } + } + + if (numNegativeSamples > 0) { + ErrorRecording.recordError( + metricData, + ErrorRecording.ErrorType.InvalidValue, + "Accumulate $numNegativeSamples negative samples", + logger, + numNegativeSamples + ) + // Negative samples indicate a serious and unexpected error, so don't record anything + return + } + + if (numTooLongSamples > 0) { + ErrorRecording.recordError( + metricData, + ErrorRecording.ErrorType.InvalidValue, + "Accumulate $numTooLongSamples samples longer than 1 terabyte", + logger, + numTooLongSamples + ) + // Too large samples should just be truncated, but otherwise we record and handle them + } + + val dummy = FunctionalHistogram(LOG_BASE, BUCKETS_PER_MAGNITUDE) + validSamples.forEach { sample -> + super.recordMetric(metricData, dummy, null) { currentValue, _ -> + currentValue?.let { + it.accumulate(sample) + it + } ?: let { + val newMD = FunctionalHistogram(LOG_BASE, BUCKETS_PER_MAGNITUDE) + newMD.accumulate(sample) + return@let newMD + } + } + } + } + + /** + * Get a snapshot of the stored data as a JSON object. + * + * @param storeName the name of the desired store + * @param clearStore whether or not to clearStore the requested store + * + * @return the [JSONObject] containing the recorded data. + */ + override fun getSnapshotAsJSON(storeName: String, clearStore: Boolean): Any? { + return getSnapshot(storeName, clearStore)?.let { dataMap -> + val jsonObj = JSONObject() + dataMap.forEach { + jsonObj.put(it.key, it.value.toJsonPayloadObject()) + } + return jsonObj + } + } +} diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/storages/StorageEngineManager.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/storages/StorageEngineManager.kt index 8128e2fa172..acd2857e404 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/storages/StorageEngineManager.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/storages/StorageEngineManager.kt @@ -7,7 +7,9 @@ package mozilla.components.service.glean.storages import android.content.Context import mozilla.components.service.glean.private.BooleanMetricType import mozilla.components.service.glean.private.CounterMetricType +import mozilla.components.service.glean.private.CustomDistributionMetricType import mozilla.components.service.glean.private.DatetimeMetricType +import mozilla.components.service.glean.private.MemoryDistributionMetricType import mozilla.components.service.glean.private.StringListMetricType import mozilla.components.service.glean.private.StringMetricType import mozilla.components.service.glean.private.TimespanMetricType @@ -26,8 +28,10 @@ internal class StorageEngineManager( private val storageEngines: Map = mapOf( "boolean" to BooleansStorageEngine, "counter" to CountersStorageEngine, + "custom_distribution" to CustomDistributionsStorageEngine, "datetime" to DatetimesStorageEngine, "events" to EventsStorageEngine, + "memory_distribution" to MemoryDistributionsStorageEngine, "string" to StringsStorageEngine, "string_list" to StringListsStorageEngine, "timespan" to TimespansStorageEngine, @@ -143,7 +147,9 @@ internal class StorageEngineManager( return when (subMetric) { is BooleanMetricType -> BooleansStorageEngine is CounterMetricType -> CountersStorageEngine + is CustomDistributionMetricType -> CustomDistributionsStorageEngine is DatetimeMetricType -> DatetimesStorageEngine + is MemoryDistributionMetricType -> MemoryDistributionsStorageEngine is StringListMetricType -> StringListsStorageEngine is StringMetricType -> StringsStorageEngine is TimingDistributionMetricType -> TimingDistributionsStorageEngine diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/storages/StringListsStorageEngine.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/storages/StringListsStorageEngine.kt index ae564f6b26b..ae232dbfd9d 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/storages/StringListsStorageEngine.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/storages/StringListsStorageEngine.kt @@ -111,7 +111,8 @@ internal open class StringListsStorageEngineImplementation( /** * Sets a string list in the desired stores. This function will replace the existing list or * create a new list if it doesn't already exist. To add or append to an existing list, use - * [add] function. + * [add] function. If an empty list is passed in, then an [ErrorType.InvalidValue] will be + * generated and the method will return without recording. * * @param metricData object with metric settings * @param value the string list value to record @@ -132,6 +133,17 @@ internal open class StringListsStorageEngineImplementation( it.take(MAX_STRING_LENGTH) } + // Record an error when attempting to record a zero-length list and return. + if (stringList.count() == 0) { + recordError( + metricData, + ErrorType.InvalidValue, + "Attempt to set() an empty string list to ${metricData.identifier}", + logger + ) + return + } + if (stringList.count() > MAX_LIST_LENGTH_VALUE) { recordError( metricData, diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt index 1df619c2d1a..73aa8c2979a 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt @@ -4,41 +4,42 @@ package mozilla.components.service.glean.storages -import android.annotation.SuppressLint import android.content.SharedPreferences -import androidx.annotation.VisibleForTesting import mozilla.components.service.glean.error.ErrorRecording +import mozilla.components.service.glean.histogram.FunctionalHistogram import mozilla.components.service.glean.private.CommonMetricData -import mozilla.components.service.glean.private.HistogramType import mozilla.components.service.glean.private.TimeUnit -import mozilla.components.service.glean.utils.getAdjustedTime +import mozilla.components.service.glean.utils.timeToNanos import mozilla.components.support.base.log.logger.Logger -import mozilla.components.support.ktx.android.org.json.tryGetInt -import mozilla.components.support.ktx.android.org.json.tryGetLong -import mozilla.components.support.ktx.android.org.json.tryGetString -import org.json.JSONArray import org.json.JSONObject /** * This singleton handles the in-memory storage logic for timing distributions. It is meant to be * used by the Timing Distribution API and the ping assembling objects. - * - * This class contains a reference to the Android application Context. While the IDE warns - * us that this could leak, the application context lives as long as the application and this - * object. For this reason, we should be safe to suppress the IDE warning. */ -@SuppressLint("StaticFieldLeak") internal object TimingDistributionsStorageEngine : TimingDistributionsStorageEngineImplementation() internal open class TimingDistributionsStorageEngineImplementation( override val logger: Logger = Logger("glean/TimingDistributionsStorageEngine") -) : GenericStorageEngine() { +) : GenericStorageEngine() { - override fun deserializeSingleMetric(metricName: String, value: Any?): TimingDistributionData? { + companion object { + // The base of the logarithm used to determine bucketing + internal const val LOG_BASE = 2.0 + + // The buckets per each order of magnitude of the logarithm. + internal const val BUCKETS_PER_MAGNITUDE = 8.0 + + // Maximum time of 10 minutes in nanoseconds. This maximum means we + // retain a maximum of 313 buckets. + internal const val MAX_SAMPLE_TIME: Long = 1000L * 1000L * 1000L * 60L * 10L + } + + override fun deserializeSingleMetric(metricName: String, value: Any?): FunctionalHistogram? { return try { (value as? String)?.let { - TimingDistributionData.fromJsonString(it) + FunctionalHistogram.fromJsonString(it) } } catch (e: org.json.JSONException) { null @@ -48,7 +49,7 @@ internal open class TimingDistributionsStorageEngineImplementation( override fun serializeSingleMetric( userPreferences: SharedPreferences.Editor?, storeName: String, - value: TimingDistributionData, + value: FunctionalHistogram, extraSerializationData: Any? ) { val json = value.toJsonObject() @@ -58,49 +59,54 @@ internal open class TimingDistributionsStorageEngineImplementation( /** * Accumulate value for the provided metric. * + * Samples greater than 10 minutes in length are truncated to 10 minutes. + * * @param metricData the metric information for the timing distribution * @param sample the value to accumulate, in nanoseconds - * @param timeUnit the [TimeUnit] the sample will be converted to */ @Synchronized fun accumulate( metricData: CommonMetricData, - sample: Long, - timeUnit: TimeUnit + sample: Long ) { - // We're checking for errors in `accumulateSamples` already, but - // we need to check it here too anyway because `getAdjustedTime` would - // throw otherwise. - if (sample < 0) { - ErrorRecording.recordError( - metricData, - ErrorRecording.ErrorType.InvalidValue, - "Accumulate negative $sample", - logger - ) - return - } - - val sampleInUnit = getAdjustedTime(timeUnit, sample) - accumulateSamples(metricData, longArrayOf(sampleInUnit), timeUnit) + accumulateSamples(metricData, longArrayOf(sample)) } /** * Accumulate an array of samples for the provided metric. * + * Samples greater than 10 minutes in length are truncated to 10 minutes. + * * @param metricData the metric information for the timing distribution - * @param samples the values to accumulate, provided in the metric's [TimeUnit] (they won't - * be truncated nor converted) - * @param timeUnit the [TimeUnit] the samples are in + * @param samples the values to accumulate, in the given `timeUnit` + * @param timeUnit the unit that the given samples are in, defaults to nanoseconds */ + @Suppress("ComplexMethod") @Synchronized fun accumulateSamples( metricData: CommonMetricData, samples: LongArray, - timeUnit: TimeUnit + timeUnit: TimeUnit = TimeUnit.Nanosecond ) { - val validSamples = samples.filter { sample -> sample >= 0 } - val numNegativeSamples = samples.size - validSamples.size + // Remove invalid samples, and convert to nanos + var numTooLongSamples = 0 + var numNegativeSamples = 0 + var factor = timeToNanos(timeUnit, 1) + val validSamples = samples.map { sample -> + if (sample < 0) { + numNegativeSamples += 1 + 0 + } else { + val sampleInNanos = sample * factor + if (sampleInNanos > MAX_SAMPLE_TIME) { + numTooLongSamples += 1 + MAX_SAMPLE_TIME + } else { + sampleInNanos + } + } + } + if (numNegativeSamples > 0) { ErrorRecording.recordError( metricData, @@ -109,22 +115,29 @@ internal open class TimingDistributionsStorageEngineImplementation( logger, numNegativeSamples ) + // Negative samples indicate a serious and unexpected error, so don't record anything return } - // Since the custom combiner closure captures this value, we need to just create a dummy - // value here that won't be used by the combine function, and create a fresh - // TimingDistributionData for each value that doesn't have an existing current value. - val dummy = TimingDistributionData(category = metricData.category, name = metricData.name, - timeUnit = timeUnit) + if (numTooLongSamples > 0) { + ErrorRecording.recordError( + metricData, + ErrorRecording.ErrorType.InvalidValue, + "Accumulate $numTooLongSamples samples longer than 10 minutes", + logger, + numTooLongSamples + ) + // Too long samples should just be truncated, but otherwise we record and handle them + } + + val dummy = FunctionalHistogram(LOG_BASE, BUCKETS_PER_MAGNITUDE) validSamples.forEach { sample -> super.recordMetric(metricData, dummy, null) { currentValue, _ -> currentValue?.let { it.accumulate(sample) it } ?: let { - val newTD = TimingDistributionData(category = metricData.category, name = metricData.name, - timeUnit = timeUnit) + val newTD = FunctionalHistogram(LOG_BASE, BUCKETS_PER_MAGNITUDE) newTD.accumulate(sample) return@let newTD } @@ -144,226 +157,9 @@ internal open class TimingDistributionsStorageEngineImplementation( return getSnapshot(storeName, clearStore)?.let { dataMap -> val jsonObj = JSONObject() dataMap.forEach { - jsonObj.put(it.key, it.value.toJsonObject()) + jsonObj.put(it.key, it.value.toJsonPayloadObject()) } return jsonObj } } } - -/** - * This class represents the structure of a timing distribution according to the pipeline schema. It - * is meant to help serialize and deserialize data to the correct format for transport and storage, - * as well as including a helper function to calculate the bucket sizes. - * - * @param category of the metric - * @param name of the metric - * @param bucketCount total number of buckets - * @param rangeMin the minimum value that can be represented - * @param rangeMax the maximum value that can be represented - * @param histogramType the [HistogramType] representing the bucket layout - * @param values a map containing the bucket index mapped to the accumulated count - * @param sum the accumulated sum of all the samples in the timing distribution - * @param timeUnit the base [TimeUnit] of the bucket values - */ -@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) -data class TimingDistributionData( - val category: String, - val name: String, - val bucketCount: Int = DEFAULT_BUCKET_COUNT, - val rangeMin: Long = DEFAULT_RANGE_MIN, - val rangeMax: Long = DEFAULT_RANGE_MAX, - val histogramType: HistogramType = HistogramType.Exponential, - // map from bucket limits to accumulated values - val values: MutableMap = mutableMapOf(), - var sum: Long = 0, - val timeUnit: TimeUnit = TimeUnit.Millisecond -) { - companion object { - // The following are defaults for a simple timing distribution for the default time unit - // of millisecond. The values arrived at were an approximated using existing "_MS" - // telemetry probes as a guide. - const val DEFAULT_BUCKET_COUNT = 100 - const val DEFAULT_RANGE_MIN = 0L - const val DEFAULT_RANGE_MAX = 60000L - - /** - * Factory function that takes stringified JSON and converts it back into a - * [TimingDistributionData]. This tries to read all values and attempts to - * use a default where no value exists. - * - * @param json Stringified JSON value representing a [TimingDistributionData] object - * @return A [TimingDistributionData] or null if unable to rebuild from the string. - */ - @Suppress("ReturnCount", "ComplexMethod") - internal fun fromJsonString(json: String): TimingDistributionData? { - val jsonObject: JSONObject - try { - jsonObject = JSONObject(json) - } catch (e: org.json.JSONException) { - return null - } - - // Category can be empty so it may be possible to be a null value so try and allow this - // by using `orEmpty()` to fill in the value. Other values should be present or else - // something is wrong and we should return null. - val category = jsonObject.tryGetString("category").orEmpty() - val name = jsonObject.tryGetString("name") ?: return null - val bucketCount = jsonObject.tryGetInt("bucket_count") ?: return null - // If 'range' isn't present, JSONException is thrown - val range = try { - val array = jsonObject.getJSONArray("range") - // Range must have exactly 2 values - if (array.length() == 2) { - // The getLong() function throws JSONException if we can't convert to a Long, so - // the catch should return null if either value isn't a valid Long - array.getLong(0) - array.getLong(1) - // This returns the JSONArray to the assignment if everything checks out - array - } else { - return null - } - } catch (e: org.json.JSONException) { - return null - } - val rawHistogramType = jsonObject.tryGetString("histogram_type") ?: return null - val histogramType = try { - HistogramType.valueOf(rawHistogramType.capitalize()) - } catch (e: IllegalArgumentException) { - return null - } - // Attempt to parse the values map, if it fails then something is wrong and we need to - // return null. - val values = try { - val mapData = jsonObject.getJSONObject("values") - val valueMap: MutableMap = mutableMapOf() - mapData.keys().forEach { key -> - valueMap[key.toLong()] = mapData.tryGetLong(key) ?: 0L - } - valueMap - } catch (e: org.json.JSONException) { - // This should only occur if there isn't a key/value pair stored for "values" - return null - } - val sum = jsonObject.tryGetLong("sum") ?: return null - val rawTimeUnit = jsonObject.tryGetString("time_unit") ?: return null - val timeUnit = try { - TimeUnit.valueOf(rawTimeUnit.capitalize()) - } catch (e: IllegalArgumentException) { - return null - } - - return TimingDistributionData( - category = category, - name = name, - bucketCount = bucketCount, - rangeMin = range.getLong(0), - rangeMax = range.getLong(1), - histogramType = histogramType, - values = values, - sum = sum, - timeUnit = timeUnit - ) - } - } - - // This is a calculated read-only property that returns the total count of accumulated values - val count: Long - get() = values.map { it.value }.sum() - - // This is a helper property to build the correct identifier for the metric and allow for - // blank categories - internal val identifier: String = if (category.isEmpty()) { name } else { "$category.$name" } - - // This is a list of limits for the buckets. Instantiated lazily to ensure that the range and - // bucket counts are set first. - internal val buckets: List by lazy { getBuckets() } - - /** - * Accumulates a sample to the correct bucket, using a binary search to locate the index of the - * bucket where the sample is bigger than or equal to the bucket limit. - * If a value doesn't exist for this bucket yet, one is created. - * - * @param sample Long value representing the sample that is being accumulated - */ - internal fun accumulate(sample: Long) { - var under = 0 - var over = bucketCount - var mid: Int - - do { - mid = under + (over - under) / 2 - if (mid == under) { - break - } - - if (buckets[mid] <= sample) { - under = mid - } else { - over = mid - } - } while (true) - - val limit = buckets[mid] - values[limit] = (values[limit] ?: 0) + 1 - sum += sample - } - - /** - * Helper function to build the [TimingDistributionData] into a JSONObject for serialization - * purposes. - */ - internal fun toJsonObject(): JSONObject { - return JSONObject(mapOf( - "category" to category, - "name" to name, - "bucket_count" to bucketCount, - "range" to JSONArray(arrayOf(rangeMin, rangeMax)), - "histogram_type" to histogramType.toString().toLowerCase(), - "values" to values.mapKeys { "${it.key}" }, - "sum" to sum, - "time_unit" to timeUnit.toString().toLowerCase() - )) - } - - /** - * Helper function to generate the list of bucket max values used when accumulating to the - * correct buckets. - * - * @return List containing the bucket limits - */ - private fun getBuckets(): List { - // This algorithm calculates the bucket sizes using a natural log approach to get - // `bucketCount` number of buckets, exponentially spaced between `range[MIN]` and - // `range[MAX]`. - // - // Bucket limits are the minimal bucket value. - // That means values in a bucket `i` are `range[i] <= value < range[i+1]`. - // It will always contain an underflow bucket (`< 1`). - val logMax = Math.log(rangeMax.toDouble()) - val result: MutableList = mutableListOf() - var current = rangeMin - if (current == 0L) { - current = 1L - } - - // underflow bucket - result.add(0) - result.add(current) - - for (i in 2 until bucketCount) { - val logCurrent = Math.log(current.toDouble()) - val logRatio = (logMax - logCurrent) / (bucketCount - i) - val logNext = logCurrent + logRatio - val nextValue = Math.round(Math.exp(logNext)) - if (nextValue > current) { - current = nextValue - } else { - ++current - } - result.add(current) - } - return result.sorted() - } -} diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt index 384decc65bf..9e32e06907c 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt @@ -25,10 +25,14 @@ import org.junit.runner.Description * @get:Rule * val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) * ``` + * + * @param context the application context + * @param configToUse an optional [Configuration] to initialize the Glean SDK with */ @VisibleForTesting(otherwise = VisibleForTesting.NONE) class GleanTestRule( - val context: Context + val context: Context, + val configToUse: Configuration = Configuration() ) : TestWatcher() { override fun starting(description: Description?) { // We're using the WorkManager in a bunch of places, and Glean will crash @@ -37,7 +41,7 @@ class GleanTestRule( Glean.resetGlean( context = context, - config = Configuration(), + config = configToUse, clearStores = true ) } diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/utils/MemoryUtils.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/utils/MemoryUtils.kt new file mode 100644 index 00000000000..974e0227efe --- /dev/null +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/utils/MemoryUtils.kt @@ -0,0 +1,25 @@ +/* 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 mozilla.components.service.glean.utils + +import mozilla.components.service.glean.private.MemoryUnit + +/** + * Convenience method to convert a memory size in a different unit to bytes. + * + * @param memoryUnit the [MemoryUnit] the value is in + * @param value a memory size in the given unit + * + * @return the memory size, in bytes + */ +@Suppress("MagicNumber") +internal fun memoryToBytes(memoryUnit: MemoryUnit, value: Long): Long { + return when (memoryUnit) { + MemoryUnit.Byte -> value + MemoryUnit.Kilobyte -> value shl 10 + MemoryUnit.Megabyte -> value shl 20 + MemoryUnit.Gigabyte -> value shl 30 + } +} diff --git a/components/service/glean/src/main/java/mozilla/components/service/glean/utils/TimeUtils.kt b/components/service/glean/src/main/java/mozilla/components/service/glean/utils/TimeUtils.kt index d1c1765e3cb..8437725f01d 100644 --- a/components/service/glean/src/main/java/mozilla/components/service/glean/utils/TimeUtils.kt +++ b/components/service/glean/src/main/java/mozilla/components/service/glean/utils/TimeUtils.kt @@ -26,3 +26,23 @@ internal fun getAdjustedTime(timeUnit: TimeUnit, elapsedNanos: Long): Long { TimeUnit.Day -> AndroidTimeUnit.NANOSECONDS.toDays(elapsedNanos) } } + +/** + * Convenience method to get a time in a different unit to nanoseconds. + * + * @param timeUnit the unit the value is in + * @param value a time in the given unit + * + * @return the time, in nanoseconds + */ +internal fun timeToNanos(timeUnit: TimeUnit, value: Long): Long { + return when (timeUnit) { + TimeUnit.Nanosecond -> value + TimeUnit.Microsecond -> AndroidTimeUnit.MICROSECONDS.toNanos(value) + TimeUnit.Millisecond -> AndroidTimeUnit.MILLISECONDS.toNanos(value) + TimeUnit.Second -> AndroidTimeUnit.SECONDS.toNanos(value) + TimeUnit.Minute -> AndroidTimeUnit.MINUTES.toNanos(value) + TimeUnit.Hour -> AndroidTimeUnit.HOURS.toNanos(value) + TimeUnit.Day -> AndroidTimeUnit.DAYS.toNanos(value) + } +} diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/histogram/FunctionalHistogramTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/histogram/FunctionalHistogramTest.kt new file mode 100644 index 00000000000..68fff99dd3e --- /dev/null +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/histogram/FunctionalHistogramTest.kt @@ -0,0 +1,70 @@ +/* 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 mozilla.components.service.glean.histogram + +import androidx.test.core.app.ApplicationProvider +import mozilla.components.service.glean.testing.GleanTestRule +import org.junit.Assert.assertEquals +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import java.lang.Math.pow + +@RunWith(RobolectricTestRunner::class) +class FunctionalHistogramTest { + + @get:Rule + val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) + + @Test + fun `sampleToBucketMinimum correctly rounds down`() { + val hist = FunctionalHistogram(2.0, 8.0) + + // Check each of the first 100 integers, where numerical accuracy of the round-tripping + // is most potentially problematic + for (i in (0..100)) { + val value = i.toLong() + val bucketMinimum = hist.sampleToBucketMinimum(value) + assert(bucketMinimum <= value) + + assertEquals(bucketMinimum, hist.sampleToBucketMinimum(bucketMinimum)) + } + + // Do an exponential sampling of higher numbers + for (i in (11..500)) { + val value = pow(1.5, i.toDouble()).toLong() + val bucketMinimum = hist.sampleToBucketMinimum(value) + assert(bucketMinimum <= value) + + assertEquals(bucketMinimum, hist.sampleToBucketMinimum(bucketMinimum)) + } + } + + @Test + fun `toJsonObject correctly converts a FunctionalHistogram object`() { + // Define a FunctionalHistogram object + val tdd = FunctionalHistogram(2.0, 8.0) + + // Accumulate some samples to populate sum and values properties + tdd.accumulate(1L) + tdd.accumulate(2L) + tdd.accumulate(3L) + + // Convert to JSON object using toJsonObject() + val jsonTdd = tdd.toJsonPayloadObject() + + // Verify properties + val jsonValue = jsonTdd.getJSONObject("values") + assertEquals("JSON values must match Timing Distribution values", + tdd.values[1], jsonValue.getLong("1")) + assertEquals("JSON values must match Timing Distribution values", + tdd.values[3], jsonValue.getLong("3")) + assertEquals("JSON values must match Timing Distribution values", + 0, jsonValue.getLong("4")) + assertEquals("JSON sum must match Timing Distribution sum", + tdd.sum, jsonTdd.getLong("sum")) + } +} diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/histogram/PrecomputedHistogramTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/histogram/PrecomputedHistogramTest.kt new file mode 100644 index 00000000000..9a29b3532de --- /dev/null +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/histogram/PrecomputedHistogramTest.kt @@ -0,0 +1,137 @@ +/* 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 mozilla.components.service.glean.histogram + +import androidx.test.core.app.ApplicationProvider +import mozilla.components.service.glean.private.HistogramType +import mozilla.components.service.glean.testing.GleanTestRule +import org.junit.Assert.assertEquals +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class PrecomputedHistogramTest { + @get:Rule + val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) + + @Test + fun `samples go in the correct bucket for exponential bucketing`() { + val td = PrecomputedHistogram( + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + for (i in (0..60)) { + val x = i * 1000L + val bucket = td.findBucket(x) + assert(bucket <= x) + } + + val td2 = PrecomputedHistogram( + rangeMin = 10000L, + rangeMax = 50000L, + bucketCount = 50, + histogramType = HistogramType.Exponential + ) + + for (i in (0..60)) { + val x = i * 1000L + val bucket = td2.findBucket(x) + assert(bucket <= x) + } + } + + @Test + fun `validate the generated linear buckets`() { + val td = PrecomputedHistogram( + rangeMin = 0L, + rangeMax = 99L, + bucketCount = 100, + histogramType = HistogramType.Linear + ) + assertEquals(100, td.buckets.size) + + for (i in (0L until 100L)) { + val bucket = td.findBucket(i) + assert(bucket <= i) + } + + val td2 = PrecomputedHistogram( + rangeMin = 50L, + rangeMax = 50000L, + bucketCount = 50, + histogramType = HistogramType.Linear + ) + assertEquals(50, td2.buckets.size) + + for (i in (0..60)) { + val x: Long = i * 1000L + val bucket = td2.findBucket(x) + assert(bucket <= x) + } + } + + @Test + fun `toJsonObject and toJsonPayloadObject correctly converts a PrecomputedHistogram object`() { + // Define a PrecomputedHistogram object + val tdd = PrecomputedHistogram( + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Accumulate some samples to populate sum and values properties + tdd.accumulate(1L) + tdd.accumulate(2L) + tdd.accumulate(3L) + + // Convert to JSON object using toJsonObject() + val jsonTdd = tdd.toJsonObject() + + // Verify properties + assertEquals("JSON bucket count must match Precomputed Histogram bucket count", + tdd.bucketCount, jsonTdd.getInt("bucket_count")) + val jsonRange = jsonTdd.getJSONArray("range") + assertEquals("JSON range minimum must match Precomputed Histogram range minimum", + tdd.rangeMin, jsonRange.getLong(0)) + assertEquals("JSON range maximum must match Precomputed Histogram range maximum", + tdd.rangeMax, jsonRange.getLong(1)) + assertEquals("JSON histogram type must match Precomputed Histogram histogram type", + tdd.histogramType.toString().toLowerCase(), jsonTdd.getString("histogram_type")) + val jsonValue = jsonTdd.getJSONObject("values") + assertEquals("JSON values must match Precomputed Histogram values", + tdd.values[1], jsonValue.getLong("1")) + assertEquals("JSON values must match Precomputed Histogram values", + tdd.values[2], jsonValue.getLong("2")) + assertEquals("JSON values must match Precomputed Histogram values", + tdd.values[3], jsonValue.getLong("3")) + assertEquals("JSON sum must match Precomputed Histogram sum", + tdd.sum, jsonTdd.getLong("sum")) + + // Convert to JSON object using toJsonObject() + val jsonPayload = tdd.toJsonPayloadObject() + + // Verify properties + assertEquals(2, jsonPayload.length()) + val jsonPayloadValue = jsonPayload.getJSONObject("values") + assertEquals("JSON values must match Precomputed Histogram values", + 0, jsonPayloadValue.getLong("0")) + assertEquals("JSON values must match Precomputed Histogram values", + tdd.values[1], jsonPayloadValue.getLong("1")) + assertEquals("JSON values must match Precomputed Histogram values", + tdd.values[2], jsonPayloadValue.getLong("2")) + assertEquals("JSON values must match Precomputed Histogram values", + tdd.values[3], jsonPayloadValue.getLong("3")) + assertEquals("JSON values must match Precomputed Histogram values", + 0, jsonPayloadValue.getLong("4")) + assertEquals("JSON sum must match Precomputed Histogram sum", + tdd.sum, jsonPayload.getLong("sum")) + } +} diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/private/CustomDistributionMetricTypeTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/private/CustomDistributionMetricTypeTest.kt new file mode 100644 index 00000000000..f9b4b508514 --- /dev/null +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/private/CustomDistributionMetricTypeTest.kt @@ -0,0 +1,176 @@ +/* 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 mozilla.components.service.glean.private + +import androidx.test.core.app.ApplicationProvider +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.ObsoleteCoroutinesApi +import mozilla.components.service.glean.testing.GleanTestRule +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Assert.assertFalse +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import java.lang.NullPointerException + +@ObsoleteCoroutinesApi +@ExperimentalCoroutinesApi +@RunWith(RobolectricTestRunner::class) +class CustomDistributionMetricTypeTest { + + @get:Rule + val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) + + @Test + fun `The API saves to its storage engine`() { + // Define a custom distribution metric which will be stored in "store1" + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Accumulate a few values + for (i in 1L..3L) { + metric.accumulateSamples(listOf(i).toLongArray()) + } + + // Check that data was properly recorded. + assertTrue(metric.testHasValue()) + val snapshot = metric.testGetValue() + // Check the sum + assertEquals(6L, snapshot.sum) + // Check that the 1L fell into the first value bucket + assertEquals(1L, snapshot.values[1]) + // Check that the 2L fell into the second value bucket + assertEquals(1L, snapshot.values[2]) + // Check that the 3L fell into the third value bucket + assertEquals(1L, snapshot.values[3]) + } + + @Test + fun `disabled custom distributions must not record data`() { + // Define a custom distribution metric which will be stored in "store1" + // It's lifetime is set to Lifetime.Ping so it should not record anything. + val metric = CustomDistributionMetricType( + disabled = true, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Attempt to store to the distribution + metric.accumulateSamples(listOf(0L).toLongArray()) + + // Check that nothing was recorded. + assertFalse("CustomDistributions without a lifetime should not record data.", + metric.testHasValue()) + } + + @Test(expected = NullPointerException::class) + fun `testGetValue() throws NullPointerException if nothing is stored`() { + // Define a custom distribution metric which will be stored in "store1" + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + metric.testGetValue() + } + + @Test + fun `The API saves to secondary pings`() { + // Define a custom distribution metric which will be stored in multiple stores + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "custom_distribution", + sendInPings = listOf("store1", "store2", "store3"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Accumulate a few values + metric.accumulateSamples(listOf(1L, 2L, 3L).toLongArray()) + + // Check that data was properly recorded in the second ping. + assertTrue(metric.testHasValue("store2")) + val snapshot = metric.testGetValue("store2") + // Check the sum + assertEquals(6L, snapshot.sum) + // Check that the 1L fell into the first bucket + assertEquals(1L, snapshot.values[1]) + // Check that the 2L fell into the second bucket + assertEquals(1L, snapshot.values[2]) + // Check that the 3L fell into the third bucket + assertEquals(1L, snapshot.values[3]) + + // Check that data was properly recorded in the third ping. + assertTrue(metric.testHasValue("store3")) + val snapshot2 = metric.testGetValue("store3") + // Check the sum + assertEquals(6L, snapshot2.sum) + // Check that the 1L fell into the first bucket + assertEquals(1L, snapshot2.values[1]) + // Check that the 2L fell into the second bucket + assertEquals(1L, snapshot2.values[2]) + // Check that the 3L fell into the third bucket + assertEquals(1L, snapshot2.values[3]) + } + + @Test + fun `The accumulateSamples API correctly stores values`() { + // Define a custom distribution metric which will be stored in multiple stores + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "custom_distribution_samples", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Accumulate a few values + val testSamples = (1L..3L).toList().toLongArray() + metric.accumulateSamples(testSamples) + + // Check that data was properly recorded in the second ping. + assertTrue(metric.testHasValue("store1")) + val snapshot = metric.testGetValue("store1") + // Check the sum + assertEquals(6L, snapshot.sum) + // Check that the 1L fell into the first bucket + assertEquals(1L, snapshot.values[1]) + // Check that the 2L fell into the second bucket + assertEquals(1L, snapshot.values[2]) + // Check that the 3L fell into the third bucket + assertEquals(1L, snapshot.values[3]) + } +} diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/private/MemoryDistributionMetricTypeTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/private/MemoryDistributionMetricTypeTest.kt new file mode 100644 index 00000000000..74984fd1e7b --- /dev/null +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/private/MemoryDistributionMetricTypeTest.kt @@ -0,0 +1,201 @@ +/* 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 mozilla.components.service.glean.private + +import androidx.test.core.app.ApplicationProvider +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.ObsoleteCoroutinesApi +import mozilla.components.service.glean.histogram.FunctionalHistogram +import mozilla.components.service.glean.storages.MemoryDistributionsStorageEngineImplementation +import mozilla.components.service.glean.testing.GleanTestRule +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Assert.assertFalse +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import java.lang.NullPointerException + +@ObsoleteCoroutinesApi +@ExperimentalCoroutinesApi +@RunWith(RobolectricTestRunner::class) +class MemoryDistributionMetricTypeTest { + + @get:Rule + val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) + + @Test + fun `The API saves to its storage engine`() { + // Define a memory distribution metric which will be stored in "store1" + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "memory_distribution", + sendInPings = listOf("store1"), + memoryUnit = MemoryUnit.Kilobyte + ) + + // Accumulate a few values + for (i in 1L..3L) { + metric.accumulate(i) + } + + val kb = 1024 + + // Check that data was properly recorded. + assertTrue(metric.testHasValue()) + val snapshot = metric.testGetValue() + // Check the sum + assertEquals(1L * kb + 2L * kb + 3L * kb, snapshot.sum) + // Check that the 1L fell into the first value bucket + assertEquals(1L, snapshot.values[1023]) + // Check that the 2L fell into the second value bucket + assertEquals(1L, snapshot.values[2047]) + // Check that the 3L fell into the third value bucket + assertEquals(1L, snapshot.values[3024]) + } + + @Test + fun `values are truncated to 1TB`() { + // Define a memory distribution metric which will be stored in "store1" + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "memory_distribution", + sendInPings = listOf("store1"), + memoryUnit = MemoryUnit.Gigabyte + ) + + metric.accumulate(2048L) + + // Check that data was properly recorded. + assertTrue(metric.testHasValue()) + val snapshot = metric.testGetValue() + // Check the sum + assertEquals(1L shl 40, snapshot.sum) + // Check that the 1L fell into 1TB bucket + assertEquals(1L, snapshot.values[(1L shl 40) - 1]) + } + + @Test + fun `disabled memory distributions must not record data`() { + // Define a memory distribution metric which will be stored in "store1" + // It's lifetime is set to Lifetime.Ping so it should not record anything. + val metric = MemoryDistributionMetricType( + disabled = true, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "memory_distribution", + sendInPings = listOf("store1"), + memoryUnit = MemoryUnit.Kilobyte + ) + + metric.accumulate(1L) + + // Check that nothing was recorded. + assertFalse("MemoryDistributions without a lifetime should not record data.", + metric.testHasValue()) + } + + @Test(expected = NullPointerException::class) + fun `testGetValue() throws NullPointerException if nothing is stored`() { + // Define a memory distribution metric which will be stored in "store1" + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "memory_distribution", + sendInPings = listOf("store1"), + memoryUnit = MemoryUnit.Kilobyte + ) + metric.testGetValue() + } + + @Test + fun `The API saves to secondary pings`() { + // Define a memory distribution metric which will be stored in multiple stores + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "memory_distribution", + sendInPings = listOf("store1", "store2", "store3"), + memoryUnit = MemoryUnit.Kilobyte + ) + + // Accumulate a few values + for (i in 1L..3L) { + metric.accumulate(i) + } + + // Check that data was properly recorded in the second ping. + assertTrue(metric.testHasValue("store2")) + val snapshot = metric.testGetValue("store2") + // Check the sum + assertEquals(6144L, snapshot.sum) + // Check that the 1L fell into the first bucket + assertEquals(1L, snapshot.values[1023]) + // Check that the 2L fell into the second bucket + assertEquals(1L, snapshot.values[2047]) + // Check that the 3L fell into the third bucket + assertEquals(1L, snapshot.values[3024]) + + // Check that data was properly recorded in the third ping. + assertTrue(metric.testHasValue("store3")) + val snapshot2 = metric.testGetValue("store3") + // Check the sum + assertEquals(6144L, snapshot2.sum) + // Check that the 1L fell into the first bucket + assertEquals(1L, snapshot2.values[1023]) + // Check that the 2L fell into the second bucket + assertEquals(1L, snapshot2.values[2047]) + // Check that the 3L fell into the third bucket + assertEquals(1L, snapshot2.values[3024]) + } + + @Test + fun `The accumulateSamples API correctly stores memory values`() { + // Define a memory distribution metric which will be stored in multiple stores + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "memory_distribution_samples", + sendInPings = listOf("store1"), + memoryUnit = MemoryUnit.Kilobyte + ) + + // Accumulate a few values + val testSamples = (1L..3L).toList().toLongArray() + metric.accumulateSamples(testSamples) + + val kb = 1024L + val hist = FunctionalHistogram( + MemoryDistributionsStorageEngineImplementation.LOG_BASE, + MemoryDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) + + // Check that data was properly recorded in the second ping. + assertTrue(metric.testHasValue("store1")) + val snapshot = metric.testGetValue("store1") + // Check the sum + assertEquals(6L * kb, snapshot.sum) + // Check that the 1L fell into the first bucket + assertEquals( + 1L, snapshot.values[hist.sampleToBucketMinimum(1 * kb)] + ) + // Check that the 2L fell into the second bucket + assertEquals( + 1L, snapshot.values[hist.sampleToBucketMinimum(2 * kb)] + ) + // Check that the 3L fell into the third bucket + assertEquals( + 1L, snapshot.values[hist.sampleToBucketMinimum(3 * kb)] + ) + } +} diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/private/TimingDistributionMetricTypeTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/private/TimingDistributionMetricTypeTest.kt index 8fc72106f99..ff2af74be46 100644 --- a/components/service/glean/src/test/java/mozilla/components/service/glean/private/TimingDistributionMetricTypeTest.kt +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/private/TimingDistributionMetricTypeTest.kt @@ -7,6 +7,8 @@ package mozilla.components.service.glean.private import androidx.test.core.app.ApplicationProvider import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi +import mozilla.components.service.glean.histogram.FunctionalHistogram +import mozilla.components.service.glean.storages.TimingDistributionsStorageEngineImplementation import mozilla.components.service.glean.testing.GleanTestRule import mozilla.components.service.glean.timing.TimingManager import org.junit.After @@ -48,7 +50,7 @@ class TimingDistributionMetricTypeTest { for (i in 1L..3L) { TimingManager.getElapsedNanos = { 0 } val timerId = metric.start() - TimingManager.getElapsedNanos = { i * 1000000 } // ms to ns + TimingManager.getElapsedNanos = { i } metric.stopAndAccumulate(timerId) } @@ -119,7 +121,7 @@ class TimingDistributionMetricTypeTest { for (i in 1L..3L) { TimingManager.getElapsedNanos = { 0 } val timerId = metric.start() - TimingManager.getElapsedNanos = { i * 1000000 } // ms to ns + TimingManager.getElapsedNanos = { i } metric.stopAndAccumulate(timerId) } @@ -164,16 +166,28 @@ class TimingDistributionMetricTypeTest { val testSamples = (1L..3L).toList().toLongArray() metric.accumulateSamples(testSamples) + val secondsToNanos = 1000L * 1000L * 1000L + val hist = FunctionalHistogram( + TimingDistributionsStorageEngineImplementation.LOG_BASE, + TimingDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) + // Check that data was properly recorded in the second ping. assertTrue(metric.testHasValue("store1")) val snapshot = metric.testGetValue("store1") // Check the sum - assertEquals(6L, snapshot.sum) + assertEquals(6L * secondsToNanos, snapshot.sum) // Check that the 1L fell into the first bucket - assertEquals(1L, snapshot.values[1]) + assertEquals( + 1L, snapshot.values[hist.sampleToBucketMinimum(1 * secondsToNanos)] + ) // Check that the 2L fell into the second bucket - assertEquals(1L, snapshot.values[2]) + assertEquals( + 1L, snapshot.values[hist.sampleToBucketMinimum(2 * secondsToNanos)] + ) // Check that the 3L fell into the third bucket - assertEquals(1L, snapshot.values[3]) + assertEquals( + 1L, snapshot.values[hist.sampleToBucketMinimum(3 * secondsToNanos)] + ) } } diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/scheduler/MetricsPingSchedulerTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/scheduler/MetricsPingSchedulerTest.kt index b9ddcc98a8d..e1a085d52b2 100644 --- a/components/service/glean/src/test/java/mozilla/components/service/glean/scheduler/MetricsPingSchedulerTest.kt +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/scheduler/MetricsPingSchedulerTest.kt @@ -459,6 +459,24 @@ class MetricsPingSchedulerTest { assertTrue(getWorkerStatus(MetricsPingWorker.TAG).isEnqueued) } + @Test + fun `cancel() correctly cancels worker`() { + val mps = MetricsPingScheduler(ApplicationProvider.getApplicationContext()) + + mps.schedulePingCollection(Calendar.getInstance(), true) + + // Verify that the worker is enqueued + assertTrue("MetricsPingWorker is enqueued", + getWorkerStatus(MetricsPingWorker.TAG).isEnqueued) + + // Cancel the worker + MetricsPingScheduler.cancel() + + // Verify worker has been cancelled + assertFalse("MetricsPingWorker is not enqueued", + getWorkerStatus(MetricsPingWorker.TAG).isEnqueued) + } + // @Test // fun `Glean should close the measurement window for overdue pings before recording new data`() { // // This test is a bit tricky: we want to make sure that, when our metrics ping is overdue diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/scheduler/PingUploadWorkerTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/scheduler/PingUploadWorkerTest.kt index 043eabe88e9..802954f3910 100644 --- a/components/service/glean/src/test/java/mozilla/components/service/glean/scheduler/PingUploadWorkerTest.kt +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/scheduler/PingUploadWorkerTest.kt @@ -6,6 +6,7 @@ import androidx.work.BackoffPolicy import androidx.work.NetworkType import androidx.work.WorkerParameters import mozilla.components.service.glean.config.Configuration +import mozilla.components.service.glean.getWorkerStatus import mozilla.components.service.glean.resetGlean import org.junit.Assert import org.junit.Before @@ -50,4 +51,20 @@ class PingUploadWorkerTest { val result = pingUploadWorker!!.doWork() Assert.assertTrue(result.toString().contains("Success")) } + + @Test + fun `cancel() correctly cancels worker`() { + PingUploadWorker.enqueueWorker() + + // Verify that the worker is enqueued + Assert.assertTrue("PingUploadWorker is enqueued", + getWorkerStatus(PingUploadWorker.PING_WORKER_TAG).isEnqueued) + + // Cancel the worker + PingUploadWorker.cancel() + + // Verify worker has been cancelled + Assert.assertFalse("PingUploadWorker is not enqueued", + getWorkerStatus(PingUploadWorker.PING_WORKER_TAG).isEnqueued) + } } diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngineTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngineTest.kt new file mode 100644 index 00000000000..a3325fcd50d --- /dev/null +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngineTest.kt @@ -0,0 +1,457 @@ +/* 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 mozilla.components.service.glean.storages + +import android.content.Context +import android.content.SharedPreferences +import androidx.test.core.app.ApplicationProvider +import kotlinx.coroutines.runBlocking +import mozilla.components.service.glean.collectAndCheckPingSchema +import mozilla.components.service.glean.private.Lifetime +import mozilla.components.service.glean.private.CustomDistributionMetricType +import mozilla.components.service.glean.error.ErrorRecording +import mozilla.components.service.glean.histogram.PrecomputedHistogram +import mozilla.components.service.glean.private.HistogramType +import mozilla.components.service.glean.private.PingType +import mozilla.components.service.glean.testing.GleanTestRule +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers +import org.mockito.Mockito +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class CustomDistributionsStorageEngineTest { + + @get:Rule + val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) + + @Test + fun `accumulate() properly updates the values in all stores`() { + val storeNames = listOf("store1", "store2") + + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "test_custom_distribution", + sendInPings = storeNames, + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Create a sample that will fall into the underflow bucket (bucket '0') so we can easily + // find it + val sample = 1L + CustomDistributionsStorageEngine.accumulateSamples( + metricData = metric, + samples = listOf(sample).toLongArray(), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Check that the data was correctly set in each store. + for (storeName in storeNames) { + val snapshot = CustomDistributionsStorageEngine.getSnapshot( + storeName = storeName, + clearStore = true + ) + assertEquals(1, snapshot!!.size) + assertEquals(1L, snapshot["telemetry.test_custom_distribution"]?.values!![1]) + } + } + + @Test + fun `deserializer should correctly parse custom distributions`() { + val td = PrecomputedHistogram( + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + val persistedSample = mapOf( + "store1#telemetry.invalid_string" to "invalid_string", + "store1#telemetry.invalid_bool" to false, + "store1#telemetry.null" to null, + "store1#telemetry.invalid_int" to -1, + "store1#telemetry.invalid_list" to listOf("1", "2", "3"), + "store1#telemetry.invalid_int_list" to "[1,2,3]", + "store1#telemetry.invalid_td_bucket_count" to "{\"bucket_count\":\"not an int!\",\"range\":[0,60000,12],\"histogram_type\":1,\"values\":{},\"sum\":0}", + "store1#telemetry.invalid_td_range" to "{\"bucket_count\":100,\"range\":[0,60000,12],\"histogram_type\":1,\"values\":{},\"sum\":0}", + "store1#telemetry.invalid_td_range2" to "{\"bucket_count\":100,\"range\":[\"not\",\"numeric\"],\"histogram_type\":1,\"values\":{},\"sum\":0}", + "store1#telemetry.invalid_td_histogram_type" to "{\"bucket_count\":100,\"range\":[0,60000,12],\"histogram_type\":-1,\"values\":{},\"sum\":0}", + "store1#telemetry.invalid_td_values" to "{\"bucket_count\":100,\"range\":[0,60000,12],\"histogram_type\":1,\"values\":{\"0\": \"nope\"},\"sum\":0}", + "store1#telemetry.invalid_td_sum" to "{\"bucket_count\":100,\"range\":[0,60000,12],\"histogram_type\":1,\"values\":{},\"sum\":\"nope\"}", + "store1#telemetry.test_custom_distribution" to td.toJsonObject().toString() + ) + + val storageEngine = CustomDistributionsStorageEngineImplementation() + + // Create a fake application context that will be used to load our data. + val context = Mockito.mock(Context::class.java) + val sharedPreferences = Mockito.mock(SharedPreferences::class.java) + Mockito.`when`(sharedPreferences.all).thenAnswer { persistedSample } + Mockito.`when`(context.getSharedPreferences( + ArgumentMatchers.eq(storageEngine::class.java.canonicalName), + ArgumentMatchers.eq(Context.MODE_PRIVATE) + )).thenReturn(sharedPreferences) + Mockito.`when`(context.getSharedPreferences( + ArgumentMatchers.eq("${storageEngine::class.java.canonicalName}.PingLifetime"), + ArgumentMatchers.eq(Context.MODE_PRIVATE) + )).thenReturn(ApplicationProvider.getApplicationContext() + .getSharedPreferences("${storageEngine::class.java.canonicalName}.PingLifetime", + Context.MODE_PRIVATE)) + + storageEngine.applicationContext = context + val snapshot = storageEngine.getSnapshot(storeName = "store1", clearStore = true) + assertEquals(1, snapshot!!.size) + assertEquals(td.toJsonObject().toString(), + snapshot["telemetry.test_custom_distribution"]?.toJsonObject().toString()) + } + + @Test + fun `serializer should serialize custom distribution that matches schema`() { + val ping1 = PingType("store1", true) + + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + metric.accumulateSamples(listOf(1000000L).toLongArray()) + + collectAndCheckPingSchema(ping1) + } + + @Test + fun `serializer should correctly serialize custom distributions`() { + run { + val storageEngine = CustomDistributionsStorageEngineImplementation() + storageEngine.applicationContext = ApplicationProvider.getApplicationContext() + + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_custom_distribution", + sendInPings = listOf("store1", "store2"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Using the PrecomputedHistogram object here to easily turn the object into JSON + // for comparison purposes. + val td = PrecomputedHistogram( + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + td.accumulate(100L) + + runBlocking { + storageEngine.accumulateSamples( + metricData = metric, + samples = listOf(100L).toLongArray(), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + } + + // Get snapshot from store1 + val json = storageEngine.getSnapshotAsJSON("store1", true) + // Check for correct JSON serialization + assertEquals("{\"${metric.identifier}\":${td.toJsonPayloadObject()}}", + json.toString() + ) + } + + // Create a new instance of storage engine to verify serialization to storage rather than + // to the cache + run { + val storageEngine = CustomDistributionsStorageEngineImplementation() + storageEngine.applicationContext = ApplicationProvider.getApplicationContext() + + val td = PrecomputedHistogram( + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + td.accumulate(100L) + + // Get snapshot from store1 + val json = storageEngine.getSnapshotAsJSON("store1", true) + // Check for correct JSON serialization + assertEquals("{\"telemetry.test_custom_distribution\":${td.toJsonPayloadObject()}}", + json.toString() + ) + } + } + + @Test + fun `custom distributions must not accumulate negative values`() { + // Define a custom distribution metric, which will be stored in "store1". + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Attempt to accumulate a negative sample + metric.accumulateSamples(listOf(-1L).toLongArray()) + // Check that nothing was recorded. + assertFalse("Custom distributions must not accumulate negative values", + metric.testHasValue()) + + // Make sure that the errors have been recorded + assertEquals("Accumulating negative values must generate an error", + 1, + ErrorRecording.testGetNumRecordedErrors(metric, ErrorRecording.ErrorType.InvalidValue)) + } + + @Test + fun `underflow values accumulate in the first bucket`() { + // Define a custom distribution metric, which will be stored in "store1". + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Attempt to accumulate an overflow sample + metric.accumulateSamples(listOf(0L).toLongArray()) + + // Check that custom distribution was recorded. + assertTrue("Accumulating underflow values records data", + metric.testHasValue()) + + // Make sure that the underflow landed in the correct (first) bucket + val snapshot = metric.testGetValue() + assertEquals("Accumulating overflow values should increment underflow bucket", + 1L, + snapshot.values[0]) + } + + @Test + fun `overflow values accumulate in the last bucket`() { + val rangeMax = 60000L + + // Define a custom distribution metric, which will be stored in "store1". + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Attempt to accumulate an overflow sample + metric.accumulateSamples(listOf(rangeMax + 100 * 1000000).toLongArray()) + + // Check that custom distribution was recorded. + assertTrue("Accumulating overflow values records data", + metric.testHasValue()) + + // Make sure that the overflow landed in the correct (last) bucket + val snapshot = metric.testGetValue() + assertEquals("Accumulating overflow values should increment last bucket", + 1L, + snapshot.values[rangeMax]) + } + + @Test + fun `getBuckets() correctly populates the buckets properly for exponential distributions`() { + // Hand calculated values using current default range 0 - 60000 and bucket count of 100. + // NOTE: The final bucket, regardless of width, represents the overflow bucket to hold any + // values beyond the maximum (in this case the maximum is 60000) + val testBuckets: List = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, + 19, 21, 23, 25, 28, 31, 34, 38, 42, 46, 51, 56, 62, 68, 75, 83, 92, 101, 111, 122, 135, + 149, 164, 181, 200, 221, 244, 269, 297, 328, 362, 399, 440, 485, 535, 590, 651, 718, + 792, 874, 964, 1064, 1174, 1295, 1429, 1577, 1740, 1920, 2118, 2337, 2579, 2846, 3140, + 3464, 3822, 4217, 4653, 5134, 5665, 6250, 6896, 7609, 8395, 9262, 10219, 11275, 12440, + 13726, 15144, 16709, 18436, 20341, 22443, 24762, 27321, 30144, 33259, 36696, 40488, + 44672, 49288, 54381, 60000) + + // Define a custom distribution metric, which will be stored in "store1". + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Accumulate a sample to force the lazy loading of `buckets` to occur + metric.accumulateSamples(listOf(0L).toLongArray()) + + // Check that custom distribution was recorded. + assertTrue("Accumulating values records data", metric.testHasValue()) + + // Make sure that the sample in the correct (underflow) bucket + val snapshot = metric.testGetValue() + assertEquals("Accumulating should increment correct bucket", + 1L, snapshot.values[0]) + + // verify buckets lists worked + assertNotNull("Buckets must not be null", snapshot.buckets) + + assertEquals("Bucket calculation failed", testBuckets, snapshot.buckets) + } + + @Test + fun `accumulate finds the correct bucket for exponential distributions`() { + // Define a custom distribution metric, which will be stored in "store1". + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Exponential + ) + + // Check that a few values correctly fall into the correct buckets (as calculated by hand) + // to validate the linear bucket search algorithm + + // Attempt to accumulate a sample to force metric to be stored + metric.accumulateSamples(listOf(1L, 10L, 100L, 1000L, 10000L).toLongArray()) + + // Check that custom distribution was recorded. + assertTrue("Accumulating values records data", metric.testHasValue()) + + // Make sure that the samples are in the correct buckets + val snapshot = metric.testGetValue() + + // Check sum and count + assertEquals("Accumulating updates the sum", 11111, snapshot.sum) + assertEquals("Accumulating updates the count", 5, snapshot.count) + + assertEquals("Accumulating should increment correct bucket", + 1L, snapshot.values[1]) + assertEquals("Accumulating should increment correct bucket", + 1L, snapshot.values[10]) + assertEquals("Accumulating should increment correct bucket", + 1L, snapshot.values[92]) + assertEquals("Accumulating should increment correct bucket", + 1L, snapshot.values[964]) + assertEquals("Accumulating should increment correct bucket", + 1L, snapshot.values[9262]) + } + + @Test + fun `accumulate finds the correct bucket for linear distributions`() { + // Define a custom distribution metric, which will be stored in "store1". + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Linear + ) + + // Check that a few values correctly fall into the correct buckets (as calculated by hand) + // to validate the linear bucket search algorithm + + // Attempt to accumulate a sample to force metric to be stored + metric.accumulateSamples(listOf(1L, 10L, 100L, 1000L, 10000L).toLongArray()) + + // Check that custom distribution was recorded. + assertTrue("Accumulating values records data", metric.testHasValue()) + + // Make sure that the samples are in the correct buckets + val snapshot = metric.testGetValue() + + // Check sum and count + assertEquals("Accumulating updates the sum", 11111, snapshot.sum) + assertEquals("Accumulating updates the count", 5, snapshot.count) + + assertEquals("Accumulating should increment correct bucket", + 3L, snapshot.values[0]) + assertEquals("Accumulating should increment correct bucket", + 1L, snapshot.values[612]) + assertEquals("Accumulating should increment correct bucket", + 1L, snapshot.values[9796]) + } + + @Test + fun `toJsonPayloadObject correctly inserts zero buckets`() { + // Define a custom distribution metric, which will be stored in "store1". + val metric = CustomDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_custom_distribution", + sendInPings = listOf("store1"), + rangeMin = 0L, + rangeMax = 60000L, + bucketCount = 100, + histogramType = HistogramType.Linear + ) + + metric.accumulateSamples(listOf(10000L).toLongArray()) + + // Make sure that the samples are in the correct buckets + val snapshot = metric.testGetValue() + val payload = snapshot.toJsonPayloadObject() + val payloadValues = payload.getJSONObject("values") + + assertEquals(18, payloadValues.length()) + assertEquals(1L, payloadValues["9796"]) + for (key in payloadValues.keys()) { + if (key != "9796") { + assertEquals(0L, payloadValues[key]) + } + } + } +} diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/storages/MemoryDistributionsStorageEngineTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/storages/MemoryDistributionsStorageEngineTest.kt new file mode 100644 index 00000000000..d209d7c16c3 --- /dev/null +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/storages/MemoryDistributionsStorageEngineTest.kt @@ -0,0 +1,298 @@ +/* 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 mozilla.components.service.glean.storages + +import android.content.Context +import android.content.SharedPreferences +import androidx.test.core.app.ApplicationProvider +import kotlinx.coroutines.runBlocking +import mozilla.components.service.glean.collectAndCheckPingSchema +import mozilla.components.service.glean.private.Lifetime +import mozilla.components.service.glean.private.MemoryDistributionMetricType +import mozilla.components.service.glean.error.ErrorRecording +import mozilla.components.service.glean.histogram.FunctionalHistogram +import mozilla.components.service.glean.private.MemoryUnit +import mozilla.components.service.glean.private.PingType +import mozilla.components.service.glean.testing.GleanTestRule +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Assert.assertEquals +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers +import org.mockito.Mockito +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class MemoryDistributionsStorageEngineTest { + + @get:Rule + val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) + + @Test + fun `accumulate() properly updates the values in all stores`() { + val storeNames = listOf("store1", "store2") + + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "test_memory_distribution", + sendInPings = storeNames, + memoryUnit = MemoryUnit.Kilobyte + ) + + // Create a sample that will fall into the underflow bucket (bucket '0') so we can easily + // find it + val sample = 1L + MemoryDistributionsStorageEngine.accumulate( + metricData = metric, + sample = sample, + memoryUnit = MemoryUnit.Kilobyte + ) + + // Check that the data was correctly set in each store. + for (storeName in storeNames) { + val snapshot = MemoryDistributionsStorageEngine.getSnapshot( + storeName = storeName, + clearStore = true + ) + assertEquals(1, snapshot!!.size) + assertEquals(1L, snapshot["telemetry.test_memory_distribution"]?.values!![1023]) + } + } + + @Test + fun `deserializer should correctly parse memory distributions`() { + val md = FunctionalHistogram( + MemoryDistributionsStorageEngineImplementation.LOG_BASE, + MemoryDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) + + val persistedSample = mapOf( + "store1#telemetry.invalid_string" to "invalid_string", + "store1#telemetry.invalid_bool" to false, + "store1#telemetry.null" to null, + "store1#telemetry.invalid_int" to -1, + "store1#telemetry.invalid_list" to listOf("1", "2", "3"), + "store1#telemetry.invalid_int_list" to "[1,2,3]", + "store1#telemetry.invalid_md_values" to "{\"log_base\":2.0,\"buckets_per_magnitude\":16.0,\"values\":{\"0\": \"nope\"},\"sum\":0}", + "store1#telemetry.invalid_md_sum" to "{\"log_base\":2.0,\"buckets_per_magnitude\":16.0,\"values\":{},\"sum\":\"nope\"}", + "store1#telemetry.test_memory_distribution" to md.toJsonObject().toString() + ) + + val storageEngine = MemoryDistributionsStorageEngineImplementation() + + // Create a fake application context that will be used to load our data. + val context = Mockito.mock(Context::class.java) + val sharedPreferences = Mockito.mock(SharedPreferences::class.java) + Mockito.`when`(sharedPreferences.all).thenAnswer { persistedSample } + Mockito.`when`(context.getSharedPreferences( + ArgumentMatchers.eq(storageEngine::class.java.canonicalName), + ArgumentMatchers.eq(Context.MODE_PRIVATE) + )).thenReturn(sharedPreferences) + Mockito.`when`(context.getSharedPreferences( + ArgumentMatchers.eq("${storageEngine::class.java.canonicalName}.PingLifetime"), + ArgumentMatchers.eq(Context.MODE_PRIVATE) + )).thenReturn(ApplicationProvider.getApplicationContext() + .getSharedPreferences("${storageEngine::class.java.canonicalName}.PingLifetime", + Context.MODE_PRIVATE)) + + storageEngine.applicationContext = context + val snapshot = storageEngine.getSnapshot(storeName = "store1", clearStore = true) + assertEquals(1, snapshot!!.size) + assertEquals(md.toJsonObject().toString(), + snapshot["telemetry.test_memory_distribution"]?.toJsonObject().toString()) + } + + @Test + fun `serializer should serialize memory distribution that matches schema`() { + val ping1 = PingType("store1", true) + + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_memory_distribution", + sendInPings = listOf("store1"), + memoryUnit = MemoryUnit.Kilobyte + ) + + runBlocking { + metric.accumulate(100000L) + } + + collectAndCheckPingSchema(ping1) + } + + @Test + fun `serializer should correctly serialize memory distributions`() { + run { + val storageEngine = MemoryDistributionsStorageEngineImplementation() + storageEngine.applicationContext = ApplicationProvider.getApplicationContext() + + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_memory_distribution", + sendInPings = listOf("store1", "store2"), + memoryUnit = MemoryUnit.Kilobyte + ) + + // Using the FunctionalHistogram object here to easily turn the object into JSON + // for comparison purposes. + val md = FunctionalHistogram( + MemoryDistributionsStorageEngineImplementation.LOG_BASE, + MemoryDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) + md.accumulate(1000000L * 1024L) + + runBlocking { + storageEngine.accumulate( + metricData = metric, + sample = 1000000L, + memoryUnit = MemoryUnit.Kilobyte + ) + } + + // Get snapshot from store1 + val json = storageEngine.getSnapshotAsJSON("store1", true) + // Check for correct JSON serialization + assertEquals("{\"${metric.identifier}\":${md.toJsonPayloadObject()}}", + json.toString() + ) + } + + // Create a new instance of storage engine to verify serialization to storage rather than + // to the cache + run { + val storageEngine = MemoryDistributionsStorageEngineImplementation() + storageEngine.applicationContext = ApplicationProvider.getApplicationContext() + + val md = FunctionalHistogram( + MemoryDistributionsStorageEngineImplementation.LOG_BASE, + MemoryDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) + md.accumulate(1000000L * 1024) + + // Get snapshot from store1 + val json = storageEngine.getSnapshotAsJSON("store1", true) + // Check for correct JSON serialization + assertEquals("{\"telemetry.test_memory_distribution\":${md.toJsonPayloadObject()}}", + json.toString() + ) + } + } + + @Test + fun `memory distributions must not accumulate negative values`() { + // Define a memory distribution metric, which will be stored in "store1". + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_memory_distribution", + sendInPings = listOf("store1"), + memoryUnit = MemoryUnit.Byte + ) + + metric.accumulate(-1) + // Check that nothing was recorded. + assertFalse("Memory distributions must not accumulate negative values", + metric.testHasValue()) + + // Make sure that the errors have been recorded + assertEquals("Accumulating negative values must generate an error", + 1, + ErrorRecording.testGetNumRecordedErrors(metric, ErrorRecording.ErrorType.InvalidValue)) + } + + @Test + fun `overflow values accumulate in the last bucket`() { + // Define a memory distribution metric, which will be stored in "store1". + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_memory_distribution", + sendInPings = listOf("store1"), + memoryUnit = MemoryUnit.Byte + ) + + // Attempt to accumulate an overflow sample + metric.accumulate(1L shl 41) + + val hist = FunctionalHistogram( + MemoryDistributionsStorageEngineImplementation.LOG_BASE, + MemoryDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) + + // Check that memory distribution was recorded. + assertTrue("Accumulating overflow values records data", + metric.testHasValue()) + + // Make sure that the overflow landed in the correct (last) bucket + val snapshot = metric.testGetValue() + assertEquals("Accumulating overflow values should increment last bucket", + 1L, + snapshot.values[hist.sampleToBucketMinimum(MemoryDistributionsStorageEngineImplementation.MAX_BYTES)]) + } + + @Test + fun `accumulate finds the correct bucket`() { + // Define a memory distribution metric, which will be stored in "store1". + val metric = MemoryDistributionMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.User, + name = "test_memory_distribution", + sendInPings = listOf("store1"), + memoryUnit = MemoryUnit.Byte + ) + + val samples = listOf(10L, 100L, 1000L, 10000L) + + // Attempt to accumulate a sample to force metric to be stored + for (i in samples) { + metric.accumulate(i) + } + + // Check that memory distribution was recorded. + assertTrue("Accumulating values records data", metric.testHasValue()) + + // Make sure that the samples are in the correct buckets + val snapshot = metric.testGetValue() + + // Check sum and count + assertEquals("Accumulating updates the sum", 11110, snapshot.sum) + assertEquals("Accumulating updates the count", 4, snapshot.count) + + val hist = FunctionalHistogram( + MemoryDistributionsStorageEngineImplementation.LOG_BASE, + MemoryDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) + + for (i in samples) { + val binEdge = hist.sampleToBucketMinimum(i) + assertEquals("Accumulating should increment correct bucket", 1L, snapshot.values[binEdge]) + } + + val json = snapshot.toJsonPayloadObject() + val values = json.getJSONObject("values") + assertEquals(154, values.length()) + + for (i in samples) { + val binEdge = hist.sampleToBucketMinimum(i) + assertEquals("Accumulating should increment correct bucket", 1L, values.getLong(binEdge.toString())) + values.remove(binEdge.toString()) + } + + for (k in values.keys()) { + assertEquals(0L, values.getLong(k)) + } + } +} diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/storages/StringListsStorageEngineTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/storages/StringListsStorageEngineTest.kt index c9ab04e5ce9..f82a4017945 100644 --- a/components/service/glean/src/test/java/mozilla/components/service/glean/storages/StringListsStorageEngineTest.kt +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/storages/StringListsStorageEngineTest.kt @@ -16,6 +16,7 @@ import org.json.JSONArray import org.json.JSONObject import org.junit.Assert import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Rule import org.junit.Test @@ -201,6 +202,28 @@ class StringListsStorageEngineTest { assertEquals(1, testGetNumRecordedErrors(metric, ErrorType.InvalidValue)) } + @Test + fun `set() records an error and returns when passed an empty list`() { + val metric = StringListMetricType( + disabled = false, + category = "telemetry", + lifetime = Lifetime.Ping, + name = "string_list_metric", + sendInPings = listOf("store1") + ) + + StringListsStorageEngine.set(metricData = metric, value = listOf()) + + // If nothing was stored, then the snapshot should be null + val snapshot = StringListsStorageEngine.getSnapshot( + storeName = "store1", + clearStore = false) + assertNull("Empty list must not be stored", snapshot) + + // Verify the error was recorded + assertEquals(1, testGetNumRecordedErrors(metric, ErrorType.InvalidValue)) + } + @Test fun `string list deserializer should correctly parse string lists`() { val persistedSample = mapOf( diff --git a/components/service/glean/src/test/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngineTest.kt b/components/service/glean/src/test/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngineTest.kt index 2734e9e3aab..09ce19fba30 100644 --- a/components/service/glean/src/test/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngineTest.kt +++ b/components/service/glean/src/test/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngineTest.kt @@ -1,6 +1,6 @@ /* 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/. */ + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package mozilla.components.service.glean.storages @@ -13,6 +13,7 @@ import mozilla.components.service.glean.private.Lifetime import mozilla.components.service.glean.private.TimeUnit import mozilla.components.service.glean.private.TimingDistributionMetricType import mozilla.components.service.glean.error.ErrorRecording +import mozilla.components.service.glean.histogram.FunctionalHistogram import mozilla.components.service.glean.private.PingType import mozilla.components.service.glean.testing.GleanTestRule import mozilla.components.service.glean.timing.TimingManager @@ -20,7 +21,6 @@ import org.junit.After import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -57,8 +57,7 @@ class TimingDistributionsStorageEngineTest { val sample = 1L TimingDistributionsStorageEngine.accumulate( metricData = metric, - sample = sample, - timeUnit = metric.timeUnit + sample = sample ) // Check that the data was correctly set in each store. @@ -68,23 +67,16 @@ class TimingDistributionsStorageEngineTest { clearStore = true ) assertEquals(1, snapshot!!.size) - assertEquals(1L, snapshot["telemetry.test_timing_distribution"]?.values!![0]) + assertEquals(1L, snapshot["telemetry.test_timing_distribution"]?.values!![1]) } } @Test fun `deserializer should correctly parse timing distributions`() { - // We are using the TimingDistributionData here as a way to turn the object - // into JSON for easy comparison - val metric = TimingDistributionMetricType( - disabled = false, - category = "telemetry", - lifetime = Lifetime.Ping, - name = "test_timing_distribution", - sendInPings = listOf("store1", "store2"), - timeUnit = TimeUnit.Millisecond + val td = FunctionalHistogram( + TimingDistributionsStorageEngineImplementation.LOG_BASE, + TimingDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE ) - val td = TimingDistributionData(category = metric.category, name = metric.name) val persistedSample = mapOf( "store1#telemetry.invalid_string" to "invalid_string", @@ -93,14 +85,8 @@ class TimingDistributionsStorageEngineTest { "store1#telemetry.invalid_int" to -1, "store1#telemetry.invalid_list" to listOf("1", "2", "3"), "store1#telemetry.invalid_int_list" to "[1,2,3]", - "store1#telemetry.invalid_td_name" to "{\"category\":\"telemetry\",\"bucket_count\":100,\"range\":[0,60000,12],\"histogram_type\":1,\"values\":{},\"sum\":0,\"time_unit\":2}", - "store1#telemetry.invalid_td_bucket_count" to "{\"category\":\"telemetry\",\"name\":\"test_timing_distribution\",\"bucket_count\":\"not an int!\",\"range\":[0,60000,12],\"histogram_type\":1,\"values\":{},\"sum\":0,\"time_unit\":2}", - "store1#telemetry.invalid_td_range" to "{\"category\":\"telemetry\",\"name\":\"test_timing_distribution\",\"bucket_count\":100,\"range\":[0,60000,12],\"histogram_type\":1,\"values\":{},\"sum\":0,\"time_unit\":2}", - "store1#telemetry.invalid_td_range2" to "{\"category\":\"telemetry\",\"name\":\"test_timing_distribution\",\"bucket_count\":100,\"range\":[\"not\",\"numeric\"],\"histogram_type\":1,\"values\":{},\"sum\":0,\"time_unit\":2}", - "store1#telemetry.invalid_td_histogram_type" to "{\"category\":\"telemetry\",\"name\":\"test_timing_distribution\",\"bucket_count\":100,\"range\":[0,60000,12],\"histogram_type\":-1,\"values\":{},\"sum\":0,\"time_unit\":2}", - "store1#telemetry.invalid_td_values" to "{\"category\":\"telemetry\",\"name\":\"test_timing_distribution\",\"bucket_count\":100,\"range\":[0,60000,12],\"histogram_type\":1,\"values\":{\"0\": \"nope\"},\"sum\":0,\"time_unit\":2}", - "store1#telemetry.invalid_td_sum" to "{\"category\":\"telemetry\",\"name\":\"test_timing_distribution\",\"bucket_count\":100,\"range\":[0,60000,12],\"histogram_type\":1,\"values\":{},\"sum\":\"nope\",\"time_unit\":2}", - "store1#telemetry.invalid_td_time_unit" to "{\"category\":\"telemetry\",\"name\":\"test_timing_distribution\",\"bucket_count\":100,\"range\":[0,60000,12],\"histogram_type\":1,\"values\":{},\"sum\":0,\"time_unit\":-1}", + "store1#telemetry.invalid_td_values" to "{\"log_base\":2.0,\"buckets_per_magnitude\":8.0,\"values\":{\"0\": \"nope\"},\"sum\":0}", + "store1#telemetry.invalid_td_sum" to "{\"log_base\":2.0,\"buckets_per_magnitude\":8.0,\"values\":{},\"sum\":\"nope\"}", "store1#telemetry.test_timing_distribution" to td.toJsonObject().toString() ) @@ -166,23 +152,25 @@ class TimingDistributionsStorageEngineTest { timeUnit = TimeUnit.Millisecond ) - // Using the TimingDistributionData object here to easily turn the object into JSON + // Using the FunctionalHistogram object here to easily turn the object into JSON // for comparison purposes. - val td = TimingDistributionData(category = metric.category, name = metric.name) - td.accumulate(1L) + val td = FunctionalHistogram( + TimingDistributionsStorageEngineImplementation.LOG_BASE, + TimingDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) + td.accumulate(1000000L) runBlocking { storageEngine.accumulate( metricData = metric, - sample = 1000000L, - timeUnit = metric.timeUnit + sample = 1000000L ) } // Get snapshot from store1 val json = storageEngine.getSnapshotAsJSON("store1", true) // Check for correct JSON serialization - assertEquals("{\"${metric.identifier}\":${td.toJsonObject()}}", + assertEquals("{\"${metric.identifier}\":${td.toJsonPayloadObject()}}", json.toString() ) } @@ -193,13 +181,16 @@ class TimingDistributionsStorageEngineTest { val storageEngine = TimingDistributionsStorageEngineImplementation() storageEngine.applicationContext = ApplicationProvider.getApplicationContext() - val td = TimingDistributionData(category = "telemetry", name = "test_timing_distribution") - td.accumulate(1L) + val td = FunctionalHistogram( + TimingDistributionsStorageEngineImplementation.LOG_BASE, + TimingDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) + td.accumulate(1000000L) // Get snapshot from store1 val json = storageEngine.getSnapshotAsJSON("store1", true) // Check for correct JSON serialization - assertEquals("{\"telemetry.test_timing_distribution\":${td.toJsonObject()}}", + assertEquals("{\"telemetry.test_timing_distribution\":${td.toJsonPayloadObject()}}", json.toString() ) } @@ -232,35 +223,6 @@ class TimingDistributionsStorageEngineTest { ErrorRecording.testGetNumRecordedErrors(metric, ErrorRecording.ErrorType.InvalidValue)) } - @Test - fun `underflow values accumulate in the first bucket`() { - // Define a timing distribution metric, which will be stored in "store1". - val metric = TimingDistributionMetricType( - disabled = false, - category = "telemetry", - lifetime = Lifetime.User, - name = "test_timing_distribution", - sendInPings = listOf("store1"), - timeUnit = TimeUnit.Millisecond - ) - - // Attempt to accumulate an overflow sample - TimingManager.getElapsedNanos = { 0 } - val timerId = metric.start() - TimingManager.getElapsedNanos = { 0 } - metric.stopAndAccumulate(timerId) - - // Check that timing distribution was recorded. - assertTrue("Accumulating underflow values records data", - metric.testHasValue()) - - // Make sure that the underflow landed in the correct (first) bucket - val snapshot = metric.testGetValue() - assertEquals("Accumulating overflow values should increment underflow bucket", - 1L, - snapshot.values[0]) - } - @Test fun `overflow values accumulate in the last bucket`() { // Define a timing distribution metric, which will be stored in "store1". @@ -276,7 +238,7 @@ class TimingDistributionsStorageEngineTest { // Attempt to accumulate an overflow sample TimingManager.getElapsedNanos = { 0 } val timerId = metric.start() - TimingManager.getElapsedNanos = { (TimingDistributionData.DEFAULT_RANGE_MAX + 100) * 1000000 } + TimingManager.getElapsedNanos = { TimingDistributionsStorageEngineImplementation.MAX_SAMPLE_TIME * 2 } metric.stopAndAccumulate(timerId) // Check that timing distribution was recorded. @@ -284,53 +246,14 @@ class TimingDistributionsStorageEngineTest { metric.testHasValue()) // Make sure that the overflow landed in the correct (last) bucket + val hist = FunctionalHistogram( + TimingDistributionsStorageEngineImplementation.LOG_BASE, + TimingDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) val snapshot = metric.testGetValue() assertEquals("Accumulating overflow values should increment last bucket", 1L, - snapshot.values[TimingDistributionData.DEFAULT_RANGE_MAX]) - } - - @Test - fun `getBuckets() correctly populates the buckets property`() { - // Hand calculated values using current default range 0 - 60000 and bucket count of 100. - // NOTE: The final bucket, regardless of width, represents the overflow bucket to hold any - // values beyond the maximum (in this case the maximum is 60000) - val testBuckets: List = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, - 19, 21, 23, 25, 28, 31, 34, 38, 42, 46, 51, 56, 62, 68, 75, 83, 92, 101, 111, 122, 135, - 149, 164, 181, 200, 221, 244, 269, 297, 328, 362, 399, 440, 485, 535, 590, 651, 718, - 792, 874, 964, 1064, 1174, 1295, 1429, 1577, 1740, 1920, 2118, 2337, 2579, 2846, 3140, - 3464, 3822, 4217, 4653, 5134, 5665, 6250, 6896, 7609, 8395, 9262, 10219, 11275, 12440, - 13726, 15144, 16709, 18436, 20341, 22443, 24762, 27321, 30144, 33259, 36696, 40488, - 44672, 49288, 54381, 60000) - - // Define a timing distribution metric, which will be stored in "store1". - val metric = TimingDistributionMetricType( - disabled = false, - category = "telemetry", - lifetime = Lifetime.User, - name = "test_timing_distribution", - sendInPings = listOf("store1"), - timeUnit = TimeUnit.Millisecond - ) - - // Accumulate a sample to force the lazy loading of `buckets` to occur - TimingManager.getElapsedNanos = { 0 } - val timerId = metric.start() - TimingManager.getElapsedNanos = { 1 } - metric.stopAndAccumulate(timerId) - - // Check that timing distribution was recorded. - assertTrue("Accumulating values records data", metric.testHasValue()) - - // Make sure that the sample in the correct (underflow) bucket - val snapshot = metric.testGetValue() - assertEquals("Accumulating should increment correct bucket", - 1L, snapshot.values[0]) - - // verify buckets lists worked - assertNotNull("Buckets must not be null", snapshot.buckets) - - assertEquals("Bucket calculation failed", testBuckets, snapshot.buckets) + snapshot.values[hist.sampleToBucketMinimum(TimingDistributionsStorageEngineImplementation.MAX_SAMPLE_TIME)]) } @Test @@ -345,14 +268,13 @@ class TimingDistributionsStorageEngineTest { timeUnit = TimeUnit.Millisecond ) - // Check that a few values correctly fall into the correct buckets (as calculated by hand) - // to validate the linear bucket search algorithm + val samples = listOf(10L, 100L, 1000L, 10000L) // Attempt to accumulate a sample to force metric to be stored - for (i in listOf(1L, 10L, 100L, 1000L, 10000L)) { + for (i in samples) { TimingManager.getElapsedNanos = { 0 } val timerId = metric.start() - TimingManager.getElapsedNanos = { i * 1000000 } // Convert ms to ns + TimingManager.getElapsedNanos = { i } metric.stopAndAccumulate(timerId) } @@ -362,61 +284,32 @@ class TimingDistributionsStorageEngineTest { // Make sure that the samples are in the correct buckets val snapshot = metric.testGetValue() + val hist = FunctionalHistogram( + TimingDistributionsStorageEngineImplementation.LOG_BASE, + TimingDistributionsStorageEngineImplementation.BUCKETS_PER_MAGNITUDE + ) + // Check sum and count - assertEquals("Accumulating updates the sum", 11111, snapshot.sum) - assertEquals("Accumulating updates the count", 5, snapshot.count) - - assertEquals("Accumulating should increment correct bucket", - 1L, snapshot.values[1]) - assertEquals("Accumulating should increment correct bucket", - 1L, snapshot.values[10]) - assertEquals("Accumulating should increment correct bucket", - 1L, snapshot.values[92]) - assertEquals("Accumulating should increment correct bucket", - 1L, snapshot.values[964]) - assertEquals("Accumulating should increment correct bucket", - 1L, snapshot.values[9262]) - } + assertEquals("Accumulating updates the sum", 11110, snapshot.sum) + assertEquals("Accumulating updates the count", 4, snapshot.count) - @Test - fun `toJsonObject correctly converts a TimingDistributionData object`() { - // Define a TimingDistributionData object - val tdd = TimingDistributionData(category = "telemetry", name = "test_timing_distribution") - - // Accumulate some samples to populate sum and values properties - tdd.accumulate(1L) - tdd.accumulate(2L) - tdd.accumulate(3L) - - // Convert to JSON object using toJsonObject() - val jsonTdd = tdd.toJsonObject() - - // Verify properties - assertEquals("JSON category must match Timing Distribution category", - "telemetry", jsonTdd.getString("category")) - assertEquals("JSON name must match Timing Distribution name", - "test_timing_distribution", jsonTdd.getString("name")) - assertEquals("JSON bucket count must match Timing Distribution bucket count", - tdd.bucketCount, jsonTdd.getInt("bucket_count")) - assertEquals("JSON name must match Timing Distribution name", - "test_timing_distribution", jsonTdd.getString("name")) - val jsonRange = jsonTdd.getJSONArray("range") - assertEquals("JSON range minimum must match Timing Distribution range minimum", - tdd.rangeMin, jsonRange.getLong(0)) - assertEquals("JSON range maximum must match Timing Distribution range maximum", - tdd.rangeMax, jsonRange.getLong(1)) - assertEquals("JSON histogram type must match Timing Distribution histogram type", - tdd.histogramType.toString().toLowerCase(), jsonTdd.getString("histogram_type")) - val jsonValue = jsonTdd.getJSONObject("values") - assertEquals("JSON values must match Timing Distribution values", - tdd.values[1], jsonValue.getLong("1")) - assertEquals("JSON values must match Timing Distribution values", - tdd.values[2], jsonValue.getLong("2")) - assertEquals("JSON values must match Timing Distribution values", - tdd.values[3], jsonValue.getLong("3")) - assertEquals("JSON sum must match Timing Distribution sum", - tdd.sum, jsonTdd.getLong("sum")) - assertEquals("JSON time unit must match Timing Distribution time unit", - tdd.timeUnit.toString().toLowerCase(), jsonTdd.getString("time_unit")) + for (i in samples) { + val binEdge = hist.sampleToBucketMinimum(i) + assertEquals("Accumulating should increment correct bucket", 1L, snapshot.values[binEdge]) + } + + val json = snapshot.toJsonPayloadObject() + val values = json.getJSONObject("values") + assertEquals(81, values.length()) + + for (i in samples) { + val binEdge = hist.sampleToBucketMinimum(i) + assertEquals("Accumulating should increment correct bucket", 1L, values.getLong(binEdge.toString())) + values.remove(binEdge.toString()) + } + + for (k in values.keys()) { + assertEquals(0L, values.getLong(k)) + } } } diff --git a/components/support/ktx/src/main/res/values-cs/strings.xml b/components/support/ktx/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000000..65840d822ca --- /dev/null +++ b/components/support/ktx/src/main/res/values-cs/strings.xml @@ -0,0 +1,5 @@ + + + Sdílet pomocí… + Sdílet pomocí + diff --git a/components/support/ktx/src/main/res/values-es-rAR/strings.xml b/components/support/ktx/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 00000000000..0ff0ff169b2 --- /dev/null +++ b/components/support/ktx/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,5 @@ + + + Compartir con… + Compartir vía + diff --git a/components/support/ktx/src/main/res/values-fi/strings.xml b/components/support/ktx/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000000..df6f127604c --- /dev/null +++ b/components/support/ktx/src/main/res/values-fi/strings.xml @@ -0,0 +1,5 @@ + + + Jaa… + Jaa + diff --git a/components/support/ktx/src/main/res/values-pa-rIN/strings.xml b/components/support/ktx/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 00000000000..fe441b18187 --- /dev/null +++ b/components/support/ktx/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,5 @@ + + + …ਨਾਲ ਸਾਂਝਾ ਕਰੋ + ਇਸ ਰਾਹੀਂ ਸਾਂਝਾ ਕਰੋ + diff --git a/components/ui/icons/src/main/res/drawable/mozac_ic_lock.xml b/components/ui/icons/src/main/res/drawable/mozac_ic_lock.xml index 2d77e7b3391..77d7c6b01a1 100644 --- a/components/ui/icons/src/main/res/drawable/mozac_ic_lock.xml +++ b/components/ui/icons/src/main/res/drawable/mozac_ic_lock.xml @@ -9,5 +9,5 @@ android:viewportHeight="24.0"> + android:pathData="M17 11V8A5 5 0 0 0 7 8v3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6a2 2 0 0 0-2-2zM9 8a3 3 0 0 1 3-3 3 3 0 0 1 3 3v3H9z"/> diff --git a/docs/api/alltypes/index.md b/docs/api/alltypes/index.md index 2af7c22d39c..4e9c644019e 100644 --- a/docs/api/alltypes/index.md +++ b/docs/api/alltypes/index.md @@ -4,6 +4,9 @@ | Name | Summary | |---|---| +| [mozilla.components.browser.engine.gecko.prompt.AC_AUTH_LEVEL](../mozilla.components.browser.engine.gecko.prompt/-a-c_-a-u-t-h_-l-e-v-e-l.md) | | +| [mozilla.components.browser.engine.gecko.prompt.AC_AUTH_METHOD](../mozilla.components.browser.engine.gecko.prompt/-a-c_-a-u-t-h_-m-e-t-h-o-d.md) | | +| [mozilla.components.browser.engine.gecko.prompt.AC_FILE_FACING_MODE](../mozilla.components.browser.engine.gecko.prompt/-a-c_-f-i-l-e_-f-a-c-i-n-g_-m-o-d-e.md) | | | [mozilla.components.lib.push.amazon.AbstractAmazonPushService](../mozilla.components.lib.push.amazon/-abstract-amazon-push-service/index.md) | An Amazon Cloud Messaging implementation of the [PushService](../mozilla.components.concept.push/-push-service/index.md) for Android devices that support Google Play Services. [ADMMessageHandlerBase](#) requires a redundant constructor parameter. | | [mozilla.components.feature.customtabs.AbstractCustomTabsService](../mozilla.components.feature.customtabs/-abstract-custom-tabs-service/index.md) | [Service](#) providing Custom Tabs related functionality. | | [mozilla.components.feature.downloads.AbstractFetchDownloadService](../mozilla.components.feature.downloads/-abstract-fetch-download-service/index.md) | Service that performs downloads through a fetch [Client](../mozilla.components.concept.fetch/-client/index.md) rather than through the native Android download manager. | @@ -114,6 +117,8 @@ | [org.mozilla.telemetry.measurement.CreatedDateMeasurementNew](../org.mozilla.telemetry.measurement/-created-date-measurement-new/index.md) | The field 'created' from CreatedDateMeasurement will be deprecated for the `createdDate` field | | [org.mozilla.telemetry.measurement.CreatedTimestampMeasurement](../org.mozilla.telemetry.measurement/-created-timestamp-measurement/index.md) | | | [org.mozilla.telemetry.measurement.CreatedTimestampMeasurementNew](../org.mozilla.telemetry.measurement/-created-timestamp-measurement-new/index.md) | The field 'created' from CreatedTimestampMeasurement will be deprecated for the `createdTimestamp` field | +| [mozilla.components.service.glean.storages.CustomDistributionData](../mozilla.components.service.glean.storages/-custom-distribution-data/index.md) | This class represents the structure of a custom distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, as well as including a helper function to calculate the bucket sizes. | +| [mozilla.components.service.glean.private.CustomDistributionMetricType](../mozilla.components.service.glean.private/-custom-distribution-metric-type/index.md) | This implements the developer facing API for recording custom distribution metrics. | | [mozilla.components.browser.domains.CustomDomains](../mozilla.components.browser.domains/-custom-domains/index.md) | Contains functionality to manage custom domains for auto-completion. | | [mozilla.components.browser.domains.autocomplete.CustomDomainsProvider](../mozilla.components.browser.domains.autocomplete/-custom-domains-provider/index.md) | Provides autocomplete functionality for domains based on a list managed by [CustomDomains](../mozilla.components.browser.domains/-custom-domains/index.md). | | [mozilla.components.browser.session.tab.CustomTabActionButtonConfig](../mozilla.components.browser.session.tab/-custom-tab-action-button-config/index.md) | | @@ -181,9 +186,9 @@ | [mozilla.components.service.fretboard.ExperimentPayload](../mozilla.components.service.fretboard/-experiment-payload/index.md) | Class which represents an experiment associated data | | [mozilla.components.service.fretboard.ExperimentSource](../mozilla.components.service.fretboard/-experiment-source/index.md) | Represents a location where experiments are stored (Kinto, a JSON file on a server, etc) | | [mozilla.components.service.fretboard.ExperimentStorage](../mozilla.components.service.fretboard/-experiment-storage/index.md) | Represents a location where experiments are stored locally on the device | -| [mozilla.components.service.experiments.Experiments](../mozilla.components.service.experiments/-experiments.md) | | -| [mozilla.components.service.experiments.debug.ExperimentsDebugActivity](../mozilla.components.service.experiments.debug/-experiments-debug-activity/index.md) | | -| [mozilla.components.service.experiments.ExperimentsInternalAPI](../mozilla.components.service.experiments/-experiments-internal-a-p-i/index.md) | Entry point of the library. | +| [mozilla.components.service.experiments.Experiments](../mozilla.components.service.experiments/-experiments.md) | The main Experiments object. | +| [mozilla.components.service.experiments.debug.ExperimentsDebugActivity](../mozilla.components.service.experiments.debug/-experiments-debug-activity/index.md) | Debugging activity exported by service-experiments to allow easier debugging. This accepts commands that can force the library to do the following: | +| [mozilla.components.service.experiments.ExperimentsInternalAPI](../mozilla.components.service.experiments/-experiments-internal-a-p-i/index.md) | This is the main experiments API, which is exposed through the global [Experiments](../mozilla.components.service.experiments/-experiments.md) object. | | [org.mozilla.telemetry.measurement.ExperimentsMapMeasurement](../org.mozilla.telemetry.measurement/-experiments-map-measurement/index.md) | | | [org.mozilla.telemetry.measurement.ExperimentsMeasurement](../org.mozilla.telemetry.measurement/-experiments-measurement/index.md) | | | [mozilla.components.service.fretboard.ExperimentsSnapshot](../mozilla.components.service.fretboard/-experiments-snapshot/index.md) | Represents an experiment sync result | @@ -213,6 +218,13 @@ | [mozilla.components.service.fxa.FxaPanicException](../mozilla.components.service.fxa/-fxa-panic-exception.md) | Thrown when the Rust library hits an assertion or panic (this is always a bug). | | [mozilla.components.service.fxa.FxaUnauthorizedException](../mozilla.components.service.fxa/-fxa-unauthorized-exception.md) | Thrown when the operation requires additional authorization. | | [mozilla.components.service.fxa.FxaUnspecifiedException](../mozilla.components.service.fxa/-fxa-unspecified-exception.md) | Thrown when the Rust library hits an unexpected error that isn't a panic. This may indicate library misuse, network errors, etc. | +| [mozilla.components.browser.engine.gecko.prompt.GECKO_AUTH_FLAGS](../mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-a-u-t-h_-f-l-a-g-s.md) | | +| [mozilla.components.browser.engine.gecko.prompt.GECKO_AUTH_LEVEL](../mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-a-u-t-h_-l-e-v-e-l.md) | | +| [mozilla.components.browser.engine.gecko.prompt.GECKO_PROMPT_CHOICE_TYPE](../mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-c-h-o-i-c-e_-t-y-p-e.md) | | +| [mozilla.components.browser.engine.gecko.prompt.GECKO_PROMPT_FILE_CAPTURE](../mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-c-a-p-t-u-r-e.md) | | +| [mozilla.components.browser.engine.gecko.prompt.GECKO_PROMPT_FILE_TYPE](../mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-t-y-p-e.md) | | +| [mozilla.components.browser.engine.gecko.glean.GeckoAdapter](../mozilla.components.browser.engine.gecko.glean/-gecko-adapter/index.md) | This implements a [RuntimeTelemetry.Delegate](#) that dispatches Gecko runtime telemetry to the Glean SDK. | +| [mozilla.components.browser.engine.gecko.prompt.GeckoAuthOptions](../mozilla.components.browser.engine.gecko.prompt/-gecko-auth-options.md) | | | [mozilla.components.browser.engine.gecko.prompt.GeckoChoice](../mozilla.components.browser.engine.gecko.prompt/-gecko-choice.md) | | | [mozilla.components.lib.crash.service.GeckoCrashReporter](../mozilla.components.lib.crash.service/-gecko-crash-reporter.md) | | | [mozilla.components.browser.engine.gecko.GeckoEngine](../mozilla.components.browser.engine.gecko/-gecko-engine/index.md) | Gecko-based implementation of Engine interface. | @@ -443,6 +455,7 @@ | [org.mozilla.telemetry.measurement.SearchesMeasurement](../org.mozilla.telemetry.measurement/-searches-measurement/index.md) | A TelemetryMeasurement implementation to count the number of times a user has searched with a specific engine from a specific location. | | [mozilla.components.browser.state.state.SecurityInfoState](../mozilla.components.browser.state.state/-security-info-state/index.md) | A value type holding security information for a Session. | | [mozilla.components.browser.session.SelectionAwareSessionObserver](../mozilla.components.browser.session/-selection-aware-session-observer/index.md) | This class is a combination of [Session.Observer](../mozilla.components.browser.session/-session/-observer/index.md) and [SessionManager.Observer](../mozilla.components.browser.session/-session-manager/-observer/index.md). It provides functionality to observe changes to a specified or selected session, and can automatically take care of switching over the observer in case a different session gets selected (see [observeFixed](../mozilla.components.browser.session/-selection-aware-session-observer/observe-fixed.md) and [observeSelected](../mozilla.components.browser.session/-selection-aware-session-observer/observe-selected.md)). | +| [mozilla.components.feature.sendtab.SendTabFeature](../mozilla.components.feature.sendtab/-send-tab-feature/index.md) | A feature that uses the [FxaAccountManager](../mozilla.components.service.fxa.manager/-fxa-account-manager/index.md) to send and receive tabs with optional push support for receiving tabs from the [AutoPushFeature](../mozilla.components.feature.push/-auto-push-feature/index.md) and a [PushService](../mozilla.components.concept.push/-push-service/index.md). | | [mozilla.components.feature.sendtab.SendTabUseCases](../mozilla.components.feature.sendtab/-send-tab-use-cases/index.md) | Contains use cases for sending tabs to devices related to the firefox-accounts. | | [mozilla.components.lib.crash.service.SentryService](../mozilla.components.lib.crash.service/-sentry-service/index.md) | A [CrashReporterService](../mozilla.components.lib.crash.service/-crash-reporter-service/index.md) implementation that uploads crash reports to a Sentry server. | | [org.mozilla.telemetry.measurement.SequenceMeasurement](../org.mozilla.telemetry.measurement/-sequence-measurement/index.md) | | @@ -568,7 +581,7 @@ | [mozilla.components.service.glean.private.TimeUnit](../mozilla.components.service.glean.private/-time-unit/index.md) | Enumeration of different resolutions supported by the Timespan and TimingDistribution metric types. | | [mozilla.components.service.glean.private.TimespanMetricType](../mozilla.components.service.glean.private/-timespan-metric-type/index.md) | This implements the developer facing API for recording timespans. | | [org.mozilla.telemetry.measurement.TimezoneOffsetMeasurement](../org.mozilla.telemetry.measurement/-timezone-offset-measurement/index.md) | | -| [mozilla.components.service.glean.storages.TimingDistributionData](../mozilla.components.service.glean.storages/-timing-distribution-data/index.md) | This class represents the structure of a timing distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, as well as including a helper function to calculate the bucket sizes. | +| [mozilla.components.service.glean.storages.TimingDistributionData](../mozilla.components.service.glean.storages/-timing-distribution-data/index.md) | This class represents the structure of a timing distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, as well as performing the calculations to determine the correct bucket for each sample. | | [mozilla.components.service.glean.private.TimingDistributionMetricType](../mozilla.components.service.glean.private/-timing-distribution-metric-type/index.md) | This implements the developer facing API for recording timing distribution metrics. | | [mozilla.components.browser.icons.preparer.TippyTopIconPreparer](../mozilla.components.browser.icons.preparer/-tippy-top-icon-preparer/index.md) | [IconPreprarer](../mozilla.components.browser.icons.preparer/-icon-preprarer/index.md) implementation that looks up the host in our "tippy top" list. If it can find a match then it inserts the icon URL into the request. | | [mozilla.components.lib.jexl.lexer.Token](../mozilla.components.lib.jexl.lexer/-token/index.md) | A token emitted by the [Lexer](#). | @@ -604,7 +617,7 @@ | [mozilla.components.feature.pwa.WebAppUseCases](../mozilla.components.feature.pwa/-web-app-use-cases/index.md) | These use cases allow for adding a web app or web site to the homescreen. | | [mozilla.components.concept.engine.webextension.WebExtension](../mozilla.components.concept.engine.webextension/-web-extension/index.md) | Represents a browser extension based on the WebExtension API: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions | | [mozilla.components.support.utils.WebURLFinder](../mozilla.components.support.utils/-web-u-r-l-finder/index.md) | Regular expressions used in this class are taken from Android's Patterns.java. We brought them in to standardize URL matching across Android versions, instead of relying on Android version-dependent built-ins that can vary across Android versions. The original code can be found here: http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/util/Patterns.java | -| [mozilla.components.support.test.rules.WebserverRule](../mozilla.components.support.test.rules/-webserver-rule/index.md) | A [TestWatcher](#) junit rule that will serve content from assets in the test package. | +| [mozilla.components.support.android.test.rules.WebserverRule](../mozilla.components.support.android.test.rules/-webserver-rule/index.md) | A [TestWatcher](#) junit rule that will serve content from assets in the test package. | | [mozilla.components.feature.session.WindowFeature](../mozilla.components.feature.session/-window-feature/index.md) | Feature implementation for handling window requests. | | [mozilla.components.concept.engine.window.WindowRequest](../mozilla.components.concept.engine.window/-window-request/index.md) | Represents a request to open or close a browser window. | | [mozilla.components.service.fxa.sync.WorkManagerSyncDispatcher](../mozilla.components.service.fxa.sync/-work-manager-sync-dispatcher/index.md) | | diff --git a/docs/api/index.md b/docs/api/index.md index 85bb60f5a05..4a9223ff65f 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -12,6 +12,7 @@ | [mozilla.components.browser.domains.autocomplete](mozilla.components.browser.domains.autocomplete/index.md) | | | [mozilla.components.browser.engine.gecko](mozilla.components.browser.engine.gecko/index.md) | | | [mozilla.components.browser.engine.gecko.fetch](mozilla.components.browser.engine.gecko.fetch/index.md) | | +| [mozilla.components.browser.engine.gecko.glean](mozilla.components.browser.engine.gecko.glean/index.md) | | | [mozilla.components.browser.engine.gecko.integration](mozilla.components.browser.engine.gecko.integration/index.md) | | | [mozilla.components.browser.engine.gecko.permission](mozilla.components.browser.engine.gecko.permission/index.md) | | | [mozilla.components.browser.engine.gecko.prompt](mozilla.components.browser.engine.gecko.prompt/index.md) | | @@ -160,6 +161,7 @@ | [mozilla.components.support.android.test.espresso](mozilla.components.support.android.test.espresso/index.md) | | | [mozilla.components.support.android.test.espresso.matcher](mozilla.components.support.android.test.espresso.matcher/index.md) | | | [mozilla.components.support.android.test.leaks](mozilla.components.support.android.test.leaks/index.md) | | +| [mozilla.components.support.android.test.rules](mozilla.components.support.android.test.rules/index.md) | | | [mozilla.components.support.base.android](mozilla.components.support.base.android/index.md) | | | [mozilla.components.support.base.android.view](mozilla.components.support.base.android.view/index.md) | | | [mozilla.components.support.base.facts](mozilla.components.support.base.facts/index.md) | | @@ -188,7 +190,6 @@ | [mozilla.components.support.test.ext](mozilla.components.support.test.ext/index.md) | | | [mozilla.components.support.test.robolectric](mozilla.components.support.test.robolectric/index.md) | | | [mozilla.components.support.test.robolectric.shadow](mozilla.components.support.test.robolectric.shadow/index.md) | | -| [mozilla.components.support.test.rules](mozilla.components.support.test.rules/index.md) | | | [mozilla.components.support.utils](mozilla.components.support.utils/index.md) | | | [mozilla.components.tooling.fetch.tests](mozilla.components.tooling.fetch.tests/index.md) | | | [mozilla.components.tooling.lint](mozilla.components.tooling.lint/index.md) | | diff --git a/docs/api/mozilla.components.browser.engine.gecko.glean/-gecko-adapter/-init-.md b/docs/api/mozilla.components.browser.engine.gecko.glean/-gecko-adapter/-init-.md new file mode 100644 index 00000000000..d76aa8b396e --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.glean/-gecko-adapter/-init-.md @@ -0,0 +1,16 @@ +[android-components](../../index.md) / [mozilla.components.browser.engine.gecko.glean](../index.md) / [GeckoAdapter](index.md) / [<init>](./-init-.md) + +# <init> + +`GeckoAdapter()` + +This implements a [RuntimeTelemetry.Delegate](#) that dispatches Gecko runtime +telemetry to the Glean SDK. + +Metrics defined in the `metrics.yaml` file in Gecko's mozilla-central repository +will be automatically dispatched to the Glean SDK and sent through the requested +pings. + +This can be used, in products collecting data through the Glean SDK, by +providing an instance to `GeckoRuntimeSettings.Builder().telemetryDelegate`. + diff --git a/docs/api/mozilla.components.browser.engine.gecko.glean/-gecko-adapter/index.md b/docs/api/mozilla.components.browser.engine.gecko.glean/-gecko-adapter/index.md new file mode 100644 index 00000000000..90fb29bd11e --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.glean/-gecko-adapter/index.md @@ -0,0 +1,27 @@ +[android-components](../../index.md) / [mozilla.components.browser.engine.gecko.glean](../index.md) / [GeckoAdapter](./index.md) + +# GeckoAdapter + +`class GeckoAdapter` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/glean/GeckoAdapter.kt#L21) + +This implements a [RuntimeTelemetry.Delegate](#) that dispatches Gecko runtime +telemetry to the Glean SDK. + +Metrics defined in the `metrics.yaml` file in Gecko's mozilla-central repository +will be automatically dispatched to the Glean SDK and sent through the requested +pings. + +This can be used, in products collecting data through the Glean SDK, by +providing an instance to `GeckoRuntimeSettings.Builder().telemetryDelegate`. + +### Constructors + +| Name | Summary | +|---|---| +| [<init>](-init-.md) | `GeckoAdapter()`
    This implements a [RuntimeTelemetry.Delegate](#) that dispatches Gecko runtime telemetry to the Glean SDK. | + +### Functions + +| Name | Summary | +|---|---| +| [onTelemetryReceived](on-telemetry-received.md) | `fun onTelemetryReceived(metric: ): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) | diff --git a/docs/api/mozilla.components.browser.engine.gecko.glean/-gecko-adapter/on-telemetry-received.md b/docs/api/mozilla.components.browser.engine.gecko.glean/-gecko-adapter/on-telemetry-received.md new file mode 100644 index 00000000000..0ecaa8a6dbf --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.glean/-gecko-adapter/on-telemetry-received.md @@ -0,0 +1,5 @@ +[android-components](../../index.md) / [mozilla.components.browser.engine.gecko.glean](../index.md) / [GeckoAdapter](index.md) / [onTelemetryReceived](./on-telemetry-received.md) + +# onTelemetryReceived + +`fun onTelemetryReceived(metric: ): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/glean/GeckoAdapter.kt#L22) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.gecko.glean/index.md b/docs/api/mozilla.components.browser.engine.gecko.glean/index.md new file mode 100644 index 00000000000..dfd52e3b2a9 --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.glean/index.md @@ -0,0 +1,9 @@ +[android-components](../index.md) / [mozilla.components.browser.engine.gecko.glean](./index.md) + +## Package mozilla.components.browser.engine.gecko.glean + +### Types + +| Name | Summary | +|---|---| +| [GeckoAdapter](-gecko-adapter/index.md) | `class GeckoAdapter`
    This implements a [RuntimeTelemetry.Delegate](#) that dispatches Gecko runtime telemetry to the Glean SDK. | diff --git a/docs/api/mozilla.components.browser.engine.gecko.prompt/-a-c_-a-u-t-h_-l-e-v-e-l.md b/docs/api/mozilla.components.browser.engine.gecko.prompt/-a-c_-a-u-t-h_-l-e-v-e-l.md new file mode 100644 index 00000000000..eb8322aaffd --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.prompt/-a-c_-a-u-t-h_-l-e-v-e-l.md @@ -0,0 +1,5 @@ +[android-components](../index.md) / [mozilla.components.browser.engine.gecko.prompt](index.md) / [AC_AUTH_LEVEL](./-a-c_-a-u-t-h_-l-e-v-e-l.md) + +# AC_AUTH_LEVEL + +`typealias AC_AUTH_LEVEL = `[`Level`](../mozilla.components.concept.engine.prompt/-prompt-request/-authentication/-level/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt#L44) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.gecko.prompt/-a-c_-a-u-t-h_-m-e-t-h-o-d.md b/docs/api/mozilla.components.browser.engine.gecko.prompt/-a-c_-a-u-t-h_-m-e-t-h-o-d.md new file mode 100644 index 00000000000..63076529e97 --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.prompt/-a-c_-a-u-t-h_-m-e-t-h-o-d.md @@ -0,0 +1,5 @@ +[android-components](../index.md) / [mozilla.components.browser.engine.gecko.prompt](index.md) / [AC_AUTH_METHOD](./-a-c_-a-u-t-h_-m-e-t-h-o-d.md) + +# AC_AUTH_METHOD + +`typealias AC_AUTH_METHOD = `[`Method`](../mozilla.components.concept.engine.prompt/-prompt-request/-authentication/-method/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt#L45) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.gecko.prompt/-a-c_-f-i-l-e_-f-a-c-i-n-g_-m-o-d-e.md b/docs/api/mozilla.components.browser.engine.gecko.prompt/-a-c_-f-i-l-e_-f-a-c-i-n-g_-m-o-d-e.md new file mode 100644 index 00000000000..5f6e2ca0d24 --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.prompt/-a-c_-f-i-l-e_-f-a-c-i-n-g_-m-o-d-e.md @@ -0,0 +1,5 @@ +[android-components](../index.md) / [mozilla.components.browser.engine.gecko.prompt](index.md) / [AC_FILE_FACING_MODE](./-a-c_-f-i-l-e_-f-a-c-i-n-g_-m-o-d-e.md) + +# AC_FILE_FACING_MODE + +`typealias AC_FILE_FACING_MODE = `[`FacingMode`](../mozilla.components.concept.engine.prompt/-prompt-request/-file/-facing-mode/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt#L46) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-a-u-t-h_-f-l-a-g-s.md b/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-a-u-t-h_-f-l-a-g-s.md new file mode 100644 index 00000000000..8b0cd80e19d --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-a-u-t-h_-f-l-a-g-s.md @@ -0,0 +1,5 @@ +[android-components](../index.md) / [mozilla.components.browser.engine.gecko.prompt](index.md) / [GECKO_AUTH_FLAGS](./-g-e-c-k-o_-a-u-t-h_-f-l-a-g-s.md) + +# GECKO_AUTH_FLAGS + +`typealias GECKO_AUTH_FLAGS = ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt#L39) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-a-u-t-h_-l-e-v-e-l.md b/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-a-u-t-h_-l-e-v-e-l.md new file mode 100644 index 00000000000..2324f064db8 --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-a-u-t-h_-l-e-v-e-l.md @@ -0,0 +1,5 @@ +[android-components](../index.md) / [mozilla.components.browser.engine.gecko.prompt](index.md) / [GECKO_AUTH_LEVEL](./-g-e-c-k-o_-a-u-t-h_-l-e-v-e-l.md) + +# GECKO_AUTH_LEVEL + +`typealias GECKO_AUTH_LEVEL = ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt#L40) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-c-h-o-i-c-e_-t-y-p-e.md b/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-c-h-o-i-c-e_-t-y-p-e.md new file mode 100644 index 00000000000..5d9bcb49689 --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-c-h-o-i-c-e_-t-y-p-e.md @@ -0,0 +1,5 @@ +[android-components](../index.md) / [mozilla.components.browser.engine.gecko.prompt](index.md) / [GECKO_PROMPT_CHOICE_TYPE](./-g-e-c-k-o_-p-r-o-m-p-t_-c-h-o-i-c-e_-t-y-p-e.md) + +# GECKO_PROMPT_CHOICE_TYPE + +`typealias GECKO_PROMPT_CHOICE_TYPE = ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt#L42) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-c-a-p-t-u-r-e.md b/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-c-a-p-t-u-r-e.md new file mode 100644 index 00000000000..5461073549f --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-c-a-p-t-u-r-e.md @@ -0,0 +1,5 @@ +[android-components](../index.md) / [mozilla.components.browser.engine.gecko.prompt](index.md) / [GECKO_PROMPT_FILE_CAPTURE](./-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-c-a-p-t-u-r-e.md) + +# GECKO_PROMPT_FILE_CAPTURE + +`typealias GECKO_PROMPT_FILE_CAPTURE = ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt#L43) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-t-y-p-e.md b/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-t-y-p-e.md new file mode 100644 index 00000000000..0f5dba58ad7 --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.prompt/-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-t-y-p-e.md @@ -0,0 +1,5 @@ +[android-components](../index.md) / [mozilla.components.browser.engine.gecko.prompt](index.md) / [GECKO_PROMPT_FILE_TYPE](./-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-t-y-p-e.md) + +# GECKO_PROMPT_FILE_TYPE + +`typealias GECKO_PROMPT_FILE_TYPE = ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt#L41) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.gecko.prompt/-gecko-auth-options.md b/docs/api/mozilla.components.browser.engine.gecko.prompt/-gecko-auth-options.md new file mode 100644 index 00000000000..dd6061dbb9c --- /dev/null +++ b/docs/api/mozilla.components.browser.engine.gecko.prompt/-gecko-auth-options.md @@ -0,0 +1,5 @@ +[android-components](../index.md) / [mozilla.components.browser.engine.gecko.prompt](index.md) / [GeckoAuthOptions](./-gecko-auth-options.md) + +# GeckoAuthOptions + +`typealias GeckoAuthOptions = ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt#L37) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.gecko.prompt/index.md b/docs/api/mozilla.components.browser.engine.gecko.prompt/index.md index 69e24dc42e9..ea3b543b674 100644 --- a/docs/api/mozilla.components.browser.engine.gecko.prompt/index.md +++ b/docs/api/mozilla.components.browser.engine.gecko.prompt/index.md @@ -6,4 +6,13 @@ | Name | Summary | |---|---| +| [AC_AUTH_LEVEL](-a-c_-a-u-t-h_-l-e-v-e-l.md) | `typealias AC_AUTH_LEVEL = `[`Level`](../mozilla.components.concept.engine.prompt/-prompt-request/-authentication/-level/index.md) | +| [AC_AUTH_METHOD](-a-c_-a-u-t-h_-m-e-t-h-o-d.md) | `typealias AC_AUTH_METHOD = `[`Method`](../mozilla.components.concept.engine.prompt/-prompt-request/-authentication/-method/index.md) | +| [AC_FILE_FACING_MODE](-a-c_-f-i-l-e_-f-a-c-i-n-g_-m-o-d-e.md) | `typealias AC_FILE_FACING_MODE = `[`FacingMode`](../mozilla.components.concept.engine.prompt/-prompt-request/-file/-facing-mode/index.md) | +| [GECKO_AUTH_FLAGS](-g-e-c-k-o_-a-u-t-h_-f-l-a-g-s.md) | `typealias GECKO_AUTH_FLAGS = ` | +| [GECKO_AUTH_LEVEL](-g-e-c-k-o_-a-u-t-h_-l-e-v-e-l.md) | `typealias GECKO_AUTH_LEVEL = ` | +| [GECKO_PROMPT_CHOICE_TYPE](-g-e-c-k-o_-p-r-o-m-p-t_-c-h-o-i-c-e_-t-y-p-e.md) | `typealias GECKO_PROMPT_CHOICE_TYPE = ` | +| [GECKO_PROMPT_FILE_CAPTURE](-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-c-a-p-t-u-r-e.md) | `typealias GECKO_PROMPT_FILE_CAPTURE = ` | +| [GECKO_PROMPT_FILE_TYPE](-g-e-c-k-o_-p-r-o-m-p-t_-f-i-l-e_-t-y-p-e.md) | `typealias GECKO_PROMPT_FILE_TYPE = ` | +| [GeckoAuthOptions](-gecko-auth-options.md) | `typealias GeckoAuthOptions = ` | | [GeckoChoice](-gecko-choice.md) | `typealias GeckoChoice = `[`Choice`](https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession/PromptDelegate/Choice.html) | diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/handle-message.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/handle-message.md index 410342a7f89..5a8206f2fe2 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/handle-message.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/handle-message.md @@ -2,4 +2,4 @@ # handleMessage -`fun handleMessage(msg: ): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L658) \ No newline at end of file +`fun handleMessage(msg: ): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L630) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/index.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/index.md index cc5dcca8a60..f4693605b24 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/index.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/index.md @@ -2,7 +2,7 @@ # ImageHandler -`class ImageHandler` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L657) +`class ImageHandler` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L629) ### Constructors diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/session.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/session.md index da610916321..719e3bdeffd 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/session.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/-image-handler/session.md @@ -2,4 +2,4 @@ # session -`val session: `[`SystemEngineSession`](../../-system-engine-session/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L657) \ No newline at end of file +`val session: `[`SystemEngineSession`](../../-system-engine-session/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L629) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/can-scroll-vertically-down.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/can-scroll-vertically-down.md index 2a9471625ce..55584ede021 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/can-scroll-vertically-down.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/can-scroll-vertically-down.md @@ -2,7 +2,7 @@ # canScrollVerticallyDown -`fun canScrollVerticallyDown(): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L676) +`fun canScrollVerticallyDown(): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L648) Overrides [EngineView.canScrollVerticallyDown](../../mozilla.components.concept.engine/-engine-view/can-scroll-vertically-down.md) diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/can-scroll-vertically-up.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/can-scroll-vertically-up.md index e51ca468ab9..b3bf14adc9c 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/can-scroll-vertically-up.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/can-scroll-vertically-up.md @@ -2,7 +2,7 @@ # canScrollVerticallyUp -`fun canScrollVerticallyUp(): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L674) +`fun canScrollVerticallyUp(): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L646) Overrides [EngineView.canScrollVerticallyUp](../../mozilla.components.concept.engine/-engine-view/can-scroll-vertically-up.md) diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/capture-thumbnail.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/capture-thumbnail.md index 75a6ebf6173..f79c44cf085 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/capture-thumbnail.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/capture-thumbnail.md @@ -2,4 +2,4 @@ # captureThumbnail -`fun captureThumbnail(onFinish: (?) -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L678) \ No newline at end of file +`fun captureThumbnail(onFinish: (?) -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L650) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/index.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/index.md index 3f48868b12d..685d66d433b 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/index.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/index.md @@ -2,7 +2,7 @@ # SystemEngineView -`class SystemEngineView : `[`EngineView`](../../mozilla.components.concept.engine/-engine-view/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L67) +`class SystemEngineView : `[`EngineView`](../../mozilla.components.concept.engine/-engine-view/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L66) WebView-based implementation of EngineView. diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-destroy.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-destroy.md index 8ed8277835e..c0b4c222d89 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-destroy.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-destroy.md @@ -2,7 +2,7 @@ # onDestroy -`fun onDestroy(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L114) +`fun onDestroy(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L110) Overrides [EngineView.onDestroy](../../mozilla.components.concept.engine/-engine-view/on-destroy.md) diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-long-click.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-long-click.md index 48fac2363a1..81e62fb377b 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-long-click.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-long-click.md @@ -2,4 +2,4 @@ # onLongClick -`fun onLongClick(view: ?): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L95) \ No newline at end of file +`fun onLongClick(view: ?): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L91) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-pause.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-pause.md index 80433dc5a70..bab6ef10978 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-pause.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-pause.md @@ -2,7 +2,7 @@ # onPause -`fun onPause(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L100) +`fun onPause(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L96) Overrides [EngineView.onPause](../../mozilla.components.concept.engine/-engine-view/on-pause.md) diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-resume.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-resume.md index ddd6b737913..12f04b15fce 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-resume.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/on-resume.md @@ -2,7 +2,7 @@ # onResume -`fun onResume(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L107) +`fun onResume(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L103) Overrides [EngineView.onResume](../../mozilla.components.concept.engine/-engine-view/on-resume.md) diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/release.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/release.md index 64fc9b8a771..16f89cd6be3 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/release.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/release.md @@ -2,7 +2,7 @@ # release -`fun release(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L89) +`fun release(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L85) Overrides [EngineView.release](../../mozilla.components.concept.engine/-engine-view/release.md) diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/render.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/render.md index 5c9a6e50466..b1fb454a576 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/render.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/render.md @@ -2,7 +2,7 @@ # render -`fun render(session: `[`EngineSession`](../../mozilla.components.concept.engine/-engine-session/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L81) +`fun render(session: `[`EngineSession`](../../mozilla.components.concept.engine/-engine-session/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L77) Overrides [EngineView.render](../../mozilla.components.concept.engine/-engine-view/render.md) diff --git a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/set-vertical-clipping.md b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/set-vertical-clipping.md index 98abf4e94bd..bf79127d125 100644 --- a/docs/api/mozilla.components.browser.engine.system/-system-engine-view/set-vertical-clipping.md +++ b/docs/api/mozilla.components.browser.engine.system/-system-engine-view/set-vertical-clipping.md @@ -2,7 +2,7 @@ # setVerticalClipping -`fun setVerticalClipping(clippingHeight: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L670) +`fun setVerticalClipping(clippingHeight: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/engine-system/src/main/java/mozilla/components/browser/engine/system/SystemEngineView.kt#L642) Overrides [EngineView.setVerticalClipping](../../mozilla.components.concept.engine/-engine-view/set-vertical-clipping.md) diff --git a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-fetch-exception/index.md b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-fetch-exception/index.md index 48ab5050f78..0a338bc8cb8 100644 --- a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-fetch-exception/index.md +++ b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-fetch-exception/index.md @@ -2,7 +2,7 @@ # FetchException -`class FetchException : `[`Exception`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-exception/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L27) +`class FetchException : `[`Exception`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-exception/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L51) Exception types for errors caught while getting a list of suggestions diff --git a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-init-.md b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-init-.md index decae589345..68d9dd8b0cf 100644 --- a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-init-.md +++ b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-init-.md @@ -3,6 +3,4 @@ # <init> `SearchSuggestionClient(searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`, fetcher: `[`SearchSuggestionFetcher`](../-search-suggestion-fetcher.md)`)` - -Provides an interface to get search suggestions from a given SearchEngine. - +`SearchSuggestionClient(context: , searchEngineManager: `[`SearchEngineManager`](../../mozilla.components.browser.search/-search-engine-manager/index.md)`, fetcher: `[`SearchSuggestionFetcher`](../-search-suggestion-fetcher.md)`)` \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-response-parser-exception/index.md b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-response-parser-exception/index.md index b41ffecb227..356dafef0cb 100644 --- a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-response-parser-exception/index.md +++ b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/-response-parser-exception/index.md @@ -2,7 +2,7 @@ # ResponseParserException -`class ResponseParserException : `[`Exception`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-exception/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L28) +`class ResponseParserException : `[`Exception`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-exception/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L52) ### Constructors diff --git a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/get-suggestions.md b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/get-suggestions.md index ec2f788dd0c..746091c66e4 100644 --- a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/get-suggestions.md +++ b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/get-suggestions.md @@ -2,7 +2,7 @@ # getSuggestions -`suspend fun getSuggestions(query: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L39) +`suspend fun getSuggestions(query: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L57) Gets search suggestions for a given query diff --git a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/index.md b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/index.md index dd469999a5f..0d618a21646 100644 --- a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/index.md +++ b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/index.md @@ -2,7 +2,7 @@ # SearchSuggestionClient -`class SearchSuggestionClient` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L19) +`class SearchSuggestionClient` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L21) Provides an interface to get search suggestions from a given SearchEngine. @@ -17,7 +17,14 @@ Provides an interface to get search suggestions from a given SearchEngine. | Name | Summary | |---|---| -| [<init>](-init-.md) | `SearchSuggestionClient(searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`, fetcher: `[`SearchSuggestionFetcher`](../-search-suggestion-fetcher.md)`)`
    Provides an interface to get search suggestions from a given SearchEngine. | +| [<init>](-init-.md) | `SearchSuggestionClient(searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`, fetcher: `[`SearchSuggestionFetcher`](../-search-suggestion-fetcher.md)`)`
    `SearchSuggestionClient(context: , searchEngineManager: `[`SearchEngineManager`](../../mozilla.components.browser.search/-search-engine-manager/index.md)`, fetcher: `[`SearchSuggestionFetcher`](../-search-suggestion-fetcher.md)`)` | + +### Properties + +| Name | Summary | +|---|---| +| [searchEngine](search-engine.md) | `var searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`?` | +| [searchEngineManager](search-engine-manager.md) | `val searchEngineManager: `[`SearchEngineManager`](../../mozilla.components.browser.search/-search-engine-manager/index.md)`?` | ### Functions diff --git a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/search-engine-manager.md b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/search-engine-manager.md new file mode 100644 index 00000000000..8467d5ca90c --- /dev/null +++ b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/search-engine-manager.md @@ -0,0 +1,5 @@ +[android-components](../../index.md) / [mozilla.components.browser.search.suggestions](../index.md) / [SearchSuggestionClient](index.md) / [searchEngineManager](./search-engine-manager.md) + +# searchEngineManager + +`val searchEngineManager: `[`SearchEngineManager`](../../mozilla.components.browser.search/-search-engine-manager/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L26) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/search-engine.md b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/search-engine.md new file mode 100644 index 00000000000..5c68027ac11 --- /dev/null +++ b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-client/search-engine.md @@ -0,0 +1,5 @@ +[android-components](../../index.md) / [mozilla.components.browser.search.suggestions](../index.md) / [SearchSuggestionClient](index.md) / [searchEngine](./search-engine.md) + +# searchEngine + +`var searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L27) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-fetcher.md b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-fetcher.md index f1c5612ce80..b35ea16e973 100644 --- a/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-fetcher.md +++ b/docs/api/mozilla.components.browser.search.suggestions/-search-suggestion-fetcher.md @@ -2,7 +2,7 @@ # SearchSuggestionFetcher -`typealias SearchSuggestionFetcher = suspend (url: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`) -> `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L14) +`typealias SearchSuggestionFetcher = suspend (url: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`) -> `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/suggestions/SearchSuggestionClient.kt#L16) Async function responsible for taking a URL and returning the results diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/default-search-engine.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/default-search-engine.md index c106a55c58e..74f48142c04 100644 --- a/docs/api/mozilla.components.browser.search/-search-engine-manager/default-search-engine.md +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/default-search-engine.md @@ -2,7 +2,7 @@ # defaultSearchEngine -`var defaultSearchEngine: `[`SearchEngine`](../-search-engine/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L39) +`var defaultSearchEngine: `[`SearchEngine`](../-search-engine/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L40) This is set by browsers to indicate the users preference of which search engine to use. This overrides the default which may be set by the [SearchEngineProvider](../../mozilla.components.browser.search.provider/-search-engine-provider/index.md) (e.g. via `list.json`) diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/get-default-search-engine-async.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-default-search-engine-async.md new file mode 100644 index 00000000000..f0d7fcff607 --- /dev/null +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-default-search-engine-async.md @@ -0,0 +1,15 @@ +[android-components](../../index.md) / [mozilla.components.browser.search](../index.md) / [SearchEngineManager](index.md) / [getDefaultSearchEngineAsync](./get-default-search-engine-async.md) + +# getDefaultSearchEngineAsync + +`suspend fun getDefaultSearchEngineAsync(context: , name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = EMPTY): `[`SearchEngine`](../-search-engine/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L129) + +Returns the default search engine. + +If defaultSearchEngine has not been set, the default engine is set by the search provider, +(e.g. as set in `list.json`). If that is not set, then the first search engine listed is +returned. + +Optionally a name can be passed to this method (e.g. from the user's preferences). If +a matching search engine was loaded then this search engine will be returned instead. + diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/get-default-search-engine.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-default-search-engine.md index 0aefbe25952..c98a5c19aa7 100644 --- a/docs/api/mozilla.components.browser.search/-search-engine-manager/get-default-search-engine.md +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-default-search-engine.md @@ -2,7 +2,7 @@ # getDefaultSearchEngine -`@Synchronized fun getDefaultSearchEngine(context: , name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = EMPTY): `[`SearchEngine`](../-search-engine/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L92) +`@Synchronized fun getDefaultSearchEngine(context: , name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = EMPTY): `[`SearchEngine`](../-search-engine/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L109) Returns the default search engine. diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/get-provided-default-search-engine-async.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-provided-default-search-engine-async.md new file mode 100644 index 00000000000..7790fd431f8 --- /dev/null +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-provided-default-search-engine-async.md @@ -0,0 +1,9 @@ +[android-components](../../index.md) / [mozilla.components.browser.search](../index.md) / [SearchEngineManager](index.md) / [getProvidedDefaultSearchEngineAsync](./get-provided-default-search-engine-async.md) + +# getProvidedDefaultSearchEngineAsync + +`suspend fun getProvidedDefaultSearchEngineAsync(context: ): `[`SearchEngine`](../-search-engine/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L153) + +Returns the provided default search engine or the first search engine if the default +is not set. + diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/get-provided-default-search-engine.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-provided-default-search-engine.md index 0f11558a050..6df890ed54c 100644 --- a/docs/api/mozilla.components.browser.search/-search-engine-manager/get-provided-default-search-engine.md +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-provided-default-search-engine.md @@ -2,7 +2,7 @@ # getProvidedDefaultSearchEngine -`@Synchronized fun getProvidedDefaultSearchEngine(context: ): `[`SearchEngine`](../-search-engine/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L107) +`@Synchronized fun getProvidedDefaultSearchEngine(context: ): `[`SearchEngine`](../-search-engine/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L144) Returns the provided default search engine or the first search engine if the default is not set. diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/get-search-engines-async.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-search-engines-async.md new file mode 100644 index 00000000000..987d4c7615a --- /dev/null +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-search-engines-async.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.browser.search](../index.md) / [SearchEngineManager](index.md) / [getSearchEnginesAsync](./get-search-engines-async.md) + +# getSearchEnginesAsync + +`suspend fun getSearchEnginesAsync(context: ): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`SearchEngine`](../-search-engine/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L94) + +Returns all search engines. + diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/get-search-engines.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-search-engines.md index 1191c8e7c90..38c9b90c195 100644 --- a/docs/api/mozilla.components.browser.search/-search-engine-manager/get-search-engines.md +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/get-search-engines.md @@ -2,7 +2,7 @@ # getSearchEngines -`@Synchronized fun getSearchEngines(context: ): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`SearchEngine`](../-search-engine/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L77) +`@Synchronized fun getSearchEngines(context: ): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`SearchEngine`](../-search-engine/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L87) Returns all search engines. diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/index.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/index.md index 7160a04a755..26a1e758056 100644 --- a/docs/api/mozilla.components.browser.search/-search-engine-manager/index.md +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/index.md @@ -2,7 +2,7 @@ # SearchEngineManager -`class SearchEngineManager` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L27) +`class SearchEngineManager` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L28) This class provides access to a centralized registry of search engines. @@ -24,8 +24,11 @@ This class provides access to a centralized registry of search engines. | Name | Summary | |---|---| | [getDefaultSearchEngine](get-default-search-engine.md) | `fun getDefaultSearchEngine(context: , name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = EMPTY): `[`SearchEngine`](../-search-engine/index.md)
    Returns the default search engine. | +| [getDefaultSearchEngineAsync](get-default-search-engine-async.md) | `suspend fun getDefaultSearchEngineAsync(context: , name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = EMPTY): `[`SearchEngine`](../-search-engine/index.md)
    Returns the default search engine. | | [getProvidedDefaultSearchEngine](get-provided-default-search-engine.md) | `fun getProvidedDefaultSearchEngine(context: ): `[`SearchEngine`](../-search-engine/index.md)
    Returns the provided default search engine or the first search engine if the default is not set. | +| [getProvidedDefaultSearchEngineAsync](get-provided-default-search-engine-async.md) | `suspend fun getProvidedDefaultSearchEngineAsync(context: ): `[`SearchEngine`](../-search-engine/index.md)
    Returns the provided default search engine or the first search engine if the default is not set. | | [getSearchEngines](get-search-engines.md) | `fun getSearchEngines(context: ): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`SearchEngine`](../-search-engine/index.md)`>`
    Returns all search engines. | +| [getSearchEnginesAsync](get-search-engines-async.md) | `suspend fun getSearchEnginesAsync(context: ): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`SearchEngine`](../-search-engine/index.md)`>`
    Returns all search engines. | | [load](load.md) | `suspend fun ~~load~~(context: ): Deferred<`[`SearchEngineList`](../../mozilla.components.browser.search.provider/-search-engine-list/index.md)`>`
    Asynchronously load search engines from providers. Inherits caller's [CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/index.html). | | [loadAsync](load-async.md) | `suspend fun loadAsync(context: ): Deferred<`[`SearchEngineList`](../../mozilla.components.browser.search.provider/-search-engine-list/index.md)`>`
    Asynchronously load search engines from providers. Inherits caller's [CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/index.html). | | [registerForLocaleUpdates](register-for-locale-updates.md) | `fun registerForLocaleUpdates(context: ): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
    Registers for ACTION_LOCALE_CHANGED broadcasts and automatically reloads the search engines whenever the locale changes. | diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/load-async.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/load-async.md index c624ea4ba5b..72691766921 100644 --- a/docs/api/mozilla.components.browser.search/-search-engine-manager/load-async.md +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/load-async.md @@ -2,7 +2,7 @@ # loadAsync -`@Synchronized suspend fun loadAsync(context: ): Deferred<`[`SearchEngineList`](../../mozilla.components.browser.search.provider/-search-engine-list/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L45) +`@Synchronized suspend fun loadAsync(context: ): Deferred<`[`SearchEngineList`](../../mozilla.components.browser.search.provider/-search-engine-list/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L46) Asynchronously load search engines from providers. Inherits caller's [CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/index.html). diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/load.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/load.md index 2f5433150d2..cba1d609e73 100644 --- a/docs/api/mozilla.components.browser.search/-search-engine-manager/load.md +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/load.md @@ -2,7 +2,7 @@ # load -`@Synchronized suspend fun ~~load~~(context: ): Deferred<`[`SearchEngineList`](../../mozilla.components.browser.search.provider/-search-engine-list/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L60) +`@Synchronized suspend fun ~~load~~(context: ): Deferred<`[`SearchEngineList`](../../mozilla.components.browser.search.provider/-search-engine-list/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L61) **Deprecated:** Use `loadAsync` instead Asynchronously load search engines from providers. Inherits caller's [CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/index.html). diff --git a/docs/api/mozilla.components.browser.search/-search-engine-manager/register-for-locale-updates.md b/docs/api/mozilla.components.browser.search/-search-engine-manager/register-for-locale-updates.md index 801d6302823..dcd6695fd92 100644 --- a/docs/api/mozilla.components.browser.search/-search-engine-manager/register-for-locale-updates.md +++ b/docs/api/mozilla.components.browser.search/-search-engine-manager/register-for-locale-updates.md @@ -2,7 +2,7 @@ # registerForLocaleUpdates -`fun registerForLocaleUpdates(context: ): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L116) +`fun registerForLocaleUpdates(context: ): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/search/src/main/java/mozilla/components/browser/search/SearchEngineManager.kt#L162) Registers for ACTION_LOCALE_CHANGED broadcasts and automatically reloads the search engines whenever the locale changes. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/-n-o_-s-e-l-e-c-t-i-o-n.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/-n-o_-s-e-l-e-c-t-i-o-n.md index 51e75c7c061..a9edb4f5936 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/-n-o_-s-e-l-e-c-t-i-o-n.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/-n-o_-s-e-l-e-c-t-i-o-n.md @@ -2,4 +2,4 @@ # NO_SELECTION -`const val NO_SELECTION: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L542) \ No newline at end of file +`const val NO_SELECTION: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L546) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/add.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/add.md index 30ba3a593f0..8b183834112 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/add.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/add.md @@ -2,11 +2,11 @@ # add -`fun add(session: `[`Session`](../-session/index.md)`, selected: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)` = false, engineSession: `[`EngineSession`](../../mozilla.components.concept.engine/-engine-session/index.md)`? = null, parent: `[`Session`](../-session/index.md)`? = null): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L134) +`fun add(session: `[`Session`](../-session/index.md)`, selected: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)` = false, engineSession: `[`EngineSession`](../../mozilla.components.concept.engine/-engine-session/index.md)`? = null, parent: `[`Session`](../-session/index.md)`? = null): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L136) Adds the provided session. -`fun add(sessions: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`Session`](../-session/index.md)`>): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L207) +`fun add(sessions: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`Session`](../-session/index.md)`>): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L209) Adds multiple sessions. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/all.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/all.md index e7dc7d905fa..e49cb15e6c3 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/all.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/all.md @@ -2,7 +2,7 @@ # all -`val all: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`Session`](../-session/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L128) +`val all: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`Session`](../-session/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L130) Returns a list of all active sessions (including CustomTab sessions). diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/create-session-snapshot.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/create-session-snapshot.md index 063c8dacc1b..66ea468d1f4 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/create-session-snapshot.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/create-session-snapshot.md @@ -2,4 +2,4 @@ # createSessionSnapshot -`fun createSessionSnapshot(session: `[`Session`](../-session/index.md)`): `[`Item`](../-session-manager/-snapshot/-item/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L82) \ No newline at end of file +`fun createSessionSnapshot(session: `[`Session`](../-session/index.md)`): `[`Item`](../-session-manager/-snapshot/-item/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L84) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/create-snapshot.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/create-snapshot.md index b3500de5fb6..8c98f88deb0 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/create-snapshot.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/create-snapshot.md @@ -2,7 +2,7 @@ # createSnapshot -`fun createSnapshot(): `[`Snapshot`](../-session-manager/-snapshot/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L42) +`fun createSnapshot(): `[`Snapshot`](../-session-manager/-snapshot/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L44) Produces a snapshot of this manager's state, suitable for restoring via [SessionManager.restore](../-session-manager/restore.md). Only regular sessions are included in the snapshot. Private and Custom Tab sessions are omitted. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/find-session-by-id.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/find-session-by-id.md index ccbed2c086f..b53725f56ee 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/find-session-by-id.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/find-session-by-id.md @@ -2,7 +2,7 @@ # findSessionById -`fun findSessionById(id: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Session`](../-session/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L525) +`fun findSessionById(id: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Session`](../-session/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L527) Finds and returns the session with the given id. Returns null if no matching session could be found. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/get-engine-session.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/get-engine-session.md index ce1016c7e5f..5bd435a82c9 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/get-engine-session.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/get-engine-session.md @@ -2,7 +2,7 @@ # getEngineSession -`fun getEngineSession(session: `[`Session`](../-session/index.md)` = selectedSessionOrThrow): `[`EngineSession`](../../mozilla.components.concept.engine/-engine-session/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L272) +`fun getEngineSession(session: `[`Session`](../-session/index.md)` = selectedSessionOrThrow): `[`EngineSession`](../../mozilla.components.concept.engine/-engine-session/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L274) Gets the linked engine session for the provided session (if it exists). diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/get-or-create-engine-session.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/get-or-create-engine-session.md index f339f4324dd..f912bc5f4b2 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/get-or-create-engine-session.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/get-or-create-engine-session.md @@ -2,7 +2,7 @@ # getOrCreateEngineSession -`fun getOrCreateEngineSession(session: `[`Session`](../-session/index.md)` = selectedSessionOrThrow): `[`EngineSession`](../../mozilla.components.concept.engine/-engine-session/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L277) +`fun getOrCreateEngineSession(session: `[`Session`](../-session/index.md)` = selectedSessionOrThrow): `[`EngineSession`](../../mozilla.components.concept.engine/-engine-session/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L279) Gets the linked engine session for the provided session and creates it if needed. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/link.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/link.md index 18a1888271b..4a8b60a350b 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/link.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/link.md @@ -2,4 +2,4 @@ # link -`fun link(session: `[`Session`](../-session/index.md)`, engineSession: `[`EngineSession`](../../mozilla.components.concept.engine/-engine-session/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L290) \ No newline at end of file +`fun link(session: `[`Session`](../-session/index.md)`, engineSession: `[`EngineSession`](../../mozilla.components.concept.engine/-engine-session/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L292) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/on-low-memory.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/on-low-memory.md index da0a950f201..fa11b3ebd8d 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/on-low-memory.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/on-low-memory.md @@ -2,7 +2,7 @@ # onLowMemory -`fun onLowMemory(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L531) +`fun onLowMemory(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L535) Informs this [SessionManager](../-session-manager/index.md) that the OS is in low memory condition so it can reduce its allocated objects. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove-all.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove-all.md index 22aa9a5178f..1b117e5adbb 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove-all.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove-all.md @@ -2,7 +2,7 @@ # removeAll -`fun removeAll(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L495) +`fun removeAll(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L497) Removes all sessions including CustomTab sessions. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove-sessions.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove-sessions.md index b88e37db84a..6395367746b 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove-sessions.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove-sessions.md @@ -2,7 +2,7 @@ # removeSessions -`fun removeSessions(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L479) +`fun removeSessions(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L481) Removes all sessions but CustomTab sessions. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove.md index a1659c62534..a077ef74c1d 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/remove.md @@ -2,7 +2,7 @@ # remove -`fun remove(session: `[`Session`](../-session/index.md)` = selectedSessionOrThrow, selectParentIfExists: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)` = false): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L317) +`fun remove(session: `[`Session`](../-session/index.md)` = selectedSessionOrThrow, selectParentIfExists: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)` = false): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L319) Removes the provided session. If no session is provided then the selected session is removed. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/restore.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/restore.md index 96f73508ad8..11f0dbae5bf 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/restore.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/restore.md @@ -2,7 +2,7 @@ # restore -`fun restore(snapshot: `[`Snapshot`](../-session-manager/-snapshot/index.md)`, updateSelection: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)` = true): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L240) +`fun restore(snapshot: `[`Snapshot`](../-session-manager/-snapshot/index.md)`, updateSelection: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)` = true): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L242) Restores sessions from the provided [Snapshot](#). diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/select.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/select.md index 707895d5f27..90f983d9c79 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/select.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/select.md @@ -2,7 +2,7 @@ # select -`fun select(session: `[`Session`](../-session/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L509) +`fun select(session: `[`Session`](../-session/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L511) Marks the given session as selected. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/selected-session-or-throw.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/selected-session-or-throw.md index 6ec240a5645..7489550c885 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/selected-session-or-throw.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/selected-session-or-throw.md @@ -2,7 +2,7 @@ # selectedSessionOrThrow -`val selectedSessionOrThrow: `[`Session`](../-session/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L116) +`val selectedSessionOrThrow: `[`Session`](../-session/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L118) Gets the currently selected session or throws an IllegalStateException if no session is selected. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/selected-session.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/selected-session.md index 8354a9c809b..820927fbd05 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/selected-session.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/selected-session.md @@ -2,7 +2,7 @@ # selectedSession -`val selectedSession: `[`Session`](../-session/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L95) +`val selectedSession: `[`Session`](../-session/index.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L97) Gets the currently selected session if there is one. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/sessions.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/sessions.md index 2125e3ad715..34fca2deaae 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/sessions.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/sessions.md @@ -2,7 +2,7 @@ # sessions -`val sessions: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`Session`](../-session/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L122) +`val sessions: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`Session`](../-session/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L124) Returns a list of active sessions and filters out sessions used for CustomTabs. diff --git a/docs/api/mozilla.components.browser.session/-legacy-session-manager/size.md b/docs/api/mozilla.components.browser.session/-legacy-session-manager/size.md index 1b54b222875..a4c8f485087 100644 --- a/docs/api/mozilla.components.browser.session/-legacy-session-manager/size.md +++ b/docs/api/mozilla.components.browser.session/-legacy-session-manager/size.md @@ -2,7 +2,7 @@ # size -`val size: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L33) +`val size: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt#L35) Returns the number of session including CustomTab sessions. diff --git a/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/apply-autocomplete-result.md b/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/apply-autocomplete-result.md index b3ccc330795..61bf2358d88 100644 --- a/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/apply-autocomplete-result.md +++ b/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/apply-autocomplete-result.md @@ -2,7 +2,7 @@ # applyAutocompleteResult -`fun applyAutocompleteResult(result: `[`AutocompleteResult`](../../mozilla.components.concept.toolbar/-autocomplete-result/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L820) +`fun applyAutocompleteResult(result: `[`AutocompleteResult`](../../mozilla.components.concept.toolbar/-autocomplete-result/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L831) Overrides [AutocompleteDelegate.applyAutocompleteResult](../../mozilla.components.concept.toolbar/-autocomplete-delegate/apply-autocomplete-result.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/coroutine-context.md b/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/coroutine-context.md index 7951efc9f40..062822b71fb 100644 --- a/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/coroutine-context.md +++ b/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/coroutine-context.md @@ -2,4 +2,4 @@ # coroutineContext -`val coroutineContext: `[`CoroutineContext`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L817) \ No newline at end of file +`val coroutineContext: `[`CoroutineContext`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L828) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/index.md b/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/index.md index 6992d65121e..ed597d3aa08 100644 --- a/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/index.md +++ b/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/index.md @@ -2,7 +2,7 @@ # AsyncAutocompleteDelegate -`class AsyncAutocompleteDelegate : `[`AutocompleteDelegate`](../../mozilla.components.concept.toolbar/-autocomplete-delegate/index.md)`, CoroutineScope` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L814) +`class AsyncAutocompleteDelegate : `[`AutocompleteDelegate`](../../mozilla.components.concept.toolbar/-autocomplete-delegate/index.md)`, CoroutineScope` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L825) An autocomplete delegate which is aware of its parent scope (to check for cancellations). Responsible for processing autocompletion results and discarding stale results when [urlView](#) moved on. diff --git a/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/no-autocomplete-result.md b/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/no-autocomplete-result.md index a1aabb1d992..559949bd9a2 100644 --- a/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/no-autocomplete-result.md +++ b/docs/api/mozilla.components.browser.toolbar/-async-autocomplete-delegate/no-autocomplete-result.md @@ -2,7 +2,7 @@ # noAutocompleteResult -`fun noAutocompleteResult(input: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L844) +`fun noAutocompleteResult(input: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L855) Overrides [AutocompleteDelegate.noAutocompleteResult](../../mozilla.components.concept.toolbar/-autocomplete-delegate/no-autocomplete-result.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/coroutine-context.md b/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/coroutine-context.md index 259191ebba6..613fd9ea552 100644 --- a/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/coroutine-context.md +++ b/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/coroutine-context.md @@ -2,4 +2,4 @@ # coroutineContext -`val coroutineContext: `[`CoroutineContext`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L795) \ No newline at end of file +`val coroutineContext: `[`CoroutineContext`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L806) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/index.md b/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/index.md index bc4cb46debb..c42023599a9 100644 --- a/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/index.md +++ b/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/index.md @@ -2,7 +2,7 @@ # AsyncFilterListener -`class AsyncFilterListener : `[`OnFilterListener`](../../mozilla.components.ui.autocomplete/-on-filter-listener.md)`, CoroutineScope` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L793) +`class AsyncFilterListener : `[`OnFilterListener`](../../mozilla.components.ui.autocomplete/-on-filter-listener.md)`, CoroutineScope` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L804) Wraps [filter](#) execution in a coroutine context, cancelling prior executions on every invocation. [coroutineContext](coroutine-context.md) must be of type that doesn't propagate cancellation of its children upwards. diff --git a/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/invoke.md b/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/invoke.md index ed186f8c79f..15566c17ded 100644 --- a/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/invoke.md +++ b/docs/api/mozilla.components.browser.toolbar/-async-filter-listener/invoke.md @@ -2,4 +2,4 @@ # invoke -`fun invoke(text: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L799) \ No newline at end of file +`fun invoke(text: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L810) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-button/index.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-button/index.md index 9f16dc77019..a8a9cdb20ab 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-button/index.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-button/index.md @@ -2,7 +2,7 @@ # Button -`class Button : `[`ActionButton`](../../../mozilla.components.concept.toolbar/-toolbar/-action-button/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L693) +`class Button : `[`ActionButton`](../../../mozilla.components.concept.toolbar/-toolbar/-action-button/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L704) An action button to be added to the toolbar. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-button/padding.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-button/padding.md index d02359ea53f..bdbe22babad 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-button/padding.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-button/padding.md @@ -2,7 +2,7 @@ # padding -`val padding: `[`Padding`](../../../mozilla.components.support.base.android/-padding/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L698) +`val padding: `[`Padding`](../../../mozilla.components.support.base.android/-padding/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L709) a custom [Padding](../../../mozilla.components.support.base.android/-padding/index.md) for this Button. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-toggle-button/index.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-toggle-button/index.md index c547cba9824..b7782d0be50 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-toggle-button/index.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-toggle-button/index.md @@ -2,7 +2,7 @@ # ToggleButton -`class ToggleButton : `[`ActionToggleButton`](../../../mozilla.components.concept.toolbar/-toolbar/-action-toggle-button/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L716) +`class ToggleButton : `[`ActionToggleButton`](../../../mozilla.components.concept.toolbar/-toolbar/-action-toggle-button/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L727) An action button with two states, selected and unselected. When the button is pressed, the state changes automatically. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-toggle-button/padding.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-toggle-button/padding.md index 007eac20d0a..f4aa991c82f 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-toggle-button/padding.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-toggle-button/padding.md @@ -2,7 +2,7 @@ # padding -`val padding: `[`Padding`](../../../mozilla.components.support.base.android/-padding/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L724) +`val padding: `[`Padding`](../../../mozilla.components.support.base.android/-padding/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L735) a custom [Padding](../../../mozilla.components.support.base.android/-padding/index.md) for this Button. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/bind.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/bind.md index f0489e1a450..c03fd14aa39 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/bind.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/bind.md @@ -2,7 +2,7 @@ # bind -`open fun bind(view: ): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L767) +`open fun bind(view: ): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L778) Overrides [ActionButton.bind](../../../mozilla.components.concept.toolbar/-toolbar/-action-button/bind.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/enabled.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/enabled.md index 26bbc20b487..ae74c028b4a 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/enabled.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/enabled.md @@ -2,4 +2,4 @@ # enabled -`var enabled: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L764) \ No newline at end of file +`var enabled: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L775) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/index.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/index.md index 31f8cc4d668..007b111aef2 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/index.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/-two-state-button/index.md @@ -2,7 +2,7 @@ # TwoStateButton -`class TwoStateButton : `[`Button`](../-button/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L750) +`class TwoStateButton : `[`Button`](../-button/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L761) An action that either shows an active button or an inactive button based on the provided isEnabled lambda. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-browser-action.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-browser-action.md index 9601f052f0f..d53db8d68fc 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-browser-action.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-browser-action.md @@ -2,7 +2,7 @@ # addBrowserAction -`fun addBrowserAction(action: `[`Action`](../../mozilla.components.concept.toolbar/-toolbar/-action/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L574) +`fun addBrowserAction(action: `[`Action`](../../mozilla.components.concept.toolbar/-toolbar/-action/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L585) Overrides [Toolbar.addBrowserAction](../../mozilla.components.concept.toolbar/-toolbar/add-browser-action.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-edit-action.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-edit-action.md index 5985ec40fa2..28941786f69 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-edit-action.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-edit-action.md @@ -2,7 +2,7 @@ # addEditAction -`fun addEditAction(action: `[`Action`](../../mozilla.components.concept.toolbar/-toolbar/-action/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L599) +`fun addEditAction(action: `[`Action`](../../mozilla.components.concept.toolbar/-toolbar/-action/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L610) Overrides [Toolbar.addEditAction](../../mozilla.components.concept.toolbar/-toolbar/add-edit-action.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-navigation-action.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-navigation-action.md index 3eedfb8e6a2..dd284abfa10 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-navigation-action.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-navigation-action.md @@ -2,7 +2,7 @@ # addNavigationAction -`fun addNavigationAction(action: `[`Action`](../../mozilla.components.concept.toolbar/-toolbar/-action/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L592) +`fun addNavigationAction(action: `[`Action`](../../mozilla.components.concept.toolbar/-toolbar/-action/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L603) Overrides [Toolbar.addNavigationAction](../../mozilla.components.concept.toolbar/-toolbar/add-navigation-action.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-page-action.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-page-action.md index d3122ae0837..86c3c8d8c9f 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-page-action.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/add-page-action.md @@ -2,7 +2,7 @@ # addPageAction -`fun addPageAction(action: `[`Action`](../../mozilla.components.concept.toolbar/-toolbar/-action/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L584) +`fun addPageAction(action: `[`Action`](../../mozilla.components.concept.toolbar/-toolbar/-action/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L595) Overrides [Toolbar.addPageAction](../../mozilla.components.concept.toolbar/-toolbar/add-page-action.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/browser-action-margin.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/browser-action-margin.md index dac9d033510..7b367bbaf7a 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/browser-action-margin.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/browser-action-margin.md @@ -2,7 +2,7 @@ # browserActionMargin -`var browserActionMargin: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L147) +`var browserActionMargin: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L156) Gets/Sets the margin to be used between browser actions. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/clear-view-color.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/clear-view-color.md index dec151f2847..2c662da6138 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/clear-view-color.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/clear-view-color.md @@ -2,7 +2,7 @@ # clearViewColor -`var clearViewColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L140) +`var clearViewColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L149) Gets/Sets the color tint of the cancel button. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-mode.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-mode.md index 8c89f11f033..c4c83f6935b 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-mode.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-mode.md @@ -2,7 +2,7 @@ # displayMode -`fun displayMode(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L627) +`fun displayMode(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L638) Overrides [Toolbar.displayMode](../../mozilla.components.concept.toolbar/-toolbar/display-mode.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-progress.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-progress.md index 470274416a4..0b4ad1b409a 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-progress.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-progress.md @@ -2,7 +2,7 @@ # displayProgress -`fun displayProgress(progress: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L543) +`fun displayProgress(progress: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L554) Overrides [Toolbar.displayProgress](../../mozilla.components.concept.toolbar/-toolbar/display-progress.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-tracking-protection-icon.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-tracking-protection-icon.md index 2830b414455..1f9979e071b 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-tracking-protection-icon.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/display-tracking-protection-icon.md @@ -2,7 +2,7 @@ # displayTrackingProtectionIcon -`var displayTrackingProtectionIcon: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L421) +`var displayTrackingProtectionIcon: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L430) Set/Get whether a tracking protection icon (usually a shield icon) should be visible. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/edit-mode.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/edit-mode.md index e841f443057..49b8cf266d4 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/edit-mode.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/edit-mode.md @@ -2,7 +2,7 @@ # editMode -`fun editMode(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L613) +`fun editMode(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L624) Overrides [Toolbar.editMode](../../mozilla.components.concept.toolbar/-toolbar/edit-mode.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/focus.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/focus.md index 76826af80ff..6a2f75634a3 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/focus.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/focus.md @@ -2,7 +2,7 @@ # focus -`fun focus(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L606) +`fun focus(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L617) Focuses the editToolbar if already in edit mode diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/hint-color.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/hint-color.md index f77d196daaf..fc123fe14ea 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/hint-color.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/hint-color.md @@ -2,7 +2,7 @@ # hintColor -`var hintColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L180) +`var hintColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L189) Sets the colour of the text to be displayed when the URL of the toolbar is empty. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/hint.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/hint.md index e34167f270b..ad651f3d8b9 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/hint.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/hint.md @@ -2,7 +2,7 @@ # hint -`var hint: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L170) +`var hint: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L179) Sets the text to be displayed when the URL of the toolbar is empty. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/index.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/index.md index cf874923bf3..ca9df6ae743 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/index.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/index.md @@ -52,7 +52,8 @@ implemented by the DisplayToolbar and EditToolbar classes. | [progressBarGravity](progress-bar-gravity.md) | `var progressBarGravity: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)
    Set progress bar to be at the top of the toolbar. It's on bottom by default. | | [separatorColor](separator-color.md) | `var separatorColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)
    Sets the colour of the vertical separator between the tracking protection icon and the security indicator icon. | | [siteSecure](site-secure.md) | `var siteSecure: `[`SiteSecurity`](../../mozilla.components.concept.toolbar/-toolbar/-site-security/index.md)
    Sets/Gets the site security to be displayed on the toolbar. | -| [siteSecurityColor](site-security-color.md) | `var siteSecurityColor: `[`Pair`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/index.html)`<`[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`>`
    Set/Get the site security icon colours (usually a lock or globe icon). It uses a pair of integers which represent the insecure and secure colours respectively. | +| [siteSecurityColor](site-security-color.md) | `var siteSecurityColor: `[`Pair`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/index.html)`<`[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`>`
    Set/Get the site security icon colours. It uses a pair of color integers which represent the insecure and secure colours respectively. | +| [siteSecurityIcon](site-security-icon.md) | `var siteSecurityIcon: `
    Set/Get the site security icon (usually a lock and globe icon). It uses a [android.graphics.drawable.StateListDrawable](#) where "state_site_secure" represents the secure icon and empty state represents the insecure icon. | | [siteTrackingProtection](site-tracking-protection.md) | `var siteTrackingProtection: `[`SiteTrackingProtection`](../../mozilla.components.concept.toolbar/-toolbar/-site-tracking-protection/index.md)
    Sets/Gets the site tracking protection state to be displayed on the toolbar. | | [suggestionBackgroundColor](suggestion-background-color.md) | `var suggestionBackgroundColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)
    The background color used for autocomplete suggestions in edit mode. | | [suggestionForegroundColor](suggestion-foreground-color.md) | `var suggestionForegroundColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`?`
    The foreground color used for autocomplete suggestions in edit mode. | diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/invalidate-actions.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/invalidate-actions.md index b086440e9a7..880aad65175 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/invalidate-actions.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/invalidate-actions.md @@ -2,7 +2,7 @@ # invalidateActions -`fun invalidateActions(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L559) +`fun invalidateActions(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L570) Declare that the actions (navigation actions, browser actions, page actions) have changed and should be updated if needed. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/menu-view-color.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/menu-view-color.md index 1c97ef4d4e3..c7a6bf686b5 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/menu-view-color.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/menu-view-color.md @@ -2,7 +2,7 @@ # menuViewColor -`var menuViewColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L133) +`var menuViewColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L142) Gets/Sets the color tint of the menu button. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-back-pressed.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-back-pressed.md index 20283880a2d..64ef3b77096 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-back-pressed.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-back-pressed.md @@ -2,7 +2,7 @@ # onBackPressed -`fun onBackPressed(): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L531) +`fun onBackPressed(): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L542) Overrides [Toolbar.onBackPressed](../../mozilla.components.concept.toolbar/-toolbar/on-back-pressed.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-layout.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-layout.md index 157bfcaa7d9..5a68f22509e 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-layout.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-layout.md @@ -2,4 +2,4 @@ # onLayout -`fun onLayout(changed: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`, left: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, top: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, right: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, bottom: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L498) \ No newline at end of file +`fun onLayout(changed: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`, left: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, top: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, right: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, bottom: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L509) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-measure.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-measure.md index 346a6f659ac..93b7d95a337 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-measure.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-measure.md @@ -2,4 +2,4 @@ # onMeasure -`fun onMeasure(widthMeasureSpec: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, heightMeasureSpec: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L509) \ No newline at end of file +`fun onMeasure(widthMeasureSpec: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, heightMeasureSpec: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L520) \ No newline at end of file diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-url-clicked.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-url-clicked.md index f63cf3101e8..70b4eaeb193 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-url-clicked.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/on-url-clicked.md @@ -2,7 +2,7 @@ # onUrlClicked -`var onUrlClicked: () -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L163) +`var onUrlClicked: () -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L172) Sets a lambda that will be invoked whenever the URL in display mode was clicked. Only if this lambda returns true the toolbar will switch to editing mode. Return diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/progress-bar-gravity.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/progress-bar-gravity.md index 186e48b02ab..3dd49f579f1 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/progress-bar-gravity.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/progress-bar-gravity.md @@ -2,7 +2,7 @@ # progressBarGravity -`var progressBarGravity: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L190) +`var progressBarGravity: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L199) Set progress bar to be at the top of the toolbar. It's on bottom by default. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/separator-color.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/separator-color.md index 97823510a4c..6a025ddf7ed 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/separator-color.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/separator-color.md @@ -2,7 +2,7 @@ # separatorColor -`var separatorColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L254) +`var separatorColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L263) Sets the colour of the vertical separator between the tracking protection icon and the security indicator icon. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-autocomplete-listener.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-autocomplete-listener.md index 476ca1ddb9b..45b59411053 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-autocomplete-listener.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-autocomplete-listener.md @@ -2,7 +2,7 @@ # setAutocompleteListener -`fun setAutocompleteListener(filter: suspend (`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, `[`AutocompleteDelegate`](../../mozilla.components.concept.toolbar/-autocomplete-delegate/index.md)`) -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L362) +`fun setAutocompleteListener(filter: suspend (`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, `[`AutocompleteDelegate`](../../mozilla.components.concept.toolbar/-autocomplete-delegate/index.md)`) -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L371) Overrides [Toolbar.setAutocompleteListener](../../mozilla.components.concept.toolbar/-toolbar/set-autocomplete-listener.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-menu-builder.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-menu-builder.md index 8add3f2c97f..6f5e1e03dbf 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-menu-builder.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-menu-builder.md @@ -2,7 +2,7 @@ # setMenuBuilder -`fun setMenuBuilder(menuBuilder: `[`BrowserMenuBuilder`](../../mozilla.components.browser.menu/-browser-menu-builder/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L635) +`fun setMenuBuilder(menuBuilder: `[`BrowserMenuBuilder`](../../mozilla.components.browser.menu/-browser-menu-builder/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L646) Sets a BrowserMenuBuilder that will be used to create a menu when the menu button is clicked. The menu button will only be visible if a builder has been set. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-edit-focus-change-listener.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-edit-focus-change-listener.md index 396c7820fc0..acaef36e33d 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-edit-focus-change-listener.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-edit-focus-change-listener.md @@ -2,7 +2,7 @@ # setOnEditFocusChangeListener -`fun setOnEditFocusChangeListener(listener: (`[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`) -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L306) +`fun setOnEditFocusChangeListener(listener: (`[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`) -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L315) Sets a listener to be invoked when focus of the URL input view (in edit mode) changed. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-edit-listener.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-edit-listener.md index 20181b05d68..8cc608ecb94 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-edit-listener.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-edit-listener.md @@ -2,7 +2,7 @@ # setOnEditListener -`fun setOnEditListener(listener: `[`OnEditListener`](../../mozilla.components.concept.toolbar/-toolbar/-on-edit-listener/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L358) +`fun setOnEditListener(listener: `[`OnEditListener`](../../mozilla.components.concept.toolbar/-toolbar/-on-edit-listener/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L367) Overrides [Toolbar.setOnEditListener](../../mozilla.components.concept.toolbar/-toolbar/set-on-edit-listener.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-site-security-clicked-listener.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-site-security-clicked-listener.md index 17488115c06..a031b5b6769 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-site-security-clicked-listener.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-site-security-clicked-listener.md @@ -2,7 +2,7 @@ # setOnSiteSecurityClickedListener -`fun setOnSiteSecurityClickedListener(listener: () -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L315) +`fun setOnSiteSecurityClickedListener(listener: () -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L324) Sets a listener to be invoked when the site security indicator icon is clicked. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-tracking-protection-clicked-listener.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-tracking-protection-clicked-listener.md index 053e4069a95..4665d66ff46 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-tracking-protection-clicked-listener.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-tracking-protection-clicked-listener.md @@ -2,7 +2,7 @@ # setOnTrackingProtectionClickedListener -`fun setOnTrackingProtectionClickedListener(listener: () -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L338) +`fun setOnTrackingProtectionClickedListener(listener: () -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L347) Sets a listener to be invoked when the site tracking protection indicator icon is clicked. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-url-commit-listener.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-url-commit-listener.md index 6c48a784702..80bad356c73 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-url-commit-listener.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-url-commit-listener.md @@ -2,7 +2,7 @@ # setOnUrlCommitListener -`fun setOnUrlCommitListener(listener: (`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L547) +`fun setOnUrlCommitListener(listener: (`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L558) Overrides [Toolbar.setOnUrlCommitListener](../../mozilla.components.concept.toolbar/-toolbar/set-on-url-commit-listener.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-url-long-click-listener.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-url-long-click-listener.md index 72e170f409f..98b688a3f72 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-url-long-click-listener.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-on-url-long-click-listener.md @@ -2,7 +2,7 @@ # setOnUrlLongClickListener -`fun setOnUrlLongClickListener(handler: () -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L642) +`fun setOnUrlLongClickListener(handler: () -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L653) Set a LongClickListener to the urlView of the toolbar. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-search-terms.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-search-terms.md index e682fee7d3f..f10fbff5420 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-search-terms.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-search-terms.md @@ -2,7 +2,7 @@ # setSearchTerms -`fun setSearchTerms(searchTerms: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L539) +`fun setSearchTerms(searchTerms: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L550) Overrides [Toolbar.setSearchTerms](../../mozilla.components.concept.toolbar/-toolbar/set-search-terms.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-tracking-protection-icons.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-tracking-protection-icons.md index f14a1b9080f..6ad9cc9b993 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-tracking-protection-icons.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-tracking-protection-icons.md @@ -14,7 +14,7 @@ context.getDrawable( TrackingProtectionIconView.DEFAULT_ICON_OFF_FOR_A_SITE ) - )): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L225) + )): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L234) Sets the different icons that the tracking protection icon could has depending of its [Toolbar.siteTrackingProtection](../../mozilla.components.concept.toolbar/-toolbar/site-tracking-protection.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-url-text-padding.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-url-text-padding.md index 070124df37e..24a3eeef246 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-url-text-padding.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/set-url-text-padding.md @@ -2,7 +2,7 @@ # setUrlTextPadding -`fun setUrlTextPadding(left: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = displayToolbar.urlView.paddingLeft, top: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = displayToolbar.urlView.paddingTop, right: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = displayToolbar.urlView.paddingRight, bottom: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = displayToolbar.urlView.paddingBottom): ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L375) +`fun setUrlTextPadding(left: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = displayToolbar.urlView.paddingLeft, top: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = displayToolbar.urlView.paddingTop, right: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = displayToolbar.urlView.paddingRight, bottom: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = displayToolbar.urlView.paddingBottom): ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L384) Sets the padding to be applied to the URL text (in display mode). diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-secure.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-secure.md index 0a07f5c7819..805dd703e9d 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-secure.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-secure.md @@ -2,7 +2,7 @@ # siteSecure -`var siteSecure: `[`SiteSecurity`](../../mozilla.components.concept.toolbar/-toolbar/-site-security/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L403) +`var siteSecure: `[`SiteSecurity`](../../mozilla.components.concept.toolbar/-toolbar/-site-security/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L412) Overrides [Toolbar.siteSecure](../../mozilla.components.concept.toolbar/-toolbar/site-secure.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-security-color.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-security-color.md index 745609abe54..12d235f4348 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-security-color.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-security-color.md @@ -2,8 +2,8 @@ # siteSecurityColor -`var siteSecurityColor: `[`Pair`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/index.html)`<`[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L119) +`var siteSecurityColor: `[`Pair`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/index.html)`<`[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L128) -Set/Get the site security icon colours (usually a lock or globe icon). It uses a pair of integers +Set/Get the site security icon colours. It uses a pair of color integers which represent the insecure and secure colours respectively. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-security-icon.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-security-icon.md new file mode 100644 index 00000000000..83236fca7a2 --- /dev/null +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-security-icon.md @@ -0,0 +1,10 @@ +[android-components](../../index.md) / [mozilla.components.browser.toolbar](../index.md) / [BrowserToolbar](index.md) / [siteSecurityIcon](./site-security-icon.md) + +# siteSecurityIcon + +`var siteSecurityIcon: ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L120) + +Set/Get the site security icon (usually a lock and globe icon). It uses a +[android.graphics.drawable.StateListDrawable](#) where "state_site_secure" represents the secure +icon and empty state represents the insecure icon. + diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-tracking-protection.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-tracking-protection.md index c662982c672..4973194b87d 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-tracking-protection.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/site-tracking-protection.md @@ -2,7 +2,7 @@ # siteTrackingProtection -`var siteTrackingProtection: `[`SiteTrackingProtection`](../../mozilla.components.concept.toolbar/-toolbar/-site-tracking-protection/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L409) +`var siteTrackingProtection: `[`SiteTrackingProtection`](../../mozilla.components.concept.toolbar/-toolbar/-site-tracking-protection/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L418) Overrides [Toolbar.siteTrackingProtection](../../mozilla.components.concept.toolbar/-toolbar/site-tracking-protection.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/suggestion-background-color.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/suggestion-background-color.md index d4595f8afe3..0b6b9de3942 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/suggestion-background-color.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/suggestion-background-color.md @@ -2,7 +2,7 @@ # suggestionBackgroundColor -`var suggestionBackgroundColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L282) +`var suggestionBackgroundColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L291) The background color used for autocomplete suggestions in edit mode. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/suggestion-foreground-color.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/suggestion-foreground-color.md index 694efa80a3d..abfd598afdd 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/suggestion-foreground-color.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/suggestion-foreground-color.md @@ -2,7 +2,7 @@ # suggestionForegroundColor -`var suggestionForegroundColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L289) +`var suggestionForegroundColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L298) The foreground color used for autocomplete suggestions in edit mode. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/text-color.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/text-color.md index e7fbdd82e86..a7b47401222 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/text-color.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/text-color.md @@ -2,7 +2,7 @@ # textColor -`var textColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L208) +`var textColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L217) Sets the colour of the text for the URL/search term displayed in the toolbar. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/text-size.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/text-size.md index 3405d1e5546..ba56c437c03 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/text-size.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/text-size.md @@ -2,7 +2,7 @@ # textSize -`var textSize: `[`Float`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-float/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L272) +`var textSize: `[`Float`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-float/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L281) Sets the size of the text for the URL/search term displayed in the toolbar. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title-color.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title-color.md index c2e4084cc0e..5d09af04fbe 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title-color.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title-color.md @@ -2,7 +2,7 @@ # titleColor -`var titleColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L199) +`var titleColor: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L208) Sets the colour of the text for title displayed in the toolbar. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title-text-size.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title-text-size.md index 90e9b28eff0..5dd7775270d 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title-text-size.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title-text-size.md @@ -2,7 +2,7 @@ # titleTextSize -`var titleTextSize: `[`Float`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-float/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L263) +`var titleTextSize: `[`Float`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-float/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L272) Sets the size of the text for the title displayed in the toolbar. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title.md index e685607e86c..da8a9182315 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/title.md @@ -2,7 +2,7 @@ # title -`var title: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L386) +`var title: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L395) Overrides [Toolbar.title](../../mozilla.components.concept.toolbar/-toolbar/title.md) diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/typeface.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/typeface.md index df199081dcf..87d20959b81 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/typeface.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/typeface.md @@ -2,7 +2,7 @@ # typeface -`var typeface: ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L296) +`var typeface: ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L305) Sets the typeface of the text for the URL/search term displayed in the toolbar. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url-box-margin.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url-box-margin.md index 6d7478ec6bc..65ef827d6fa 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url-box-margin.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url-box-margin.md @@ -2,7 +2,7 @@ # urlBoxMargin -`var urlBoxMargin: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L154) +`var urlBoxMargin: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L163) Gets/Sets horizontal margin of the URL box (surrounding URL and page actions) in display mode. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url-box-view.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url-box-view.md index 2cdf7beaac5..58f7f21d577 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url-box-view.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url-box-view.md @@ -2,7 +2,7 @@ # urlBoxView -`var urlBoxView: ?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L126) +`var urlBoxView: ?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L135) Gets/Sets a custom view that will be drawn as behind the URL and page actions in display mode. diff --git a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url.md b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url.md index 06f54d8a469..8f7065bd42d 100644 --- a/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url.md +++ b/docs/api/mozilla.components.browser.toolbar/-browser-toolbar/url.md @@ -2,7 +2,7 @@ # url -`var url: `[`CharSequence`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-char-sequence/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L393) +`var url: `[`CharSequence`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-char-sequence/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/BrowserToolbar.kt#L402) Overrides [Toolbar.url](../../mozilla.components.concept.toolbar/-toolbar/url.md) diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-controller/index.md b/docs/api/mozilla.components.concept.engine.media/-media/-controller/index.md index 200a6fa9f37..2272d7ecdb6 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-controller/index.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-controller/index.md @@ -2,7 +2,7 @@ # Controller -`interface Controller` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L39) +`interface Controller` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L45) Controller for controlling playback of a media element. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-controller/pause.md b/docs/api/mozilla.components.concept.engine.media/-media/-controller/pause.md index fc7cbde09da..56412797883 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-controller/pause.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-controller/pause.md @@ -2,7 +2,7 @@ # pause -`abstract fun pause(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L43) +`abstract fun pause(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L49) Pauses the media. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-controller/play.md b/docs/api/mozilla.components.concept.engine.media/-media/-controller/play.md index f5d9e47e7f9..f4a5baa34a5 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-controller/play.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-controller/play.md @@ -2,7 +2,7 @@ # play -`abstract fun play(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L48) +`abstract fun play(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L54) Plays the media. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-controller/seek.md b/docs/api/mozilla.components.concept.engine.media/-media/-controller/seek.md index 6d64383b448..9d723850b45 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-controller/seek.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-controller/seek.md @@ -2,7 +2,7 @@ # seek -`abstract fun seek(time: `[`Double`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L53) +`abstract fun seek(time: `[`Double`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L59) Seek the media to a given time. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-controller/set-muted.md b/docs/api/mozilla.components.concept.engine.media/-media/-controller/set-muted.md index 6120b99bd2b..99240a1c420 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-controller/set-muted.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-controller/set-muted.md @@ -2,7 +2,7 @@ # setMuted -`abstract fun setMuted(muted: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L58) +`abstract fun setMuted(muted: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L64) Mutes/Unmutes the media. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-metadata/-init-.md b/docs/api/mozilla.components.concept.engine.media/-media/-metadata/-init-.md new file mode 100644 index 00000000000..6584fdd13e8 --- /dev/null +++ b/docs/api/mozilla.components.concept.engine.media/-media/-metadata/-init-.md @@ -0,0 +1,8 @@ +[android-components](../../../index.md) / [mozilla.components.concept.engine.media](../../index.md) / [Media](../index.md) / [Metadata](index.md) / [<init>](./-init-.md) + +# <init> + +`Metadata(duration: `[`Double`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)` = -1.0)` + +Metadata associated with [Media](../index.md). + diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-metadata/duration.md b/docs/api/mozilla.components.concept.engine.media/-media/-metadata/duration.md new file mode 100644 index 00000000000..b5c26548b7f --- /dev/null +++ b/docs/api/mozilla.components.concept.engine.media/-media/-metadata/duration.md @@ -0,0 +1,11 @@ +[android-components](../../../index.md) / [mozilla.components.concept.engine.media](../../index.md) / [Media](../index.md) / [Metadata](index.md) / [duration](./duration.md) + +# duration + +`val duration: `[`Double`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L144) + +Indicates the duration of the media in seconds. + +### Property + +`duration` - Indicates the duration of the media in seconds. \ No newline at end of file diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-metadata/index.md b/docs/api/mozilla.components.concept.engine.media/-media/-metadata/index.md new file mode 100644 index 00000000000..b87227d2120 --- /dev/null +++ b/docs/api/mozilla.components.concept.engine.media/-media/-metadata/index.md @@ -0,0 +1,19 @@ +[android-components](../../../index.md) / [mozilla.components.concept.engine.media](../../index.md) / [Media](../index.md) / [Metadata](./index.md) + +# Metadata + +`data class Metadata` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L143) + +Metadata associated with [Media](../index.md). + +### Constructors + +| Name | Summary | +|---|---| +| [<init>](-init-.md) | `Metadata(duration: `[`Double`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)` = -1.0)`
    Metadata associated with [Media](../index.md). | + +### Properties + +| Name | Summary | +|---|---| +| [duration](duration.md) | `val duration: `[`Double`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
    Indicates the duration of the media in seconds. | diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-observer/index.md b/docs/api/mozilla.components.concept.engine.media/-media/-observer/index.md index fcd04dfc21e..7e43b6db184 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-observer/index.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-observer/index.md @@ -2,7 +2,7 @@ # Observer -`interface Observer` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L32) +`interface Observer` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L37) Interface to be implemented by classes that want to observe a media element. @@ -10,4 +10,5 @@ Interface to be implemented by classes that want to observe a media element. | Name | Summary | |---|---| +| [onMetadataChanged](on-metadata-changed.md) | `open fun onMetadataChanged(media: `[`Media`](../index.md)`, metadata: `[`Metadata`](../-metadata/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) | | [onPlaybackStateChanged](on-playback-state-changed.md) | `open fun onPlaybackStateChanged(media: `[`Media`](../index.md)`, playbackState: `[`PlaybackState`](../-playback-state/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) | diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-observer/on-metadata-changed.md b/docs/api/mozilla.components.concept.engine.media/-media/-observer/on-metadata-changed.md new file mode 100644 index 00000000000..dcbbf516409 --- /dev/null +++ b/docs/api/mozilla.components.concept.engine.media/-media/-observer/on-metadata-changed.md @@ -0,0 +1,5 @@ +[android-components](../../../index.md) / [mozilla.components.concept.engine.media](../../index.md) / [Media](../index.md) / [Observer](index.md) / [onMetadataChanged](./on-metadata-changed.md) + +# onMetadataChanged + +`open fun onMetadataChanged(media: `[`Media`](../index.md)`, metadata: `[`Metadata`](../-metadata/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L39) \ No newline at end of file diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-observer/on-playback-state-changed.md b/docs/api/mozilla.components.concept.engine.media/-media/-observer/on-playback-state-changed.md index 356be44e029..a1c96ffb3e9 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-observer/on-playback-state-changed.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-observer/on-playback-state-changed.md @@ -2,4 +2,4 @@ # onPlaybackStateChanged -`open fun onPlaybackStateChanged(media: `[`Media`](../index.md)`, playbackState: `[`PlaybackState`](../-playback-state/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L33) \ No newline at end of file +`open fun onPlaybackStateChanged(media: `[`Media`](../index.md)`, playbackState: `[`PlaybackState`](../-playback-state/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L38) \ No newline at end of file diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-a-b-o-r-t.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-a-b-o-r-t.md index bf37fc64567..c01221270a2 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-a-b-o-r-t.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-a-b-o-r-t.md @@ -2,7 +2,7 @@ # ABORT -`ABORT` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L123) +`ABORT` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L129) Sent when playback is aborted; for example, if the media is playing and is restarted from the beginning, this event is sent. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-e-m-p-t-i-e-d.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-e-m-p-t-i-e-d.md index 835ed6ac4f7..98924b6297f 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-e-m-p-t-i-e-d.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-e-m-p-t-i-e-d.md @@ -2,7 +2,7 @@ # EMPTIED -`EMPTIED` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L129) +`EMPTIED` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L135) The media has become empty. For example, this event is sent if the media has already been loaded, and the load() method is called to reload it. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-e-n-d-e-d.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-e-n-d-e-d.md index 6dbd4c356e3..6451a7927e6 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-e-n-d-e-d.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-e-n-d-e-d.md @@ -2,7 +2,7 @@ # ENDED -`ENDED` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L90) +`ENDED` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L96) Sent when playback completes. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-a-u-s-e.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-a-u-s-e.md index 28af1aed419..b0cecb32378 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-a-u-s-e.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-a-u-s-e.md @@ -2,7 +2,7 @@ # PAUSE -`PAUSE` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L85) +`PAUSE` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L91) Sent when the playback state is changed to paused. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-l-a-y-i-n-g.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-l-a-y-i-n-g.md index 427c2358263..1f6ebe303e6 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-l-a-y-i-n-g.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-l-a-y-i-n-g.md @@ -2,7 +2,7 @@ # PLAYING -`PLAYING` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L80) +`PLAYING` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L86) Sent when the media has enough data to start playing, after the play event, but also when recovering from being stalled, when looping media restarts, and after seeked, if it was playing before seeking. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-l-a-y.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-l-a-y.md index 437bd99608c..8235a8701c0 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-l-a-y.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-p-l-a-y.md @@ -2,7 +2,7 @@ # PLAY -`PLAY` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L74) +`PLAY` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L80) The media is no longer paused, as a result of the play method, or the autoplay attribute. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-e-e-k-e-d.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-e-e-k-e-d.md index da6fea4e08a..786258d7b71 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-e-e-k-e-d.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-e-e-k-e-d.md @@ -2,7 +2,7 @@ # SEEKED -`SEEKED` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L100) +`SEEKED` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L106) Sent when a seek operation completes. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-e-e-k-i-n-g.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-e-e-k-i-n-g.md index 6d5c926cee6..932da10b640 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-e-e-k-i-n-g.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-e-e-k-i-n-g.md @@ -2,7 +2,7 @@ # SEEKING -`SEEKING` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L95) +`SEEKING` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L101) Sent when a seek operation begins. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-t-a-l-l-e-d.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-t-a-l-l-e-d.md index b815d96322d..92d214afed8 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-t-a-l-l-e-d.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-t-a-l-l-e-d.md @@ -2,7 +2,7 @@ # STALLED -`STALLED` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L105) +`STALLED` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L111) Sent when the user agent is trying to fetch media data, but data is unexpectedly not forthcoming. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-u-s-p-e-n-d-e-d.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-u-s-p-e-n-d-e-d.md index 1fc7277d137..9882f262cc9 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-u-s-p-e-n-d-e-d.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-s-u-s-p-e-n-d-e-d.md @@ -2,7 +2,7 @@ # SUSPENDED -`SUSPENDED` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L111) +`SUSPENDED` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L117) Sent when loading of the media is suspended. This may happen either because the download has completed or because it has been paused for any other reason. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-u-n-k-n-o-w-n.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-u-n-k-n-o-w-n.md index 0379c4d5861..27f99cb945c 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-u-n-k-n-o-w-n.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-u-n-k-n-o-w-n.md @@ -2,7 +2,7 @@ # UNKNOWN -`UNKNOWN` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L69) +`UNKNOWN` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L75) Unknown. No state has been received from the engine yet. diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-w-a-i-t-i-n-g.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-w-a-i-t-i-n-g.md index 2a1cab89d64..81433b165cc 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-w-a-i-t-i-n-g.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/-w-a-i-t-i-n-g.md @@ -2,7 +2,7 @@ # WAITING -`WAITING` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L117) +`WAITING` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L123) Sent when the requested operation (such as playback) is delayed pending the completion of another operation (such as a seek). diff --git a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/index.md b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/index.md index abf8887e0ee..d35663d8bdd 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/index.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/-playback-state/index.md @@ -2,7 +2,7 @@ # PlaybackState -`enum class PlaybackState` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L65) +`enum class PlaybackState` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L71) ### Enum Values diff --git a/docs/api/mozilla.components.concept.engine.media/-media/index.md b/docs/api/mozilla.components.concept.engine.media/-media/index.md index 9636669ce2c..ef822d20b54 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/index.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/index.md @@ -11,6 +11,7 @@ Value type that represents a media element that is present on the currently disp | Name | Summary | |---|---| | [Controller](-controller/index.md) | `interface Controller`
    Controller for controlling playback of a media element. | +| [Metadata](-metadata/index.md) | `data class Metadata`
    Metadata associated with [Media](./index.md). | | [Observer](-observer/index.md) | `interface Observer`
    Interface to be implemented by classes that want to observe a media element. | | [PlaybackState](-playback-state/index.md) | `enum class PlaybackState` | @@ -25,6 +26,7 @@ Value type that represents a media element that is present on the currently disp | Name | Summary | |---|---| | [controller](controller.md) | `abstract val controller: `[`Controller`](-controller/index.md)
    The [Controller](-controller/index.md) for controlling playback of this media element. | +| [metadata](metadata.md) | `abstract val metadata: `[`Metadata`](-metadata/index.md)
    The [Metadata](-metadata/index.md) | | [playbackState](playback-state.md) | `var playbackState: `[`PlaybackState`](-playback-state/index.md)
    The current [PlaybackState](-playback-state/index.md) of this media element. | ### Functions diff --git a/docs/api/mozilla.components.concept.engine.media/-media/metadata.md b/docs/api/mozilla.components.concept.engine.media/-media/metadata.md new file mode 100644 index 00000000000..345eabc9ae9 --- /dev/null +++ b/docs/api/mozilla.components.concept.engine.media/-media/metadata.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.concept.engine.media](../index.md) / [Media](index.md) / [metadata](./metadata.md) + +# metadata + +`abstract val metadata: `[`Metadata`](-metadata/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L32) + +The [Metadata](-metadata/index.md) + diff --git a/docs/api/mozilla.components.concept.engine.media/-media/to-string.md b/docs/api/mozilla.components.concept.engine.media/-media/to-string.md index 0ba388ac4e4..5d29b6cb70d 100644 --- a/docs/api/mozilla.components.concept.engine.media/-media/to-string.md +++ b/docs/api/mozilla.components.concept.engine.media/-media/to-string.md @@ -2,4 +2,4 @@ # toString -`open fun toString(): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L141) \ No newline at end of file +`open fun toString(): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/concept/engine/src/main/java/mozilla/components/concept/engine/media/Media.kt#L156) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-init-.md b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-init-.md index 27dba514c1a..9f76be0f344 100644 --- a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-init-.md +++ b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-init-.md @@ -4,8 +4,7 @@ `SearchSuggestionProvider(searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](-mode/index.md)` = Mode.SINGLE_SUGGESTION, icon: ? = null)` -A [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) implementation that provides a suggestion containing search engine suggestions (as -chips) from the passed in [SearchEngine](../../mozilla.components.browser.search/-search-engine/index.md). +Creates a [SearchSuggestionProvider](index.md) for the provided [SearchEngine](../../mozilla.components.browser.search/-search-engine/index.md). ### Parameters @@ -19,4 +18,23 @@ chips) from the passed in [SearchEngine](../../mozilla.components.browser.search `mode` - Whether to return a single search suggestion (with chips) or one suggestion per item. +`icon` - The image to display next to the result. If not specified, the engine icon is used`SearchSuggestionProvider(context: , searchEngineManager: `[`SearchEngineManager`](../../mozilla.components.browser.search/-search-engine-manager/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](-mode/index.md)` = Mode.SINGLE_SUGGESTION, icon: ? = null)` + +Creates a [SearchSuggestionProvider](index.md) using the default engine as returned by the provided +[SearchEngineManager](../../mozilla.components.browser.search/-search-engine-manager/index.md). + +### Parameters + +`context` - the activity or application context, required to load search engines. + +`searchEngineManager` - The search engine manager to look up search engines. + +`searchUseCase` - The use case to invoke for searches. + +`fetchClient` - The HTTP client for requesting suggestions from the search engine. + +`limit` - The maximum number of suggestions that should be returned. It needs to be >= 1. + +`mode` - Whether to return a single search suggestion (with chips) or one suggestion per item. + `icon` - The image to display next to the result. If not specified, the engine icon is used \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/-m-u-l-t-i-p-l-e_-s-u-g-g-e-s-t-i-o-n-s.md b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/-m-u-l-t-i-p-l-e_-s-u-g-g-e-s-t-i-o-n-s.md index f1b4f25288d..77c27ed279c 100644 --- a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/-m-u-l-t-i-p-l-e_-s-u-g-g-e-s-t-i-o-n-s.md +++ b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/-m-u-l-t-i-p-l-e_-s-u-g-g-e-s-t-i-o-n-s.md @@ -2,4 +2,4 @@ # MULTIPLE_SUGGESTIONS -`MULTIPLE_SUGGESTIONS` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L148) \ No newline at end of file +`MULTIPLE_SUGGESTIONS` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L196) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/-s-i-n-g-l-e_-s-u-g-g-e-s-t-i-o-n.md b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/-s-i-n-g-l-e_-s-u-g-g-e-s-t-i-o-n.md index 1672ae7181a..7a343e2d8e0 100644 --- a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/-s-i-n-g-l-e_-s-u-g-g-e-s-t-i-o-n.md +++ b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/-s-i-n-g-l-e_-s-u-g-g-e-s-t-i-o-n.md @@ -2,4 +2,4 @@ # SINGLE_SUGGESTION -`SINGLE_SUGGESTION` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L147) \ No newline at end of file +`SINGLE_SUGGESTION` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L195) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/index.md b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/index.md index 146ae6cb85a..fd46677109d 100644 --- a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/index.md +++ b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/index.md @@ -2,7 +2,7 @@ # Mode -`enum class Mode` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L146) +`enum class Mode` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L194) ### Enum Values diff --git a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/id.md b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/id.md index ebda9f1503d..b6044ffa127 100644 --- a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/id.md +++ b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/id.md @@ -2,7 +2,7 @@ # id -`val id: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L39) +`val id: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L28) Overrides [SuggestionProvider.id](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/id.md) diff --git a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/index.md b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/index.md index 9e6323d464b..c579dcb0a13 100644 --- a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/index.md +++ b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/index.md @@ -2,25 +2,11 @@ # SearchSuggestionProvider -`class SearchSuggestionProvider : `[`SuggestionProvider`](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L31) +`class SearchSuggestionProvider : `[`SuggestionProvider`](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L27) A [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) implementation that provides a suggestion containing search engine suggestions (as chips) from the passed in [SearchEngine](../../mozilla.components.browser.search/-search-engine/index.md). -### Parameters - -`searchEngine` - The search engine to request suggestions from. - -`searchUseCase` - The use case to invoke for searches. - -`fetchClient` - The HTTP client for requesting suggestions from the search engine. - -`limit` - The maximum number of suggestions that should be returned. It needs to be >= 1. - -`mode` - Whether to return a single search suggestion (with chips) or one suggestion per item. - -`icon` - The image to display next to the result. If not specified, the engine icon is used - ### Types | Name | Summary | @@ -31,7 +17,7 @@ chips) from the passed in [SearchEngine](../../mozilla.components.browser.search | Name | Summary | |---|---| -| [<init>](-init-.md) | `SearchSuggestionProvider(searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](-mode/index.md)` = Mode.SINGLE_SUGGESTION, icon: ? = null)`
    A [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) implementation that provides a suggestion containing search engine suggestions (as chips) from the passed in [SearchEngine](../../mozilla.components.browser.search/-search-engine/index.md). | +| [<init>](-init-.md) | `SearchSuggestionProvider(searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](-mode/index.md)` = Mode.SINGLE_SUGGESTION, icon: ? = null)`
    Creates a [SearchSuggestionProvider](./index.md) for the provided [SearchEngine](../../mozilla.components.browser.search/-search-engine/index.md).`SearchSuggestionProvider(context: , searchEngineManager: `[`SearchEngineManager`](../../mozilla.components.browser.search/-search-engine-manager/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](-mode/index.md)` = Mode.SINGLE_SUGGESTION, icon: ? = null)`
    Creates a [SearchSuggestionProvider](./index.md) using the default engine as returned by the provided [SearchEngineManager](../../mozilla.components.browser.search/-search-engine-manager/index.md). | ### Properties diff --git a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/on-input-changed.md b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/on-input-changed.md index 2f1d5b93a02..f374e2d99fd 100644 --- a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/on-input-changed.md +++ b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/on-input-changed.md @@ -2,7 +2,7 @@ # onInputChanged -`suspend fun onInputChanged(text: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`Suggestion`](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L54) +`suspend fun onInputChanged(text: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`Suggestion`](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L108) Overrides [SuggestionProvider.onInputChanged](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/on-input-changed.md) diff --git a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/should-clear-suggestions.md b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/should-clear-suggestions.md index 5ffac625ad2..0e53f52f3a3 100644 --- a/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/should-clear-suggestions.md +++ b/docs/api/mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/should-clear-suggestions.md @@ -2,7 +2,7 @@ # shouldClearSuggestions -`val shouldClearSuggestions: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L142) +`val shouldClearSuggestions: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/provider/SearchSuggestionProvider.kt#L190) Overrides [SuggestionProvider.shouldClearSuggestions](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/should-clear-suggestions.md) diff --git a/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-clipboard-provider.md b/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-clipboard-provider.md index 3cb28bee820..1259e14f6e9 100644 --- a/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-clipboard-provider.md +++ b/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-clipboard-provider.md @@ -2,4 +2,4 @@ # addClipboardProvider -`fun addClipboardProvider(context: , loadUrlUseCase: `[`LoadUrlUseCase`](../../mozilla.components.feature.session/-session-use-cases/-load-url-use-case/index.md)`): `[`AwesomeBarFeature`](index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L85) \ No newline at end of file +`fun addClipboardProvider(context: , loadUrlUseCase: `[`LoadUrlUseCase`](../../mozilla.components.feature.session/-session-use-cases/-load-url-use-case/index.md)`): `[`AwesomeBarFeature`](index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L107) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-history-provider.md b/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-history-provider.md index c3662393e5e..bf7e0df48a3 100644 --- a/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-history-provider.md +++ b/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-history-provider.md @@ -2,7 +2,7 @@ # addHistoryProvider -`fun addHistoryProvider(historyStorage: `[`HistoryStorage`](../../mozilla.components.concept.storage/-history-storage/index.md)`, loadUrlUseCase: `[`LoadUrlUseCase`](../../mozilla.components.feature.session/-session-use-cases/-load-url-use-case/index.md)`): `[`AwesomeBarFeature`](index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L77) +`fun addHistoryProvider(historyStorage: `[`HistoryStorage`](../../mozilla.components.concept.storage/-history-storage/index.md)`, loadUrlUseCase: `[`LoadUrlUseCase`](../../mozilla.components.feature.session/-session-use-cases/-load-url-use-case/index.md)`): `[`AwesomeBarFeature`](index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L99) Add a [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) for browsing history to the [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md). diff --git a/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-search-provider.md b/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-search-provider.md index 453a6db4081..457b53676b6 100644 --- a/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-search-provider.md +++ b/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-search-provider.md @@ -2,7 +2,14 @@ # addSearchProvider -`fun addSearchProvider(searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](../../mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/index.md)` = SearchSuggestionProvider.Mode.SINGLE_SUGGESTION): `[`AwesomeBarFeature`](index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L63) +`fun addSearchProvider(searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](../../mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/index.md)` = SearchSuggestionProvider.Mode.SINGLE_SUGGESTION): `[`AwesomeBarFeature`](index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L64) -Add a [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) for search engine suggestions to the [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md). +Adds a [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) for search engine suggestions to the [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md). + +`fun addSearchProvider(context: , searchEngineManager: `[`SearchEngineManager`](../../mozilla.components.browser.search/-search-engine-manager/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](../../mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/index.md)` = SearchSuggestionProvider.Mode.SINGLE_SUGGESTION): `[`AwesomeBarFeature`](index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L82) + +Adds a [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) for search engine suggestions to the [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md). +If the default search engine is to be used for fetching search engine suggestions then +this method is preferable over [addSearchProvider](./add-search-provider.md), as it will lazily load the default +search engine using the provided [SearchEngineManager](../../mozilla.components.browser.search/-search-engine-manager/index.md). diff --git a/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-session-provider.md b/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-session-provider.md index 66d520c2e64..b2f30c0a5e4 100644 --- a/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-session-provider.md +++ b/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/add-session-provider.md @@ -2,7 +2,7 @@ # addSessionProvider -`fun addSessionProvider(sessionManager: `[`SessionManager`](../../mozilla.components.browser.session/-session-manager/index.md)`, selectTabUseCase: `[`SelectTabUseCase`](../../mozilla.components.feature.tabs/-tabs-use-cases/-select-tab-use-case/index.md)`): `[`AwesomeBarFeature`](index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L51) +`fun addSessionProvider(sessionManager: `[`SessionManager`](../../mozilla.components.browser.session/-session-manager/index.md)`, selectTabUseCase: `[`SelectTabUseCase`](../../mozilla.components.feature.tabs/-tabs-use-cases/-select-tab-use-case/index.md)`): `[`AwesomeBarFeature`](index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L52) Add a [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) for "Open tabs" to the [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md). diff --git a/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/index.md b/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/index.md index 4b7d6d146a5..549e7dfdf93 100644 --- a/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/index.md +++ b/docs/api/mozilla.components.feature.awesomebar/-awesome-bar-feature/index.md @@ -2,7 +2,7 @@ # AwesomeBarFeature -`class AwesomeBarFeature` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L28) +`class AwesomeBarFeature` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/awesomebar/src/main/java/mozilla/components/feature/awesomebar/AwesomeBarFeature.kt#L29) Connects an [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md) with a [Toolbar](../../mozilla.components.concept.toolbar/-toolbar/index.md) and allows adding multiple [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) implementations. @@ -18,5 +18,5 @@ Connects an [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-ba |---|---| | [addClipboardProvider](add-clipboard-provider.md) | `fun addClipboardProvider(context: , loadUrlUseCase: `[`LoadUrlUseCase`](../../mozilla.components.feature.session/-session-use-cases/-load-url-use-case/index.md)`): `[`AwesomeBarFeature`](./index.md) | | [addHistoryProvider](add-history-provider.md) | `fun addHistoryProvider(historyStorage: `[`HistoryStorage`](../../mozilla.components.concept.storage/-history-storage/index.md)`, loadUrlUseCase: `[`LoadUrlUseCase`](../../mozilla.components.feature.session/-session-use-cases/-load-url-use-case/index.md)`): `[`AwesomeBarFeature`](./index.md)
    Add a [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) for browsing history to the [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md). | -| [addSearchProvider](add-search-provider.md) | `fun addSearchProvider(searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](../../mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/index.md)` = SearchSuggestionProvider.Mode.SINGLE_SUGGESTION): `[`AwesomeBarFeature`](./index.md)
    Add a [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) for search engine suggestions to the [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md). | +| [addSearchProvider](add-search-provider.md) | `fun addSearchProvider(searchEngine: `[`SearchEngine`](../../mozilla.components.browser.search/-search-engine/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](../../mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/index.md)` = SearchSuggestionProvider.Mode.SINGLE_SUGGESTION): `[`AwesomeBarFeature`](./index.md)
    Adds a [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) for search engine suggestions to the [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md).`fun addSearchProvider(context: , searchEngineManager: `[`SearchEngineManager`](../../mozilla.components.browser.search/-search-engine-manager/index.md)`, searchUseCase: `[`SearchUseCase`](../../mozilla.components.feature.search/-search-use-cases/-search-use-case/index.md)`, fetchClient: `[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`, limit: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = 15, mode: `[`Mode`](../../mozilla.components.feature.awesomebar.provider/-search-suggestion-provider/-mode/index.md)` = SearchSuggestionProvider.Mode.SINGLE_SUGGESTION): `[`AwesomeBarFeature`](./index.md)
    Adds a [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) for search engine suggestions to the [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md). If the default search engine is to be used for fetching search engine suggestions then this method is preferable over [addSearchProvider](add-search-provider.md), as it will lazily load the default search engine using the provided [SearchEngineManager](../../mozilla.components.browser.search/-search-engine-manager/index.md). | | [addSessionProvider](add-session-provider.md) | `fun addSessionProvider(sessionManager: `[`SessionManager`](../../mozilla.components.browser.session/-session-manager/index.md)`, selectTabUseCase: `[`SelectTabUseCase`](../../mozilla.components.feature.tabs/-tabs-use-cases/-select-tab-use-case/index.md)`): `[`AwesomeBarFeature`](./index.md)
    Add a [AwesomeBar.SuggestionProvider](../../mozilla.components.concept.awesomebar/-awesome-bar/-suggestion-provider/index.md) for "Open tabs" to the [AwesomeBar](../../mozilla.components.concept.awesomebar/-awesome-bar/index.md). | diff --git a/docs/api/mozilla.components.feature.media/-media-feature/enable.md b/docs/api/mozilla.components.feature.media/-media-feature/enable.md index 7d4e87d8285..92a9f3b7b50 100644 --- a/docs/api/mozilla.components.feature.media/-media-feature/enable.md +++ b/docs/api/mozilla.components.feature.media/-media-feature/enable.md @@ -2,7 +2,7 @@ # enable -`fun enable(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/media/src/main/java/mozilla/components/feature/media/MediaFeature.kt#L30) +`fun enable(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/media/src/main/java/mozilla/components/feature/media/MediaFeature.kt#L36) Enables the feature. diff --git a/docs/api/mozilla.components.feature.media/-media-feature/index.md b/docs/api/mozilla.components.feature.media/-media-feature/index.md index 085e76dd8ea..7d7ab0203c1 100644 --- a/docs/api/mozilla.components.feature.media/-media-feature/index.md +++ b/docs/api/mozilla.components.feature.media/-media-feature/index.md @@ -2,7 +2,7 @@ # MediaFeature -`class MediaFeature` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/media/src/main/java/mozilla/components/feature/media/MediaFeature.kt#L22) +`class MediaFeature` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/media/src/main/java/mozilla/components/feature/media/MediaFeature.kt#L23) Feature implementation for media playback in web content. This feature takes care of: diff --git a/docs/api/mozilla.components.feature.prompts/-prompt-feature/-f-i-l-e_-p-i-c-k-e-r_-a-c-t-i-v-i-t-y_-r-e-q-u-e-s-t_-c-o-d-e.md b/docs/api/mozilla.components.feature.prompts/-prompt-feature/-f-i-l-e_-p-i-c-k-e-r_-a-c-t-i-v-i-t-y_-r-e-q-u-e-s-t_-c-o-d-e.md index 175f1fec69b..0aef9e492d0 100644 --- a/docs/api/mozilla.components.feature.prompts/-prompt-feature/-f-i-l-e_-p-i-c-k-e-r_-a-c-t-i-v-i-t-y_-r-e-q-u-e-s-t_-c-o-d-e.md +++ b/docs/api/mozilla.components.feature.prompts/-prompt-feature/-f-i-l-e_-p-i-c-k-e-r_-a-c-t-i-v-i-t-y_-r-e-q-u-e-s-t_-c-o-d-e.md @@ -2,4 +2,4 @@ # FILE_PICKER_ACTIVITY_REQUEST_CODE -`const val FILE_PICKER_ACTIVITY_REQUEST_CODE: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L398) \ No newline at end of file +`const val FILE_PICKER_ACTIVITY_REQUEST_CODE: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L458) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.prompts/-prompt-feature/index.md b/docs/api/mozilla.components.feature.prompts/-prompt-feature/index.md index 76e1c49c5c3..64f394013c4 100644 --- a/docs/api/mozilla.components.feature.prompts/-prompt-feature/index.md +++ b/docs/api/mozilla.components.feature.prompts/-prompt-feature/index.md @@ -2,7 +2,7 @@ # PromptFeature -`class PromptFeature : `[`LifecycleAwareFeature`](../../mozilla.components.support.base.feature/-lifecycle-aware-feature/index.md)`, `[`PermissionsFeature`](../../mozilla.components.support.base.feature/-permissions-feature/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L71) +`class PromptFeature : `[`LifecycleAwareFeature`](../../mozilla.components.support.base.feature/-lifecycle-aware-feature/index.md)`, `[`PermissionsFeature`](../../mozilla.components.support.base.feature/-permissions-feature/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L72) Feature for displaying native dialogs for html elements like: input type date, file, time, color, option, menu, authentication, confirmation and alerts. diff --git a/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-activity-result.md b/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-activity-result.md index 0bdd696782f..0df830f49a2 100644 --- a/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-activity-result.md +++ b/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-activity-result.md @@ -2,7 +2,7 @@ # onActivityResult -`fun onActivityResult(requestCode: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, resultCode: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, intent: ?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L150) +`fun onActivityResult(requestCode: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, resultCode: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, intent: ?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L153) Notifies the feature of intent results for prompt requests handled by other apps like file chooser requests. diff --git a/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-need-to-request-permissions.md b/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-need-to-request-permissions.md index c13d3d612f8..c0a742758ff 100644 --- a/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-need-to-request-permissions.md +++ b/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-need-to-request-permissions.md @@ -2,7 +2,7 @@ # onNeedToRequestPermissions -`val onNeedToRequestPermissions: ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L118) +`val onNeedToRequestPermissions: ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L120) Overrides [PermissionsFeature.onNeedToRequestPermissions](../../mozilla.components.support.base.feature/-permissions-feature/on-need-to-request-permissions.md) diff --git a/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-permissions-result.md b/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-permissions-result.md index 3d0ce6f97f6..394690d714f 100644 --- a/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-permissions-result.md +++ b/docs/api/mozilla.components.feature.prompts/-prompt-feature/on-permissions-result.md @@ -2,7 +2,7 @@ # onPermissionsResult -`fun onPermissionsResult(permissions: `[`Array`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>, grantResults: `[`IntArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L162) +`fun onPermissionsResult(permissions: `[`Array`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>, grantResults: `[`IntArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L165) Overrides [PermissionsFeature.onPermissionsResult](../../mozilla.components.support.base.feature/-permissions-feature/on-permissions-result.md) diff --git a/docs/api/mozilla.components.feature.prompts/-prompt-feature/start.md b/docs/api/mozilla.components.feature.prompts/-prompt-feature/start.md index 54484e473f7..f26160eae46 100644 --- a/docs/api/mozilla.components.feature.prompts/-prompt-feature/start.md +++ b/docs/api/mozilla.components.feature.prompts/-prompt-feature/start.md @@ -2,7 +2,7 @@ # start -`fun start(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L125) +`fun start(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L127) Overrides [LifecycleAwareFeature.start](../../mozilla.components.support.base.feature/-lifecycle-aware-feature/start.md) diff --git a/docs/api/mozilla.components.feature.prompts/-prompt-feature/stop.md b/docs/api/mozilla.components.feature.prompts/-prompt-feature/stop.md index e456b06d562..ab1afc06de4 100644 --- a/docs/api/mozilla.components.feature.prompts/-prompt-feature/stop.md +++ b/docs/api/mozilla.components.feature.prompts/-prompt-feature/stop.md @@ -2,7 +2,7 @@ # stop -`fun stop(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L139) +`fun stop(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt#L142) Overrides [LifecycleAwareFeature.stop](../../mozilla.components.support.base.feature/-lifecycle-aware-feature/stop.md) diff --git a/docs/api/mozilla.components.feature.push/-auto-push-feature/force-registration-renewal.md b/docs/api/mozilla.components.feature.push/-auto-push-feature/force-registration-renewal.md index 0e3ee438789..49914d6ded1 100644 --- a/docs/api/mozilla.components.feature.push/-auto-push-feature/force-registration-renewal.md +++ b/docs/api/mozilla.components.feature.push/-auto-push-feature/force-registration-renewal.md @@ -2,8 +2,11 @@ # forceRegistrationRenewal -`fun forceRegistrationRenewal(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L235) +`fun forceRegistrationRenewal(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L245) Deletes the registration token locally so that it forces the service to get a new one the next time hits it's messaging server. +Implementation notes: This shouldn't need to be used unless we're certain. When we introduce +[a polling service](https://github.com/mozilla-mobile/android-components/issues/3173) to check if endpoints are expired, we would invoke this. + diff --git a/docs/api/mozilla.components.feature.push/-auto-push-feature/subscribe-all.md b/docs/api/mozilla.components.feature.push/-auto-push-feature/subscribe-all.md index 354ce3b89f4..1d948823283 100644 --- a/docs/api/mozilla.components.feature.push/-auto-push-feature/subscribe-all.md +++ b/docs/api/mozilla.components.feature.push/-auto-push-feature/subscribe-all.md @@ -2,7 +2,7 @@ # subscribeAll -`fun subscribeAll(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L220) +`fun subscribeAll(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L225) Returns all subscription for the push type if available. diff --git a/docs/api/mozilla.components.feature.push/-auto-push-feature/unsubscribe-for-type.md b/docs/api/mozilla.components.feature.push/-auto-push-feature/unsubscribe-for-type.md index ae109dd9173..bd4dbf9fa38 100644 --- a/docs/api/mozilla.components.feature.push/-auto-push-feature/unsubscribe-for-type.md +++ b/docs/api/mozilla.components.feature.push/-auto-push-feature/unsubscribe-for-type.md @@ -2,7 +2,10 @@ # unsubscribeForType -`fun unsubscribeForType(type: `[`PushType`](../-push-type/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L209) +`fun unsubscribeForType(type: `[`PushType`](../-push-type/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L214) Returns subscription information for the push type if available. +Implementation notes: We need to connect this to the device constellation so that we update our subscriptions +when notified by FxA. See [#3859](https://github.com/mozilla-mobile/android-components/issues/3859). + diff --git a/docs/api/mozilla.components.feature.push/-auto-push-subscription/auth-key.md b/docs/api/mozilla.components.feature.push/-auto-push-subscription/auth-key.md index 4bc45ea6741..22a44cb9eef 100644 --- a/docs/api/mozilla.components.feature.push/-auto-push-subscription/auth-key.md +++ b/docs/api/mozilla.components.feature.push/-auto-push-subscription/auth-key.md @@ -2,4 +2,4 @@ # authKey -`val authKey: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L338) \ No newline at end of file +`val authKey: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L348) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-auto-push-subscription/endpoint.md b/docs/api/mozilla.components.feature.push/-auto-push-subscription/endpoint.md index 12e70e3b62b..ee1ff5b3e98 100644 --- a/docs/api/mozilla.components.feature.push/-auto-push-subscription/endpoint.md +++ b/docs/api/mozilla.components.feature.push/-auto-push-subscription/endpoint.md @@ -2,4 +2,4 @@ # endpoint -`val endpoint: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L336) \ No newline at end of file +`val endpoint: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L346) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-auto-push-subscription/index.md b/docs/api/mozilla.components.feature.push/-auto-push-subscription/index.md index cdfba743d6d..f77c148fee6 100644 --- a/docs/api/mozilla.components.feature.push/-auto-push-subscription/index.md +++ b/docs/api/mozilla.components.feature.push/-auto-push-subscription/index.md @@ -2,7 +2,7 @@ # AutoPushSubscription -`data class AutoPushSubscription` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L334) +`data class AutoPushSubscription` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L344) The subscription information from Autopush that can be used to send push messages to other devices. diff --git a/docs/api/mozilla.components.feature.push/-auto-push-subscription/public-key.md b/docs/api/mozilla.components.feature.push/-auto-push-subscription/public-key.md index 5ee6939d1e6..1caf294b8a5 100644 --- a/docs/api/mozilla.components.feature.push/-auto-push-subscription/public-key.md +++ b/docs/api/mozilla.components.feature.push/-auto-push-subscription/public-key.md @@ -2,4 +2,4 @@ # publicKey -`val publicKey: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L337) \ No newline at end of file +`val publicKey: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L347) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-auto-push-subscription/type.md b/docs/api/mozilla.components.feature.push/-auto-push-subscription/type.md index 690ee401e7c..f66f581ca45 100644 --- a/docs/api/mozilla.components.feature.push/-auto-push-subscription/type.md +++ b/docs/api/mozilla.components.feature.push/-auto-push-subscription/type.md @@ -2,4 +2,4 @@ # type -`val type: `[`PushType`](../-push-type/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L335) \ No newline at end of file +`val type: `[`PushType`](../-push-type/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L345) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-protocol/-h-t-t-p-s.md b/docs/api/mozilla.components.feature.push/-protocol/-h-t-t-p-s.md index a42d361aa25..d0ab711e02d 100644 --- a/docs/api/mozilla.components.feature.push/-protocol/-h-t-t-p-s.md +++ b/docs/api/mozilla.components.feature.push/-protocol/-h-t-t-p-s.md @@ -2,4 +2,4 @@ # HTTPS -`HTTPS` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L328) \ No newline at end of file +`HTTPS` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L338) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-protocol/-h-t-t-p.md b/docs/api/mozilla.components.feature.push/-protocol/-h-t-t-p.md index a9652239d60..4b4ef78da7f 100644 --- a/docs/api/mozilla.components.feature.push/-protocol/-h-t-t-p.md +++ b/docs/api/mozilla.components.feature.push/-protocol/-h-t-t-p.md @@ -2,4 +2,4 @@ # HTTP -`HTTP` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L327) \ No newline at end of file +`HTTP` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L337) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-protocol/index.md b/docs/api/mozilla.components.feature.push/-protocol/index.md index 1df0433ba47..9db7a2f3619 100644 --- a/docs/api/mozilla.components.feature.push/-protocol/index.md +++ b/docs/api/mozilla.components.feature.push/-protocol/index.md @@ -2,7 +2,7 @@ # Protocol -`enum class Protocol` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L326) +`enum class Protocol` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L336) Supported network protocols. diff --git a/docs/api/mozilla.components.feature.push/-push-config/index.md b/docs/api/mozilla.components.feature.push/-push-config/index.md index cb8b49f393a..a4560b79ae2 100644 --- a/docs/api/mozilla.components.feature.push/-push-config/index.md +++ b/docs/api/mozilla.components.feature.push/-push-config/index.md @@ -2,7 +2,7 @@ # PushConfig -`data class PushConfig` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L344) +`data class PushConfig` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L354) Configuration object for initializing the Push Manager. diff --git a/docs/api/mozilla.components.feature.push/-push-config/protocol.md b/docs/api/mozilla.components.feature.push/-push-config/protocol.md index e725b20f2e5..af6a8d2347a 100644 --- a/docs/api/mozilla.components.feature.push/-push-config/protocol.md +++ b/docs/api/mozilla.components.feature.push/-push-config/protocol.md @@ -2,4 +2,4 @@ # protocol -`val protocol: `[`Protocol`](../-protocol/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L347) \ No newline at end of file +`val protocol: `[`Protocol`](../-protocol/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L357) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-push-config/sender-id.md b/docs/api/mozilla.components.feature.push/-push-config/sender-id.md index 60c51318374..411c63d4ac2 100644 --- a/docs/api/mozilla.components.feature.push/-push-config/sender-id.md +++ b/docs/api/mozilla.components.feature.push/-push-config/sender-id.md @@ -2,4 +2,4 @@ # senderId -`val senderId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L345) \ No newline at end of file +`val senderId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L355) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-push-config/server-host.md b/docs/api/mozilla.components.feature.push/-push-config/server-host.md index 94c40aa1591..dec7c626588 100644 --- a/docs/api/mozilla.components.feature.push/-push-config/server-host.md +++ b/docs/api/mozilla.components.feature.push/-push-config/server-host.md @@ -2,4 +2,4 @@ # serverHost -`val serverHost: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L346) \ No newline at end of file +`val serverHost: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L356) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-push-config/service-type.md b/docs/api/mozilla.components.feature.push/-push-config/service-type.md index dd63988fd35..9b43296bbc7 100644 --- a/docs/api/mozilla.components.feature.push/-push-config/service-type.md +++ b/docs/api/mozilla.components.feature.push/-push-config/service-type.md @@ -2,4 +2,4 @@ # serviceType -`val serviceType: `[`ServiceType`](../-service-type/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L348) \ No newline at end of file +`val serviceType: `[`ServiceType`](../-service-type/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L358) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-push-subscription-observer/index.md b/docs/api/mozilla.components.feature.push/-push-subscription-observer/index.md index ca7f161d68f..e33159d3a70 100644 --- a/docs/api/mozilla.components.feature.push/-push-subscription-observer/index.md +++ b/docs/api/mozilla.components.feature.push/-push-subscription-observer/index.md @@ -2,7 +2,7 @@ # PushSubscriptionObserver -`interface PushSubscriptionObserver` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L292) +`interface PushSubscriptionObserver` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L302) Observers that want to receive updates for new subscriptions. diff --git a/docs/api/mozilla.components.feature.push/-push-subscription-observer/on-subscription-available.md b/docs/api/mozilla.components.feature.push/-push-subscription-observer/on-subscription-available.md index 1e5930fa5a3..2335364acb9 100644 --- a/docs/api/mozilla.components.feature.push/-push-subscription-observer/on-subscription-available.md +++ b/docs/api/mozilla.components.feature.push/-push-subscription-observer/on-subscription-available.md @@ -2,4 +2,4 @@ # onSubscriptionAvailable -`abstract fun onSubscriptionAvailable(subscription: `[`AutoPushSubscription`](../-auto-push-subscription/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L293) \ No newline at end of file +`abstract fun onSubscriptionAvailable(subscription: `[`AutoPushSubscription`](../-auto-push-subscription/index.md)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L303) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-push-type/-services.md b/docs/api/mozilla.components.feature.push/-push-type/-services.md index cf804a2b3f0..64a7b364f73 100644 --- a/docs/api/mozilla.components.feature.push/-push-type/-services.md +++ b/docs/api/mozilla.components.feature.push/-push-type/-services.md @@ -2,7 +2,7 @@ # Services -`Services` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L278) +`Services` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L288) ### Inherited Functions diff --git a/docs/api/mozilla.components.feature.push/-push-type/-web-push.md b/docs/api/mozilla.components.feature.push/-push-type/-web-push.md index e5ecead06de..174b55c429b 100644 --- a/docs/api/mozilla.components.feature.push/-push-type/-web-push.md +++ b/docs/api/mozilla.components.feature.push/-push-type/-web-push.md @@ -2,7 +2,7 @@ # WebPush -`WebPush` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L279) +`WebPush` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L289) ### Inherited Functions diff --git a/docs/api/mozilla.components.feature.push/-push-type/index.md b/docs/api/mozilla.components.feature.push/-push-type/index.md index e22149ce40a..9da70acd462 100644 --- a/docs/api/mozilla.components.feature.push/-push-type/index.md +++ b/docs/api/mozilla.components.feature.push/-push-type/index.md @@ -2,7 +2,7 @@ # PushType -`enum class PushType` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L277) +`enum class PushType` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L287) The different kind of message types that a [EncryptedPushMessage](../../mozilla.components.concept.push/-encrypted-push-message/index.md) can be: diff --git a/docs/api/mozilla.components.feature.push/-push-type/to-channel-id.md b/docs/api/mozilla.components.feature.push/-push-type/to-channel-id.md index 051fd12d749..11d9ac8f4e0 100644 --- a/docs/api/mozilla.components.feature.push/-push-type/to-channel-id.md +++ b/docs/api/mozilla.components.feature.push/-push-type/to-channel-id.md @@ -2,7 +2,7 @@ # toChannelId -`fun toChannelId(): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L286) +`fun toChannelId(): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L296) Retrieve a channel ID from the PushType. diff --git a/docs/api/mozilla.components.feature.push/-service-type/-a-d-m.md b/docs/api/mozilla.components.feature.push/-service-type/-a-d-m.md index 159b38cc011..50a4bf8dbcc 100644 --- a/docs/api/mozilla.components.feature.push/-service-type/-a-d-m.md +++ b/docs/api/mozilla.components.feature.push/-service-type/-a-d-m.md @@ -2,4 +2,4 @@ # ADM -`ADM` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L320) \ No newline at end of file +`ADM` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L330) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-service-type/-f-c-m.md b/docs/api/mozilla.components.feature.push/-service-type/-f-c-m.md index 90d38f61478..6d46fde740c 100644 --- a/docs/api/mozilla.components.feature.push/-service-type/-f-c-m.md +++ b/docs/api/mozilla.components.feature.push/-service-type/-f-c-m.md @@ -2,4 +2,4 @@ # FCM -`FCM` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L319) \ No newline at end of file +`FCM` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L329) \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.push/-service-type/index.md b/docs/api/mozilla.components.feature.push/-service-type/index.md index 416f620f85b..c4f34ad80d6 100644 --- a/docs/api/mozilla.components.feature.push/-service-type/index.md +++ b/docs/api/mozilla.components.feature.push/-service-type/index.md @@ -2,7 +2,7 @@ # ServiceType -`enum class ServiceType` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L318) +`enum class ServiceType` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt#L328) Supported push services. diff --git a/docs/api/mozilla.components.feature.sendtab/-send-tab-feature/-init-.md b/docs/api/mozilla.components.feature.sendtab/-send-tab-feature/-init-.md new file mode 100644 index 00000000000..a307c34c756 --- /dev/null +++ b/docs/api/mozilla.components.feature.sendtab/-send-tab-feature/-init-.md @@ -0,0 +1,25 @@ +[android-components](../../index.md) / [mozilla.components.feature.sendtab](../index.md) / [SendTabFeature](index.md) / [<init>](./-init-.md) + +# <init> + +`SendTabFeature(accountManager: `[`FxaAccountManager`](../../mozilla.components.service.fxa.manager/-fxa-account-manager/index.md)`, pushFeature: `[`AutoPushFeature`](../../mozilla.components.feature.push/-auto-push-feature/index.md)`? = null, owner: LifecycleOwner = ProcessLifecycleOwner.get(), autoPause: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)` = false, onTabsReceived: (`[`Device`](../../mozilla.components.concept.sync/-device/index.md)`?, `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`TabData`](../../mozilla.components.concept.sync/-tab-data/index.md)`>) -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`)` + +A feature that uses the [FxaAccountManager](../../mozilla.components.service.fxa.manager/-fxa-account-manager/index.md) to send and receive tabs with optional push support +for receiving tabs from the [AutoPushFeature](../../mozilla.components.feature.push/-auto-push-feature/index.md) and a [PushService](../../mozilla.components.concept.push/-push-service/index.md). + +If the push components are not used, the feature can still function while tabs would only be +received when refreshing the device state. + +### Parameters + +`accountManager` - Firefox account manager. + +`pushFeature` - The [AutoPushFeature](../../mozilla.components.feature.push/-auto-push-feature/index.md) if that is setup for observing push events. + +`owner` - Android lifecycle owner for the observers. Defaults to the [ProcessLifecycleOwner](#) +so that we can always observe events throughout the application lifecycle. + +`autoPause` - whether or not the observer should automatically be +paused/resumed with the bound lifecycle. + +`onTabsReceived` - the callback invoked with new tab(s) are received. \ No newline at end of file diff --git a/docs/api/mozilla.components.feature.sendtab/-send-tab-feature/index.md b/docs/api/mozilla.components.feature.sendtab/-send-tab-feature/index.md new file mode 100644 index 00000000000..17a00dcf838 --- /dev/null +++ b/docs/api/mozilla.components.feature.sendtab/-send-tab-feature/index.md @@ -0,0 +1,31 @@ +[android-components](../../index.md) / [mozilla.components.feature.sendtab](../index.md) / [SendTabFeature](./index.md) + +# SendTabFeature + +`class SendTabFeature` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/feature/sendtab/src/main/java/mozilla/components/feature/sendtab/SendTabFeature.kt#L43) + +A feature that uses the [FxaAccountManager](../../mozilla.components.service.fxa.manager/-fxa-account-manager/index.md) to send and receive tabs with optional push support +for receiving tabs from the [AutoPushFeature](../../mozilla.components.feature.push/-auto-push-feature/index.md) and a [PushService](../../mozilla.components.concept.push/-push-service/index.md). + +If the push components are not used, the feature can still function while tabs would only be +received when refreshing the device state. + +### Parameters + +`accountManager` - Firefox account manager. + +`pushFeature` - The [AutoPushFeature](../../mozilla.components.feature.push/-auto-push-feature/index.md) if that is setup for observing push events. + +`owner` - Android lifecycle owner for the observers. Defaults to the [ProcessLifecycleOwner](#) +so that we can always observe events throughout the application lifecycle. + +`autoPause` - whether or not the observer should automatically be +paused/resumed with the bound lifecycle. + +`onTabsReceived` - the callback invoked with new tab(s) are received. + +### Constructors + +| Name | Summary | +|---|---| +| [<init>](-init-.md) | `SendTabFeature(accountManager: `[`FxaAccountManager`](../../mozilla.components.service.fxa.manager/-fxa-account-manager/index.md)`, pushFeature: `[`AutoPushFeature`](../../mozilla.components.feature.push/-auto-push-feature/index.md)`? = null, owner: LifecycleOwner = ProcessLifecycleOwner.get(), autoPause: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)` = false, onTabsReceived: (`[`Device`](../../mozilla.components.concept.sync/-device/index.md)`?, `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`TabData`](../../mozilla.components.concept.sync/-tab-data/index.md)`>) -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`)`
    A feature that uses the [FxaAccountManager](../../mozilla.components.service.fxa.manager/-fxa-account-manager/index.md) to send and receive tabs with optional push support for receiving tabs from the [AutoPushFeature](../../mozilla.components.feature.push/-auto-push-feature/index.md) and a [PushService](../../mozilla.components.concept.push/-push-service/index.md). | diff --git a/docs/api/mozilla.components.feature.sendtab/index.md b/docs/api/mozilla.components.feature.sendtab/index.md index 710f5a16229..30563b6c00c 100644 --- a/docs/api/mozilla.components.feature.sendtab/index.md +++ b/docs/api/mozilla.components.feature.sendtab/index.md @@ -6,4 +6,5 @@ | Name | Summary | |---|---| +| [SendTabFeature](-send-tab-feature/index.md) | `class SendTabFeature`
    A feature that uses the [FxaAccountManager](../mozilla.components.service.fxa.manager/-fxa-account-manager/index.md) to send and receive tabs with optional push support for receiving tabs from the [AutoPushFeature](../mozilla.components.feature.push/-auto-push-feature/index.md) and a [PushService](../mozilla.components.concept.push/-push-service/index.md). | | [SendTabUseCases](-send-tab-use-cases/index.md) | `class SendTabUseCases`
    Contains use cases for sending tabs to devices related to the firefox-accounts. | diff --git a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-init-.md b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-init-.md index c218bef1fa9..1379839dc29 100644 --- a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-init-.md +++ b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-init-.md @@ -2,4 +2,19 @@ # <init> -`ExperimentsDebugActivity()` \ No newline at end of file +`ExperimentsDebugActivity()` + +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 + diff --git a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-b-r-a-n-c-h_-e-x-t-r-a_-k-e-y.md b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-b-r-a-n-c-h_-e-x-t-r-a_-k-e-y.md index f751a02f584..5fb7b11bc84 100644 --- a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-b-r-a-n-c-h_-e-x-t-r-a_-k-e-y.md +++ b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-b-r-a-n-c-h_-e-x-t-r-a_-k-e-y.md @@ -2,4 +2,7 @@ # OVERRIDE_BRANCH_EXTRA_KEY -`const val OVERRIDE_BRANCH_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L37) \ No newline at end of file +`const val OVERRIDE_BRANCH_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L63) + +Used only with [OVERRIDE_EXPERIMENT_EXTRA_KEY](-o-v-e-r-r-i-d-e_-e-x-p-e-r-i-m-e-n-t_-e-x-t-r-a_-k-e-y.md). + diff --git a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-c-l-e-a-r_-a-l-l_-e-x-t-r-a_-k-e-y.md b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-c-l-e-a-r_-a-l-l_-e-x-t-r-a_-k-e-y.md index d385d4188db..d20b72c0412 100644 --- a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-c-l-e-a-r_-a-l-l_-e-x-t-r-a_-k-e-y.md +++ b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-c-l-e-a-r_-a-l-l_-e-x-t-r-a_-k-e-y.md @@ -2,4 +2,7 @@ # OVERRIDE_CLEAR_ALL_EXTRA_KEY -`const val OVERRIDE_CLEAR_ALL_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L38) \ No newline at end of file +`const val OVERRIDE_CLEAR_ALL_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L67) + +Clears any existing overrides. + diff --git a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-e-x-p-e-r-i-m-e-n-t_-e-x-t-r-a_-k-e-y.md b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-e-x-p-e-r-i-m-e-n-t_-e-x-t-r-a_-k-e-y.md index 15a9e8ba176..b0b1c3b8cb2 100644 --- a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-e-x-p-e-r-i-m-e-n-t_-e-x-t-r-a_-k-e-y.md +++ b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-o-v-e-r-r-i-d-e_-e-x-p-e-r-i-m-e-n-t_-e-x-t-r-a_-k-e-y.md @@ -2,4 +2,9 @@ # OVERRIDE_EXPERIMENT_EXTRA_KEY -`const val OVERRIDE_EXPERIMENT_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L36) \ No newline at end of file +`const val OVERRIDE_EXPERIMENT_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L59) + +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. + diff --git a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-s-e-t_-k-i-n-t-o_-i-n-s-t-a-n-c-e_-e-x-t-r-a_-k-e-y.md b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-s-e-t_-k-i-n-t-o_-i-n-s-t-a-n-c-e_-e-x-t-r-a_-k-e-y.md index 1b517ec1460..8386fdf3e6a 100644 --- a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-s-e-t_-k-i-n-t-o_-i-n-s-t-a-n-c-e_-e-x-t-r-a_-k-e-y.md +++ b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-s-e-t_-k-i-n-t-o_-i-n-s-t-a-n-c-e_-e-x-t-r-a_-k-e-y.md @@ -2,4 +2,8 @@ # SET_KINTO_INSTANCE_EXTRA_KEY -`const val SET_KINTO_INSTANCE_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L32) \ No newline at end of file +`const val SET_KINTO_INSTANCE_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L53) + +Sets the Kinto endpoint to the supplied endpoint. +Must be one of: `dev`, `staging`, or `prod`. + diff --git a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-u-p-d-a-t-e_-e-x-p-e-r-i-m-e-n-t-s_-e-x-t-r-a_-k-e-y.md b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-u-p-d-a-t-e_-e-x-p-e-r-i-m-e-n-t-s_-e-x-t-r-a_-k-e-y.md index f375ccbbe0c..406f1d4e7ac 100644 --- a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-u-p-d-a-t-e_-e-x-p-e-r-i-m-e-n-t-s_-e-x-t-r-a_-k-e-y.md +++ b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/-u-p-d-a-t-e_-e-x-p-e-r-i-m-e-n-t-s_-e-x-t-r-a_-k-e-y.md @@ -2,4 +2,7 @@ # UPDATE_EXPERIMENTS_EXTRA_KEY -`const val UPDATE_EXPERIMENTS_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L31) \ No newline at end of file +`const val UPDATE_EXPERIMENTS_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L48) + +Fetch experiments from the server and update the active experiment if necessary. + diff --git a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/index.md b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/index.md index 91e3c1c998c..82ce8f98630 100644 --- a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/index.md +++ b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/index.md @@ -2,26 +2,40 @@ # ExperimentsDebugActivity -`class ExperimentsDebugActivity` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L19) +`class ExperimentsDebugActivity` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L33) + +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 ### Constructors | Name | Summary | |---|---| -| [<init>](-init-.md) | `ExperimentsDebugActivity()` | +| [<init>](-init-.md) | `ExperimentsDebugActivity()`
    Debugging activity exported by service-experiments to allow easier debugging. This accepts commands that can force the library to do the following: | ### Functions | Name | Summary | |---|---| -| [onCreate](on-create.md) | `fun onCreate(savedInstanceState: ?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) | +| [onCreate](on-create.md) | `fun onCreate(savedInstanceState: ?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
    On creation of the debug activity, process the command switches | ### Companion Object Properties | Name | Summary | |---|---| -| [OVERRIDE_BRANCH_EXTRA_KEY](-o-v-e-r-r-i-d-e_-b-r-a-n-c-h_-e-x-t-r-a_-k-e-y.md) | `const val OVERRIDE_BRANCH_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | -| [OVERRIDE_CLEAR_ALL_EXTRA_KEY](-o-v-e-r-r-i-d-e_-c-l-e-a-r_-a-l-l_-e-x-t-r-a_-k-e-y.md) | `const val OVERRIDE_CLEAR_ALL_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | -| [OVERRIDE_EXPERIMENT_EXTRA_KEY](-o-v-e-r-r-i-d-e_-e-x-p-e-r-i-m-e-n-t_-e-x-t-r-a_-k-e-y.md) | `const val OVERRIDE_EXPERIMENT_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | -| [SET_KINTO_INSTANCE_EXTRA_KEY](-s-e-t_-k-i-n-t-o_-i-n-s-t-a-n-c-e_-e-x-t-r-a_-k-e-y.md) | `const val SET_KINTO_INSTANCE_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | -| [UPDATE_EXPERIMENTS_EXTRA_KEY](-u-p-d-a-t-e_-e-x-p-e-r-i-m-e-n-t-s_-e-x-t-r-a_-k-e-y.md) | `const val UPDATE_EXPERIMENTS_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | +| [OVERRIDE_BRANCH_EXTRA_KEY](-o-v-e-r-r-i-d-e_-b-r-a-n-c-h_-e-x-t-r-a_-k-e-y.md) | `const val OVERRIDE_BRANCH_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
    Used only with [OVERRIDE_EXPERIMENT_EXTRA_KEY](-o-v-e-r-r-i-d-e_-e-x-p-e-r-i-m-e-n-t_-e-x-t-r-a_-k-e-y.md). | +| [OVERRIDE_CLEAR_ALL_EXTRA_KEY](-o-v-e-r-r-i-d-e_-c-l-e-a-r_-a-l-l_-e-x-t-r-a_-k-e-y.md) | `const val OVERRIDE_CLEAR_ALL_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
    Clears any existing overrides. | +| [OVERRIDE_EXPERIMENT_EXTRA_KEY](-o-v-e-r-r-i-d-e_-e-x-p-e-r-i-m-e-n-t_-e-x-t-r-a_-k-e-y.md) | `const val OVERRIDE_EXPERIMENT_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
    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. | +| [SET_KINTO_INSTANCE_EXTRA_KEY](-s-e-t_-k-i-n-t-o_-i-n-s-t-a-n-c-e_-e-x-t-r-a_-k-e-y.md) | `const val SET_KINTO_INSTANCE_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
    Sets the Kinto endpoint to the supplied endpoint. Must be one of: `dev`, `staging`, or `prod`. | +| [UPDATE_EXPERIMENTS_EXTRA_KEY](-u-p-d-a-t-e_-e-x-p-e-r-i-m-e-n-t-s_-e-x-t-r-a_-k-e-y.md) | `const val UPDATE_EXPERIMENTS_EXTRA_KEY: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
    Fetch experiments from the server and update the active experiment if necessary. | diff --git a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/on-create.md b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/on-create.md index cfbc441e483..8461b6271e0 100644 --- a/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/on-create.md +++ b/docs/api/mozilla.components.service.experiments.debug/-experiments-debug-activity/on-create.md @@ -2,4 +2,7 @@ # onCreate -`fun onCreate(savedInstanceState: ?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L42) \ No newline at end of file +`fun onCreate(savedInstanceState: ?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/debug/ExperimentsDebugActivity.kt#L74) + +On creation of the debug activity, process the command switches + diff --git a/docs/api/mozilla.components.service.experiments.debug/index.md b/docs/api/mozilla.components.service.experiments.debug/index.md index c79cbff4b9b..6be7f891985 100644 --- a/docs/api/mozilla.components.service.experiments.debug/index.md +++ b/docs/api/mozilla.components.service.experiments.debug/index.md @@ -6,4 +6,4 @@ | Name | Summary | |---|---| -| [ExperimentsDebugActivity](-experiments-debug-activity/index.md) | `class ExperimentsDebugActivity` | +| [ExperimentsDebugActivity](-experiments-debug-activity/index.md) | `class ExperimentsDebugActivity`
    Debugging activity exported by service-experiments to allow easier debugging. This accepts commands that can force the library to do the following: | diff --git a/docs/api/mozilla.components.service.experiments/-configuration/http-client.md b/docs/api/mozilla.components.service.experiments/-configuration/http-client.md index 6d9b11f2e50..c38d05c81e3 100644 --- a/docs/api/mozilla.components.service.experiments/-configuration/http-client.md +++ b/docs/api/mozilla.components.service.experiments/-configuration/http-client.md @@ -2,7 +2,7 @@ # httpClient -`val httpClient: `[`Lazy`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-lazy/index.html)`<`[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Configuration.kt#L16) +`val httpClient: `[`Lazy`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-lazy/index.html)`<`[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Configuration.kt#L19) The HTTP client implementation to use for uploading pings. diff --git a/docs/api/mozilla.components.service.experiments/-configuration/index.md b/docs/api/mozilla.components.service.experiments/-configuration/index.md index 772f32a40db..edadcee61dd 100644 --- a/docs/api/mozilla.components.service.experiments/-configuration/index.md +++ b/docs/api/mozilla.components.service.experiments/-configuration/index.md @@ -2,7 +2,7 @@ # Configuration -`data class Configuration` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Configuration.kt#L15) +`data class Configuration` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Configuration.kt#L18) The Configuration class describes how to configure Experiments. @@ -17,4 +17,4 @@ The Configuration class describes how to configure Experiments. | Name | Summary | |---|---| | [httpClient](http-client.md) | `val httpClient: `[`Lazy`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-lazy/index.html)`<`[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`>`
    The HTTP client implementation to use for uploading pings. | -| [kintoEndpoint](kinto-endpoint.md) | `val kintoEndpoint: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | +| [kintoEndpoint](kinto-endpoint.md) | `val kintoEndpoint: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
    the endpoint to fetch experiments from, must be one of: [ExperimentsUpdater.KINTO_ENDPOINT_DEV](#), [ExperimentsUpdater.KINTO_ENDPOINT_STAGING](#), or [ExperimentsUpdater.KINTO_ENDPOINT_PROD](#) | diff --git a/docs/api/mozilla.components.service.experiments/-configuration/kinto-endpoint.md b/docs/api/mozilla.components.service.experiments/-configuration/kinto-endpoint.md index d663b13ece8..01c8d4de4f4 100644 --- a/docs/api/mozilla.components.service.experiments/-configuration/kinto-endpoint.md +++ b/docs/api/mozilla.components.service.experiments/-configuration/kinto-endpoint.md @@ -2,4 +2,14 @@ # kintoEndpoint -`val kintoEndpoint: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Configuration.kt#L17) \ No newline at end of file +`val kintoEndpoint: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Configuration.kt#L20) + +the endpoint to fetch experiments from, must be one of: +[ExperimentsUpdater.KINTO_ENDPOINT_DEV](#), [ExperimentsUpdater.KINTO_ENDPOINT_STAGING](#), or +[ExperimentsUpdater.KINTO_ENDPOINT_PROD](#) + +### 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](#) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/index.md b/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/index.md index f70b93bed99..5e6dafeaad1 100644 --- a/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/index.md +++ b/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/index.md @@ -4,7 +4,7 @@ `open class ExperimentsInternalAPI` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt#L18) -Entry point of the library. +This is the main experiments API, which is exposed through the global [Experiments](../-experiments.md) object. ### Functions @@ -17,4 +17,4 @@ Entry point of the library. | Name | Summary | |---|---| -| [Experiments](../-experiments.md) | `object Experiments : `[`ExperimentsInternalAPI`](./index.md) | +| [Experiments](../-experiments.md) | `object Experiments : `[`ExperimentsInternalAPI`](./index.md)
    The main Experiments object. | diff --git a/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/initialize.md b/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/initialize.md index 534c3e2c8fd..00a9471efdf 100644 --- a/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/initialize.md +++ b/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/initialize.md @@ -2,7 +2,7 @@ # initialize -`fun initialize(applicationContext: , configuration: `[`Configuration`](../-configuration/index.md)` = Configuration()): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt#L55) +`fun initialize(applicationContext: , configuration: `[`Configuration`](../-configuration/index.md)` = Configuration()): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt#L57) Initialize the experiments library. @@ -13,4 +13,6 @@ This should only be initialized once by the application. `applicationContext` - [Context](#) to access application features, such 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. \ No newline at end of file +if the initializing application doesn't comply. + +`configuration` - [Configuration](../-configuration/index.md) containing information about the experiments endpoint. \ No newline at end of file diff --git a/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/with-experiment.md b/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/with-experiment.md index 18a2096b677..719b7291839 100644 --- a/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/with-experiment.md +++ b/docs/api/mozilla.components.service.experiments/-experiments-internal-a-p-i/with-experiment.md @@ -2,7 +2,7 @@ # withExperiment -`fun withExperiment(experimentId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, block: (branch: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`) -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt#L227) +`fun withExperiment(experimentId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, block: (branch: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`) -> `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt#L248) Performs an action if the user is part of the specified experiment diff --git a/docs/api/mozilla.components.service.experiments/-experiments.md b/docs/api/mozilla.components.service.experiments/-experiments.md index 25e03bef58c..c55dc78d4d2 100644 --- a/docs/api/mozilla.components.service.experiments/-experiments.md +++ b/docs/api/mozilla.components.service.experiments/-experiments.md @@ -2,7 +2,17 @@ # Experiments -`object Experiments : `[`ExperimentsInternalAPI`](-experiments-internal-a-p-i/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt#L364) +`object Experiments : `[`ExperimentsInternalAPI`](-experiments-internal-a-p-i/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/experiments/src/main/java/mozilla/components/service/experiments/Experiments.kt#L399) + +The main Experiments object. + +This is a global object that must be initialized by the application by calling the [initialize](-experiments-internal-a-p-i/initialize.md) +function before the experiments library can fetch updates from the server or be used to determine +experiment enrollment. + +``` +Experiments.initialize(applicationContext) +``` ### Inherited Functions diff --git a/docs/api/mozilla.components.service.experiments/index.md b/docs/api/mozilla.components.service.experiments/index.md index 25bcb4d634c..2a22a7b40b9 100644 --- a/docs/api/mozilla.components.service.experiments/index.md +++ b/docs/api/mozilla.components.service.experiments/index.md @@ -7,5 +7,5 @@ | Name | Summary | |---|---| | [Configuration](-configuration/index.md) | `data class Configuration`
    The Configuration class describes how to configure Experiments. | -| [Experiments](-experiments.md) | `object Experiments : `[`ExperimentsInternalAPI`](-experiments-internal-a-p-i/index.md) | -| [ExperimentsInternalAPI](-experiments-internal-a-p-i/index.md) | `open class ExperimentsInternalAPI`
    Entry point of the library. | +| [Experiments](-experiments.md) | `object Experiments : `[`ExperimentsInternalAPI`](-experiments-internal-a-p-i/index.md)
    The main Experiments object. | +| [ExperimentsInternalAPI](-experiments-internal-a-p-i/index.md) | `open class ExperimentsInternalAPI`
    This is the main experiments API, which is exposed through the global [Experiments](-experiments.md) object. | diff --git a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-c-o-n-n-e-c-t-i-o-n_-t-i-m-e-o-u-t.md b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-c-o-n-n-e-c-t-i-o-n_-t-i-m-e-o-u-t.md index bb3875988b1..82d6822ee87 100644 --- a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-c-o-n-n-e-c-t-i-o-n_-t-i-m-e-o-u-t.md +++ b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-c-o-n-n-e-c-t-i-o-n_-t-i-m-e-o-u-t.md @@ -2,4 +2,4 @@ # DEFAULT_CONNECTION_TIMEOUT -`const val DEFAULT_CONNECTION_TIMEOUT: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L69) \ No newline at end of file +`const val DEFAULT_CONNECTION_TIMEOUT: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L70) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-l-o-g_-p-i-n-g-s.md b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-l-o-g_-p-i-n-g-s.md index bda9de6a625..0f0ba82c8c1 100644 --- a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-l-o-g_-p-i-n-g-s.md +++ b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-l-o-g_-p-i-n-g-s.md @@ -2,4 +2,4 @@ # DEFAULT_LOG_PINGS -`const val DEFAULT_LOG_PINGS: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L72) \ No newline at end of file +`const val DEFAULT_LOG_PINGS: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L73) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-m-a-x_-e-v-e-n-t-s.md b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-m-a-x_-e-v-e-n-t-s.md index 8c77755717e..5388864a37d 100644 --- a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-m-a-x_-e-v-e-n-t-s.md +++ b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-m-a-x_-e-v-e-n-t-s.md @@ -2,4 +2,4 @@ # DEFAULT_MAX_EVENTS -`const val DEFAULT_MAX_EVENTS: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L71) \ No newline at end of file +`const val DEFAULT_MAX_EVENTS: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L72) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-r-e-a-d_-t-i-m-e-o-u-t.md b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-r-e-a-d_-t-i-m-e-o-u-t.md index 96a2ca7d047..7df824bdf2c 100644 --- a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-r-e-a-d_-t-i-m-e-o-u-t.md +++ b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-r-e-a-d_-t-i-m-e-o-u-t.md @@ -2,4 +2,4 @@ # DEFAULT_READ_TIMEOUT -`const val DEFAULT_READ_TIMEOUT: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L70) \ No newline at end of file +`const val DEFAULT_READ_TIMEOUT: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L71) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-t-e-l-e-m-e-t-r-y_-e-n-d-p-o-i-n-t.md b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-t-e-l-e-m-e-t-r-y_-e-n-d-p-o-i-n-t.md index b3618853f75..2a294cd04ec 100644 --- a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-t-e-l-e-m-e-t-r-y_-e-n-d-p-o-i-n-t.md +++ b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-t-e-l-e-m-e-t-r-y_-e-n-d-p-o-i-n-t.md @@ -2,4 +2,4 @@ # DEFAULT_TELEMETRY_ENDPOINT -`const val DEFAULT_TELEMETRY_ENDPOINT: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L67) \ No newline at end of file +`const val DEFAULT_TELEMETRY_ENDPOINT: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L68) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-u-s-e-r_-a-g-e-n-t.md b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-u-s-e-r_-a-g-e-n-t.md index 72e030101b8..f4daf7e2a55 100644 --- a/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-u-s-e-r_-a-g-e-n-t.md +++ b/docs/api/mozilla.components.service.glean.config/-configuration/-d-e-f-a-u-l-t_-u-s-e-r_-a-g-e-n-t.md @@ -2,4 +2,4 @@ # DEFAULT_USER_AGENT -`const val DEFAULT_USER_AGENT: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L68) \ No newline at end of file +`const val DEFAULT_USER_AGENT: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt#L69) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.config/-configuration/-init-.md b/docs/api/mozilla.components.service.glean.config/-configuration/-init-.md index c1ffd658b85..8a44e8d1698 100644 --- a/docs/api/mozilla.components.service.glean.config/-configuration/-init-.md +++ b/docs/api/mozilla.components.service.glean.config/-configuration/-init-.md @@ -2,4 +2,4 @@ # <init> -`Configuration(connectionTimeout: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_CONNECTION_TIMEOUT, readTimeout: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_READ_TIMEOUT, maxEvents: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = DEFAULT_MAX_EVENTS, httpClient: `[`Lazy`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-lazy/index.html)`<`[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`> = lazy { HttpURLConnectionClient() }, channel: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`? = null)` \ No newline at end of file +`Configuration(serverEndpoint: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = DEFAULT_TELEMETRY_ENDPOINT, connectionTimeout: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_CONNECTION_TIMEOUT, readTimeout: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_READ_TIMEOUT, maxEvents: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = DEFAULT_MAX_EVENTS, httpClient: `[`Lazy`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-lazy/index.html)`<`[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`> = lazy { HttpURLConnectionClient() }, channel: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`? = null)` \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.config/-configuration/index.md b/docs/api/mozilla.components.service.glean.config/-configuration/index.md index 380dc6ccdd0..f0ba2efc901 100644 --- a/docs/api/mozilla.components.service.glean.config/-configuration/index.md +++ b/docs/api/mozilla.components.service.glean.config/-configuration/index.md @@ -10,7 +10,7 @@ The Configuration class describes how to configure the Glean. | Name | Summary | |---|---| -| [<init>](-init-.md) | `Configuration(connectionTimeout: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_CONNECTION_TIMEOUT, readTimeout: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_READ_TIMEOUT, maxEvents: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = DEFAULT_MAX_EVENTS, httpClient: `[`Lazy`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-lazy/index.html)`<`[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`> = lazy { HttpURLConnectionClient() }, channel: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`? = null)` | +| [<init>](-init-.md) | `Configuration(serverEndpoint: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = DEFAULT_TELEMETRY_ENDPOINT, connectionTimeout: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_CONNECTION_TIMEOUT, readTimeout: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_READ_TIMEOUT, maxEvents: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = DEFAULT_MAX_EVENTS, httpClient: `[`Lazy`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-lazy/index.html)`<`[`Client`](../../mozilla.components.concept.fetch/-client/index.md)`> = lazy { HttpURLConnectionClient() }, channel: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`? = null)` | ### Properties diff --git a/docs/api/mozilla.components.service.glean.private/-common-metric-data/index.md b/docs/api/mozilla.components.service.glean.private/-common-metric-data/index.md index 1d996fb8e22..2946a2817ca 100644 --- a/docs/api/mozilla.components.service.glean.private/-common-metric-data/index.md +++ b/docs/api/mozilla.components.service.glean.private/-common-metric-data/index.md @@ -30,6 +30,7 @@ metric types. |---|---| | [BooleanMetricType](../-boolean-metric-type/index.md) | `data class BooleanMetricType : `[`CommonMetricData`](./index.md)
    This implements the developer facing API for recording boolean metrics. | | [CounterMetricType](../-counter-metric-type/index.md) | `data class CounterMetricType : `[`CommonMetricData`](./index.md)
    This implements the developer facing API for recording counter metrics. | +| [CustomDistributionMetricType](../-custom-distribution-metric-type/index.md) | `data class CustomDistributionMetricType : `[`CommonMetricData`](./index.md)`, `[`HistogramBase`](../-histogram-base/index.md)
    This implements the developer facing API for recording custom distribution metrics. | | [DatetimeMetricType](../-datetime-metric-type/index.md) | `data class DatetimeMetricType : `[`CommonMetricData`](./index.md)
    This implements the developer facing API for recording datetime metrics. | | [EventMetricType](../-event-metric-type/index.md) | `data class EventMetricType> : `[`CommonMetricData`](./index.md)
    This implements the developer facing API for recording events. | | [LabeledMetricType](../-labeled-metric-type/index.md) | `data class LabeledMetricType : `[`CommonMetricData`](./index.md)
    This implements the developer facing API for labeled metrics. | diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/-init-.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/-init-.md new file mode 100644 index 00000000000..bb2b647da55 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/-init-.md @@ -0,0 +1,24 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [<init>](./-init-.md) + +# <init> + +`CustomDistributionMetricType(disabled: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`, category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, lifetime: `[`Lifetime`](../-lifetime/index.md)`, name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, sendInPings: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>, rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, histogramType: `[`HistogramType`](../-histogram-type/index.md)`)` + +This implements the developer facing API for recording custom distribution metrics. + +Custom distributions are histograms with the following parameters that are settable on a +per-metric basis: + +``` + - `rangeMin`/`rangeMax`: The minimum and maximum values + - `bucketCount`: The number of histogram buckets + - `histogramType`: Whether the bucketing is linear or exponential +``` + +This metric exists primarily for backward compatibility with histograms in +legacy (pre-Glean) telemetry, and its use is not recommended for newly-created +metrics. + +Instances of this class type are automatically generated by the parsers at build time, +allowing developers to record values that were previously registered in the metrics.yaml file. + diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/accumulate-samples.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/accumulate-samples.md new file mode 100644 index 00000000000..a93b51ba507 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/accumulate-samples.md @@ -0,0 +1,17 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [accumulateSamples](./accumulate-samples.md) + +# accumulateSamples + +`fun accumulateSamples(samples: `[`LongArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long-array/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L53) + +Overrides [HistogramBase.accumulateSamples](../-histogram-base/accumulate-samples.md) + +Accumulates the provided samples in the metric. + +The unit of the samples is entirely defined by the user. We encourage the author of the +metric to provide a `unit` parameter in the `metrics.yaml` file, but that has no effect +in the client and there is no unit conversion performed here. + +### Parameters + +`samples` - the [LongArray](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long-array/index.html) holding the samples to be recorded by the metric. \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/bucket-count.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/bucket-count.md new file mode 100644 index 00000000000..a14a79128d4 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/bucket-count.md @@ -0,0 +1,5 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [bucketCount](./bucket-count.md) + +# bucketCount + +`val bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L38) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/category.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/category.md new file mode 100644 index 00000000000..533f47b54e8 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/category.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [category](./category.md) + +# category + +`val category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L32) + +Overrides [CommonMetricData.category](../-common-metric-data/category.md) + diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/disabled.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/disabled.md new file mode 100644 index 00000000000..4b2e227d92b --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/disabled.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [disabled](./disabled.md) + +# disabled + +`val disabled: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L31) + +Overrides [CommonMetricData.disabled](../-common-metric-data/disabled.md) + diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/histogram-type.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/histogram-type.md new file mode 100644 index 00000000000..af897a70394 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/histogram-type.md @@ -0,0 +1,5 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [histogramType](./histogram-type.md) + +# histogramType + +`val histogramType: `[`HistogramType`](../-histogram-type/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L39) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/index.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/index.md new file mode 100644 index 00000000000..3ac4470c560 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/index.md @@ -0,0 +1,63 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](./index.md) + +# CustomDistributionMetricType + +`data class CustomDistributionMetricType : `[`CommonMetricData`](../-common-metric-data/index.md)`, `[`HistogramBase`](../-histogram-base/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L30) + +This implements the developer facing API for recording custom distribution metrics. + +Custom distributions are histograms with the following parameters that are settable on a +per-metric basis: + +``` + - `rangeMin`/`rangeMax`: The minimum and maximum values + - `bucketCount`: The number of histogram buckets + - `histogramType`: Whether the bucketing is linear or exponential +``` + +This metric exists primarily for backward compatibility with histograms in +legacy (pre-Glean) telemetry, and its use is not recommended for newly-created +metrics. + +Instances of this class type are automatically generated by the parsers at build time, +allowing developers to record values that were previously registered in the metrics.yaml file. + +### Constructors + +| Name | Summary | +|---|---| +| [<init>](-init-.md) | `CustomDistributionMetricType(disabled: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`, category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, lifetime: `[`Lifetime`](../-lifetime/index.md)`, name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, sendInPings: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>, rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, histogramType: `[`HistogramType`](../-histogram-type/index.md)`)`
    This implements the developer facing API for recording custom distribution metrics. | + +### Properties + +| Name | Summary | +|---|---| +| [bucketCount](bucket-count.md) | `val bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) | +| [category](category.md) | `val category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | +| [disabled](disabled.md) | `val disabled: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) | +| [histogramType](histogram-type.md) | `val histogramType: `[`HistogramType`](../-histogram-type/index.md) | +| [lifetime](lifetime.md) | `val lifetime: `[`Lifetime`](../-lifetime/index.md) | +| [name](name.md) | `val name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | +| [rangeMax](range-max.md) | `val rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) | +| [rangeMin](range-min.md) | `val rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) | +| [sendInPings](send-in-pings.md) | `val sendInPings: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>` | + +### Inherited Properties + +| Name | Summary | +|---|---| +| [identifier](../-common-metric-data/identifier.md) | `open val identifier: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | + +### Functions + +| Name | Summary | +|---|---| +| [accumulateSamples](accumulate-samples.md) | `fun accumulateSamples(samples: `[`LongArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long-array/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
    Accumulates the provided samples in the metric. | +| [testGetValue](test-get-value.md) | `fun testGetValue(pingName: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = sendInPings.first()): `[`CustomDistributionData`](../../mozilla.components.service.glean.storages/-custom-distribution-data/index.md)
    Returns the stored value for testing purposes only. This function will attempt to await the last task (if any) writing to the the metric's storage engine before returning a value. | +| [testHasValue](test-has-value.md) | `fun testHasValue(pingName: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = sendInPings.first()): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)
    Tests whether a value is stored for the metric for testing purposes only. This function will attempt to await the last task (if any) writing to the the metric's storage engine before returning a value. | + +### Inherited Functions + +| Name | Summary | +|---|---| +| [shouldRecord](../-common-metric-data/should-record.md) | `open fun shouldRecord(logger: `[`Logger`](../../mozilla.components.support.base.log.logger/-logger/index.md)`): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) | diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/lifetime.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/lifetime.md new file mode 100644 index 00000000000..554fbbae66e --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/lifetime.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [lifetime](./lifetime.md) + +# lifetime + +`val lifetime: `[`Lifetime`](../-lifetime/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L33) + +Overrides [CommonMetricData.lifetime](../-common-metric-data/lifetime.md) + diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/name.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/name.md new file mode 100644 index 00000000000..c2b21d9dd5c --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/name.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [name](./name.md) + +# name + +`val name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L34) + +Overrides [CommonMetricData.name](../-common-metric-data/name.md) + diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/range-max.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/range-max.md new file mode 100644 index 00000000000..1a36c45075b --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/range-max.md @@ -0,0 +1,5 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [rangeMax](./range-max.md) + +# rangeMax + +`val rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L37) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/range-min.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/range-min.md new file mode 100644 index 00000000000..e79632480c8 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/range-min.md @@ -0,0 +1,5 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [rangeMin](./range-min.md) + +# rangeMin + +`val rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L36) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/send-in-pings.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/send-in-pings.md new file mode 100644 index 00000000000..006cbafbad4 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/send-in-pings.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [sendInPings](./send-in-pings.md) + +# sendInPings + +`val sendInPings: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L35) + +Overrides [CommonMetricData.sendInPings](../-common-metric-data/send-in-pings.md) + diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/test-get-value.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/test-get-value.md new file mode 100644 index 00000000000..0d81ff4c66e --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/test-get-value.md @@ -0,0 +1,22 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [testGetValue](./test-get-value.md) + +# testGetValue + +`fun testGetValue(pingName: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = sendInPings.first()): `[`CustomDistributionData`](../../mozilla.components.service.glean.storages/-custom-distribution-data/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L100) + +Returns the stored value for testing purposes only. This function will attempt to await the +last task (if any) writing to the the metric's storage engine before returning a value. + +### Parameters + +`pingName` - represents the name of the ping to retrieve the metric for. Defaults + to the either the first value in [defaultStorageDestinations](#) or the first + value in [sendInPings](send-in-pings.md) + +### Exceptions + +`NullPointerException` - if no value is stored + +**Return** +value of the stored metric + diff --git a/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/test-has-value.md b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/test-has-value.md new file mode 100644 index 00000000000..215d313d3ec --- /dev/null +++ b/docs/api/mozilla.components.service.glean.private/-custom-distribution-metric-type/test-has-value.md @@ -0,0 +1,19 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.private](../index.md) / [CustomDistributionMetricType](index.md) / [testHasValue](./test-has-value.md) + +# testHasValue + +`fun testHasValue(pingName: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = sendInPings.first()): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/CustomDistributionMetricType.kt#L82) + +Tests whether a value is stored for the metric for testing purposes only. This function will +attempt to await the last task (if any) writing to the the metric's storage engine before +returning a value. + +### Parameters + +`pingName` - represents the name of the ping to retrieve the metric for. Defaults + to the either the first value in [defaultStorageDestinations](#) or the first + value in [sendInPings](send-in-pings.md) + +**Return** +true if metric value exists, otherwise false + diff --git a/docs/api/mozilla.components.service.glean.private/-histogram-base/accumulate-samples.md b/docs/api/mozilla.components.service.glean.private/-histogram-base/accumulate-samples.md index 1db73f0d713..ab1d42f2317 100644 --- a/docs/api/mozilla.components.service.glean.private/-histogram-base/accumulate-samples.md +++ b/docs/api/mozilla.components.service.glean.private/-histogram-base/accumulate-samples.md @@ -2,16 +2,10 @@ # accumulateSamples -`abstract fun accumulateSamples(samples: `[`LongArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long-array/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/HistogramBase.kt#L23) +`abstract fun accumulateSamples(samples: `[`LongArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long-array/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/HistogramBase.kt#L17) Accumulates the provided samples in the metric. -Please note that this assumes that the provided samples are already in the -"unit" declared by the instance of the implementing metric type (e.g. if the -implementing class is a [TimingDistributionMetricType](../-timing-distribution-metric-type/index.md) and the instance this -method was called on is using [TimeUnit.Second](../-time-unit/-second.md), then `samples` are assumed -to be in that unit). - ### Parameters `samples` - the [LongArray](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long-array/index.html) holding the samples to be recorded by the metric. \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.private/-histogram-base/index.md b/docs/api/mozilla.components.service.glean.private/-histogram-base/index.md index 4a9ea01d521..9fd20f12e92 100644 --- a/docs/api/mozilla.components.service.glean.private/-histogram-base/index.md +++ b/docs/api/mozilla.components.service.glean.private/-histogram-base/index.md @@ -17,4 +17,5 @@ supported by the Glean SDK. | Name | Summary | |---|---| +| [CustomDistributionMetricType](../-custom-distribution-metric-type/index.md) | `data class CustomDistributionMetricType : `[`CommonMetricData`](../-common-metric-data/index.md)`, `[`HistogramBase`](./index.md)
    This implements the developer facing API for recording custom distribution metrics. | | [TimingDistributionMetricType](../-timing-distribution-metric-type/index.md) | `data class TimingDistributionMetricType : `[`CommonMetricData`](../-common-metric-data/index.md)`, `[`HistogramBase`](./index.md)
    This implements the developer facing API for recording timing distribution metrics. | diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/-init-.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/-init-.md index 7bf28f1a021..6e04883de8f 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/-init-.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/-init-.md @@ -6,6 +6,13 @@ This implements the developer facing API for recording timing distribution metrics. +The `timeUnit` parameter is only used when the values are set directly +through `accumulateSamples`, which is used for bringing in GeckoView metrics, +and not for normal use. + +To prevent the number of buckets from being unbounded, timings longer than 10 minutes +are truncated to 10 minutes. + Instances of this class type are automatically generated by the parsers at build time, allowing developers to record values that were previously registered in the metrics.yaml file. diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/accumulate-samples.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/accumulate-samples.md index f309644b0fd..908ef96fcd7 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/accumulate-samples.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/accumulate-samples.md @@ -2,7 +2,7 @@ # accumulateSamples -`fun accumulateSamples(samples: `[`LongArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long-array/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L88) +`fun accumulateSamples(samples: `[`LongArray`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long-array/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L105) Overrides [HistogramBase.accumulateSamples](../-histogram-base/accumulate-samples.md) diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/cancel.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/cancel.md index c32348cdccd..38b12ac8928 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/cancel.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/cancel.md @@ -2,7 +2,7 @@ # cancel -`fun cancel(timerId: `[`GleanTimerId`](../../mozilla.components.service.glean.timing/-glean-timer-id.md)`?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L80) +`fun cancel(timerId: `[`GleanTimerId`](../../mozilla.components.service.glean.timing/-glean-timer-id.md)`?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L86) Abort a previous [start](start.md) call. No error is recorded if no [start](start.md) was called. diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/category.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/category.md index c93a9cfd723..5cb06098c6c 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/category.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/category.md @@ -2,7 +2,7 @@ # category -`val category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L23) +`val category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L30) Overrides [CommonMetricData.category](../-common-metric-data/category.md) diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/disabled.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/disabled.md index ec4e66da331..46d37873948 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/disabled.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/disabled.md @@ -2,7 +2,7 @@ # disabled -`val disabled: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L22) +`val disabled: `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L29) Overrides [CommonMetricData.disabled](../-common-metric-data/disabled.md) diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/index.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/index.md index 130d37690b5..7fec343be66 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/index.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/index.md @@ -2,10 +2,17 @@ # TimingDistributionMetricType -`data class TimingDistributionMetricType : `[`CommonMetricData`](../-common-metric-data/index.md)`, `[`HistogramBase`](../-histogram-base/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L21) +`data class TimingDistributionMetricType : `[`CommonMetricData`](../-common-metric-data/index.md)`, `[`HistogramBase`](../-histogram-base/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L28) This implements the developer facing API for recording timing distribution metrics. +The `timeUnit` parameter is only used when the values are set directly +through `accumulateSamples`, which is used for bringing in GeckoView metrics, +and not for normal use. + +To prevent the number of buckets from being unbounded, timings longer than 10 minutes +are truncated to 10 minutes. + Instances of this class type are automatically generated by the parsers at build time, allowing developers to record values that were previously registered in the metrics.yaml file. diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/lifetime.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/lifetime.md index 8c0e03731e9..77f9524d0a5 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/lifetime.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/lifetime.md @@ -2,7 +2,7 @@ # lifetime -`val lifetime: `[`Lifetime`](../-lifetime/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L24) +`val lifetime: `[`Lifetime`](../-lifetime/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L31) Overrides [CommonMetricData.lifetime](../-common-metric-data/lifetime.md) diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/name.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/name.md index 5a8596d5ca1..1534a5c68b4 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/name.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/name.md @@ -2,7 +2,7 @@ # name -`val name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L25) +`val name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L32) Overrides [CommonMetricData.name](../-common-metric-data/name.md) diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/send-in-pings.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/send-in-pings.md index 93d749b14b1..08f9195c430 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/send-in-pings.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/send-in-pings.md @@ -2,7 +2,7 @@ # sendInPings -`val sendInPings: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L26) +`val sendInPings: `[`List`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L33) Overrides [CommonMetricData.sendInPings](../-common-metric-data/send-in-pings.md) diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/start.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/start.md index e72b764ec63..19b0265c668 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/start.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/start.md @@ -2,7 +2,7 @@ # start -`fun start(): `[`GleanTimerId`](../../mozilla.components.service.glean.timing/-glean-timer-id.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L38) +`fun start(): `[`GleanTimerId`](../../mozilla.components.service.glean.timing/-glean-timer-id.md)`?` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L45) Start tracking time for the provided metric and [GleanTimerId](../../mozilla.components.service.glean.timing/-glean-timer-id.md). This records an error if it’s already tracking time (i.e. start was already diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/stop-and-accumulate.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/stop-and-accumulate.md index 0c40ad3499d..8759eb5d80a 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/stop-and-accumulate.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/stop-and-accumulate.md @@ -2,7 +2,7 @@ # stopAndAccumulate -`fun stopAndAccumulate(timerId: `[`GleanTimerId`](../../mozilla.components.service.glean.timing/-glean-timer-id.md)`?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L55) +`fun stopAndAccumulate(timerId: `[`GleanTimerId`](../../mozilla.components.service.glean.timing/-glean-timer-id.md)`?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L62) Stop tracking time for the provided metric and associated timer id. Add a count to the corresponding bucket in the timing distribution. diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/test-get-value.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/test-get-value.md index 574ab66bfa4..88fc0d26264 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/test-get-value.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/test-get-value.md @@ -2,7 +2,7 @@ # testGetValue -`fun testGetValue(pingName: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = sendInPings.first()): `[`TimingDistributionData`](../../mozilla.components.service.glean.storages/-timing-distribution-data/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L132) +`fun testGetValue(pingName: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = sendInPings.first()): `[`TimingDistributionData`](../../mozilla.components.service.glean.storages/-timing-distribution-data/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L149) Returns the stored value for testing purposes only. This function will attempt to await the last task (if any) writing to the the metric's storage engine before returning a value. diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/test-has-value.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/test-has-value.md index c14898da76a..d597d22ac5d 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/test-has-value.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/test-has-value.md @@ -2,7 +2,7 @@ # testHasValue -`fun testHasValue(pingName: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = sendInPings.first()): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L114) +`fun testHasValue(pingName: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = sendInPings.first()): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L131) Tests whether a value is stored for the metric for testing purposes only. This function will attempt to await the last task (if any) writing to the the metric's storage engine before diff --git a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/time-unit.md b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/time-unit.md index d627d2234a5..3557b5a9e90 100644 --- a/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/time-unit.md +++ b/docs/api/mozilla.components.service.glean.private/-timing-distribution-metric-type/time-unit.md @@ -2,4 +2,4 @@ # timeUnit -`val timeUnit: `[`TimeUnit`](../-time-unit/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L27) \ No newline at end of file +`val timeUnit: `[`TimeUnit`](../-time-unit/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/private/TimingDistributionMetricType.kt#L34) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.private/index.md b/docs/api/mozilla.components.service.glean.private/index.md index 9bc86d28ee0..00983ffbeda 100644 --- a/docs/api/mozilla.components.service.glean.private/index.md +++ b/docs/api/mozilla.components.service.glean.private/index.md @@ -9,6 +9,7 @@ | [BooleanMetricType](-boolean-metric-type/index.md) | `data class BooleanMetricType : `[`CommonMetricData`](-common-metric-data/index.md)
    This implements the developer facing API for recording boolean metrics. | | [CommonMetricData](-common-metric-data/index.md) | `interface CommonMetricData`
    This defines the common set of data shared across all the different metric types. | | [CounterMetricType](-counter-metric-type/index.md) | `data class CounterMetricType : `[`CommonMetricData`](-common-metric-data/index.md)
    This implements the developer facing API for recording counter metrics. | +| [CustomDistributionMetricType](-custom-distribution-metric-type/index.md) | `data class CustomDistributionMetricType : `[`CommonMetricData`](-common-metric-data/index.md)`, `[`HistogramBase`](-histogram-base/index.md)
    This implements the developer facing API for recording custom distribution metrics. | | [DatetimeMetricType](-datetime-metric-type/index.md) | `data class DatetimeMetricType : `[`CommonMetricData`](-common-metric-data/index.md)
    This implements the developer facing API for recording datetime metrics. | | [EventMetricType](-event-metric-type/index.md) | `data class EventMetricType> : `[`CommonMetricData`](-common-metric-data/index.md)
    This implements the developer facing API for recording events. | | [HistogramBase](-histogram-base/index.md) | `interface HistogramBase`
    A common interface to be implemented by all the histogram-like metric types supported by the Glean SDK. | diff --git a/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/-init-.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/-init-.md new file mode 100644 index 00000000000..9d6f1abda05 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/-init-.md @@ -0,0 +1,27 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](index.md) / [<init>](./-init-.md) + +# <init> + +`CustomDistributionData(category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, histogramType: `[`HistogramType`](../../mozilla.components.service.glean.private/-histogram-type/index.md)`, values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`> = mutableMapOf(), sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = 0)` + +This class represents the structure of a custom distribution according to the pipeline schema. It +is meant to help serialize and deserialize data to the correct format for transport and storage, +as well as including a helper function to calculate the bucket sizes. + +### Parameters + +`category` - of the metric + +`name` - of the metric + +`bucketCount` - total number of buckets + +`rangeMin` - the minimum value that can be represented + +`rangeMax` - the maximum value that can be represented + +`histogramType` - the [HistogramType](../../mozilla.components.service.glean.private/-histogram-type/index.md) representing the bucket layout + +`values` - a map containing the bucket index mapped to the accumulated count + +`sum` - the accumulated sum of all the samples in the custom distribution \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/bucket-count.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/bucket-count.md similarity index 66% rename from docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/bucket-count.md rename to docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/bucket-count.md index 81a2b284237..2b2dceb1166 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/bucket-count.md +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/bucket-count.md @@ -1,8 +1,8 @@ -[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [TimingDistributionData](index.md) / [bucketCount](./bucket-count.md) +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](index.md) / [bucketCount](./bucket-count.md) # bucketCount -`val bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L173) +`val bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt#L150) total number of buckets diff --git a/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/category.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/category.md new file mode 100644 index 00000000000..1edec934a35 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/category.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](index.md) / [category](./category.md) + +# category + +`val category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt#L146) + +of the metric + diff --git a/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/count.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/count.md new file mode 100644 index 00000000000..eb197d61710 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/count.md @@ -0,0 +1,5 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](index.md) / [count](./count.md) + +# count + +`val count: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt#L232) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/histogram-type.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/histogram-type.md similarity index 81% rename from docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/histogram-type.md rename to docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/histogram-type.md index 545f17ccf8f..cb01ea6de63 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/histogram-type.md +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/histogram-type.md @@ -1,8 +1,8 @@ -[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [TimingDistributionData](index.md) / [histogramType](./histogram-type.md) +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](index.md) / [histogramType](./histogram-type.md) # histogramType -`val histogramType: `[`HistogramType`](../../mozilla.components.service.glean.private/-histogram-type/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L176) +`val histogramType: `[`HistogramType`](../../mozilla.components.service.glean.private/-histogram-type/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt#L151) the [HistogramType](../../mozilla.components.service.glean.private/-histogram-type/index.md) representing the bucket layout diff --git a/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/index.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/index.md new file mode 100644 index 00000000000..bd633eaae43 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/index.md @@ -0,0 +1,47 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](./index.md) + +# CustomDistributionData + +`data class CustomDistributionData` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt#L145) + +This class represents the structure of a custom distribution according to the pipeline schema. It +is meant to help serialize and deserialize data to the correct format for transport and storage, +as well as including a helper function to calculate the bucket sizes. + +### Parameters + +`category` - of the metric + +`name` - of the metric + +`bucketCount` - total number of buckets + +`rangeMin` - the minimum value that can be represented + +`rangeMax` - the maximum value that can be represented + +`histogramType` - the [HistogramType](../../mozilla.components.service.glean.private/-histogram-type/index.md) representing the bucket layout + +`values` - a map containing the bucket index mapped to the accumulated count + +`sum` - the accumulated sum of all the samples in the custom distribution + +### Constructors + +| Name | Summary | +|---|---| +| [<init>](-init-.md) | `CustomDistributionData(category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)`, histogramType: `[`HistogramType`](../../mozilla.components.service.glean.private/-histogram-type/index.md)`, values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`> = mutableMapOf(), sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = 0)`
    This class represents the structure of a custom distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, as well as including a helper function to calculate the bucket sizes. | + +### Properties + +| Name | Summary | +|---|---| +| [bucketCount](bucket-count.md) | `val bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)
    total number of buckets | +| [category](category.md) | `val category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
    of the metric | +| [count](count.md) | `val count: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) | +| [histogramType](histogram-type.md) | `val histogramType: `[`HistogramType`](../../mozilla.components.service.glean.private/-histogram-type/index.md)
    the [HistogramType](../../mozilla.components.service.glean.private/-histogram-type/index.md) representing the bucket layout | +| [name](name.md) | `val name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
    of the metric | +| [rangeMax](range-max.md) | `val rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)
    the maximum value that can be represented | +| [rangeMin](range-min.md) | `val rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)
    the minimum value that can be represented | +| [sum](sum.md) | `var sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)
    the accumulated sum of all the samples in the custom distribution | +| [values](values.md) | `val values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`>`
    a map containing the bucket index mapped to the accumulated count | diff --git a/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/name.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/name.md new file mode 100644 index 00000000000..308e103253e --- /dev/null +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/name.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](index.md) / [name](./name.md) + +# name + +`val name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt#L147) + +of the metric + diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/range-max.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/range-max.md similarity index 67% rename from docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/range-max.md rename to docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/range-max.md index d4e52489c6d..5d056c91eaa 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/range-max.md +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/range-max.md @@ -1,8 +1,8 @@ -[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [TimingDistributionData](index.md) / [rangeMax](./range-max.md) +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](index.md) / [rangeMax](./range-max.md) # rangeMax -`val rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L175) +`val rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt#L149) the maximum value that can be represented diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/range-min.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/range-min.md similarity index 67% rename from docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/range-min.md rename to docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/range-min.md index ac9d42ed183..31250fe566f 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/range-min.md +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/range-min.md @@ -1,8 +1,8 @@ -[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [TimingDistributionData](index.md) / [rangeMin](./range-min.md) +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](index.md) / [rangeMin](./range-min.md) # rangeMin -`val rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L174) +`val rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt#L148) the minimum value that can be represented diff --git a/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/sum.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/sum.md new file mode 100644 index 00000000000..9ecf4868774 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/sum.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](index.md) / [sum](./sum.md) + +# sum + +`var sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt#L154) + +the accumulated sum of all the samples in the custom distribution + diff --git a/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/values.md b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/values.md new file mode 100644 index 00000000000..d6613766c18 --- /dev/null +++ b/docs/api/mozilla.components.service.glean.storages/-custom-distribution-data/values.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [CustomDistributionData](index.md) / [values](./values.md) + +# values + +`val values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/CustomDistributionsStorageEngine.kt#L153) + +a map containing the bucket index mapped to the accumulated count + diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-d-e-f-a-u-l-t_-b-u-c-k-e-t_-c-o-u-n-t.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-d-e-f-a-u-l-t_-b-u-c-k-e-t_-c-o-u-n-t.md deleted file mode 100644 index 9c6806440d1..00000000000 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-d-e-f-a-u-l-t_-b-u-c-k-e-t_-c-o-u-n-t.md +++ /dev/null @@ -1,5 +0,0 @@ -[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [TimingDistributionData](index.md) / [DEFAULT_BUCKET_COUNT](./-d-e-f-a-u-l-t_-b-u-c-k-e-t_-c-o-u-n-t.md) - -# DEFAULT_BUCKET_COUNT - -`const val DEFAULT_BUCKET_COUNT: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L186) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-d-e-f-a-u-l-t_-r-a-n-g-e_-m-a-x.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-d-e-f-a-u-l-t_-r-a-n-g-e_-m-a-x.md deleted file mode 100644 index e6fa1f450f4..00000000000 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-d-e-f-a-u-l-t_-r-a-n-g-e_-m-a-x.md +++ /dev/null @@ -1,5 +0,0 @@ -[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [TimingDistributionData](index.md) / [DEFAULT_RANGE_MAX](./-d-e-f-a-u-l-t_-r-a-n-g-e_-m-a-x.md) - -# DEFAULT_RANGE_MAX - -`const val DEFAULT_RANGE_MAX: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L188) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-d-e-f-a-u-l-t_-r-a-n-g-e_-m-i-n.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-d-e-f-a-u-l-t_-r-a-n-g-e_-m-i-n.md deleted file mode 100644 index 0a03af8123a..00000000000 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-d-e-f-a-u-l-t_-r-a-n-g-e_-m-i-n.md +++ /dev/null @@ -1,5 +0,0 @@ -[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [TimingDistributionData](index.md) / [DEFAULT_RANGE_MIN](./-d-e-f-a-u-l-t_-r-a-n-g-e_-m-i-n.md) - -# DEFAULT_RANGE_MIN - -`const val DEFAULT_RANGE_MIN: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L187) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-init-.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-init-.md index 97160683106..a145067c04b 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-init-.md +++ b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/-init-.md @@ -2,28 +2,31 @@ # <init> -`TimingDistributionData(category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = DEFAULT_BUCKET_COUNT, rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_RANGE_MIN, rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_RANGE_MAX, histogramType: `[`HistogramType`](../../mozilla.components.service.glean.private/-histogram-type/index.md)` = HistogramType.Exponential, values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`> = mutableMapOf(), sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = 0, timeUnit: `[`TimeUnit`](../../mozilla.components.service.glean.private/-time-unit/index.md)` = TimeUnit.Millisecond)` +`TimingDistributionData(category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`> = mutableMapOf(), sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = 0)` This class represents the structure of a timing distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, -as well as including a helper function to calculate the bucket sizes. +as well as performing the calculations to determine the correct bucket for each sample. -### Parameters +The bucket index of a given sample is determined with the following function: -`category` - of the metric +``` + i = ⌊n log₂(𝑥)⌋ +``` -`name` - of the metric +In other words, there are n buckets for each power of 2 magnitude. -`bucketCount` - total number of buckets +The value of 8 for n was determined experimentally based on existing data to have sufficient +resolution. -`rangeMin` - the minimum value that can be represented +Samples greater than 10 minutes in length are truncated to 10 minutes. -`rangeMax` - the maximum value that can be represented +### Parameters -`histogramType` - the [HistogramType](../../mozilla.components.service.glean.private/-histogram-type/index.md) representing the bucket layout +`category` - of the metric -`values` - a map containing the bucket index mapped to the accumulated count +`name` - of the metric -`sum` - the accumulated sum of all the samples in the timing distribution +`values` - a map containing the minimum bucket value mapped to the accumulated count -`timeUnit` - the base [TimeUnit](../../mozilla.components.service.glean.private/-time-unit/index.md) of the bucket values \ No newline at end of file +`sum` - the accumulated sum of all the samples in the timing distribution \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/category.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/category.md index ec2a78df4aa..414a2aef854 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/category.md +++ b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/category.md @@ -2,7 +2,7 @@ # category -`val category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L171) +`val category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L193) of the metric diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/count.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/count.md index 00784ca6016..4b7bbf4b6fd 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/count.md +++ b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/count.md @@ -2,4 +2,4 @@ # count -`val count: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L272) \ No newline at end of file +`val count: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L292) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/index.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/index.md index 3bf914c2aa0..f6fe2163587 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/index.md +++ b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/index.md @@ -2,57 +2,47 @@ # TimingDistributionData -`data class TimingDistributionData` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L170) +`data class TimingDistributionData` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L192) This class represents the structure of a timing distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, -as well as including a helper function to calculate the bucket sizes. +as well as performing the calculations to determine the correct bucket for each sample. -### Parameters +The bucket index of a given sample is determined with the following function: -`category` - of the metric +``` + i = ⌊n log₂(𝑥)⌋ +``` -`name` - of the metric +In other words, there are n buckets for each power of 2 magnitude. -`bucketCount` - total number of buckets +The value of 8 for n was determined experimentally based on existing data to have sufficient +resolution. -`rangeMin` - the minimum value that can be represented +Samples greater than 10 minutes in length are truncated to 10 minutes. -`rangeMax` - the maximum value that can be represented +### Parameters + +`category` - of the metric -`histogramType` - the [HistogramType](../../mozilla.components.service.glean.private/-histogram-type/index.md) representing the bucket layout +`name` - of the metric -`values` - a map containing the bucket index mapped to the accumulated count +`values` - a map containing the minimum bucket value mapped to the accumulated count `sum` - the accumulated sum of all the samples in the timing distribution -`timeUnit` - the base [TimeUnit](../../mozilla.components.service.glean.private/-time-unit/index.md) of the bucket values - ### Constructors | Name | Summary | |---|---| -| [<init>](-init-.md) | `TimingDistributionData(category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)` = DEFAULT_BUCKET_COUNT, rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_RANGE_MIN, rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = DEFAULT_RANGE_MAX, histogramType: `[`HistogramType`](../../mozilla.components.service.glean.private/-histogram-type/index.md)` = HistogramType.Exponential, values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`> = mutableMapOf(), sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = 0, timeUnit: `[`TimeUnit`](../../mozilla.components.service.glean.private/-time-unit/index.md)` = TimeUnit.Millisecond)`
    This class represents the structure of a timing distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, as well as including a helper function to calculate the bucket sizes. | +| [<init>](-init-.md) | `TimingDistributionData(category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`> = mutableMapOf(), sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)` = 0)`
    This class represents the structure of a timing distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, as well as performing the calculations to determine the correct bucket for each sample. | ### Properties | Name | Summary | |---|---| -| [bucketCount](bucket-count.md) | `val bucketCount: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)
    total number of buckets | | [category](category.md) | `val category: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
    of the metric | | [count](count.md) | `val count: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) | -| [histogramType](histogram-type.md) | `val histogramType: `[`HistogramType`](../../mozilla.components.service.glean.private/-histogram-type/index.md)
    the [HistogramType](../../mozilla.components.service.glean.private/-histogram-type/index.md) representing the bucket layout | | [name](name.md) | `val name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
    of the metric | -| [rangeMax](range-max.md) | `val rangeMax: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)
    the maximum value that can be represented | -| [rangeMin](range-min.md) | `val rangeMin: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)
    the minimum value that can be represented | | [sum](sum.md) | `var sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)
    the accumulated sum of all the samples in the timing distribution | -| [timeUnit](time-unit.md) | `val timeUnit: `[`TimeUnit`](../../mozilla.components.service.glean.private/-time-unit/index.md)
    the base [TimeUnit](../../mozilla.components.service.glean.private/-time-unit/index.md) of the bucket values | -| [values](values.md) | `val values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`>`
    a map containing the bucket index mapped to the accumulated count | - -### Companion Object Properties - -| Name | Summary | -|---|---| -| [DEFAULT_BUCKET_COUNT](-d-e-f-a-u-l-t_-b-u-c-k-e-t_-c-o-u-n-t.md) | `const val DEFAULT_BUCKET_COUNT: `[`Int`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) | -| [DEFAULT_RANGE_MAX](-d-e-f-a-u-l-t_-r-a-n-g-e_-m-a-x.md) | `const val DEFAULT_RANGE_MAX: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) | -| [DEFAULT_RANGE_MIN](-d-e-f-a-u-l-t_-r-a-n-g-e_-m-i-n.md) | `const val DEFAULT_RANGE_MIN: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) | +| [values](values.md) | `val values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`>`
    a map containing the minimum bucket value mapped to the accumulated count | diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/name.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/name.md index 6333c77a62b..3b9c4b130b2 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/name.md +++ b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/name.md @@ -2,7 +2,7 @@ # name -`val name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L172) +`val name: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L194) of the metric diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/sum.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/sum.md index 2d5717eeacd..4f5154bf101 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/sum.md +++ b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/sum.md @@ -2,7 +2,7 @@ # sum -`var sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L179) +`var sum: `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L197) the accumulated sum of all the samples in the timing distribution diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/time-unit.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/time-unit.md deleted file mode 100644 index eca6090ba3a..00000000000 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/time-unit.md +++ /dev/null @@ -1,8 +0,0 @@ -[android-components](../../index.md) / [mozilla.components.service.glean.storages](../index.md) / [TimingDistributionData](index.md) / [timeUnit](./time-unit.md) - -# timeUnit - -`val timeUnit: `[`TimeUnit`](../../mozilla.components.service.glean.private/-time-unit/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L180) - -the base [TimeUnit](../../mozilla.components.service.glean.private/-time-unit/index.md) of the bucket values - diff --git a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/values.md b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/values.md index 13062dc9024..a791cd78126 100644 --- a/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/values.md +++ b/docs/api/mozilla.components.service.glean.storages/-timing-distribution-data/values.md @@ -2,7 +2,7 @@ # values -`val values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L178) +`val values: `[`MutableMap`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-map/index.html)`<`[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`, `[`Long`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-long/index.html)`>` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/storages/TimingDistributionsStorageEngine.kt#L196) -a map containing the bucket index mapped to the accumulated count +a map containing the minimum bucket value mapped to the accumulated count diff --git a/docs/api/mozilla.components.service.glean.storages/index.md b/docs/api/mozilla.components.service.glean.storages/index.md index 2055048078f..871ca5f434f 100644 --- a/docs/api/mozilla.components.service.glean.storages/index.md +++ b/docs/api/mozilla.components.service.glean.storages/index.md @@ -6,6 +6,7 @@ | Name | Summary | |---|---| +| [CustomDistributionData](-custom-distribution-data/index.md) | `data class CustomDistributionData`
    This class represents the structure of a custom distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, as well as including a helper function to calculate the bucket sizes. | | [RecordedEventData](-recorded-event-data/index.md) | `data class RecordedEventData` | | [RecordedExperimentData](-recorded-experiment-data/index.md) | `data class RecordedExperimentData` | -| [TimingDistributionData](-timing-distribution-data/index.md) | `data class TimingDistributionData`
    This class represents the structure of a timing distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, as well as including a helper function to calculate the bucket sizes. | +| [TimingDistributionData](-timing-distribution-data/index.md) | `data class TimingDistributionData`
    This class represents the structure of a timing distribution according to the pipeline schema. It is meant to help serialize and deserialize data to the correct format for transport and storage, as well as performing the calculations to determine the correct bucket for each sample. | diff --git a/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/-init-.md b/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/-init-.md index 3c1921bb288..35379caef29 100644 --- a/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/-init-.md +++ b/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/-init-.md @@ -2,7 +2,7 @@ # <init> -`GleanTestRule(context: )` +`GleanTestRule(context: , configToUse: `[`Configuration`](../../mozilla.components.service.glean.config/-configuration/index.md)` = Configuration())` This implements a JUnit rule for writing tests for Glean SDK metrics. @@ -17,3 +17,8 @@ Example usage: val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) ``` +### Parameters + +`context` - the application context + +`configToUse` - an optional [Configuration](../../mozilla.components.service.glean.config/-configuration/index.md) to initialize the Glean SDK with \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/config-to-use.md b/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/config-to-use.md new file mode 100644 index 00000000000..613d55b011c --- /dev/null +++ b/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/config-to-use.md @@ -0,0 +1,8 @@ +[android-components](../../index.md) / [mozilla.components.service.glean.testing](../index.md) / [GleanTestRule](index.md) / [configToUse](./config-to-use.md) + +# configToUse + +`val configToUse: `[`Configuration`](../../mozilla.components.service.glean.config/-configuration/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt#L35) + +an optional [Configuration](../../mozilla.components.service.glean.config/-configuration/index.md) to initialize the Glean SDK with + diff --git a/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/context.md b/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/context.md index 9a775695b5a..5aa0e264a05 100644 --- a/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/context.md +++ b/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/context.md @@ -2,4 +2,7 @@ # context -`val context: ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt#L31) \ No newline at end of file +`val context: ` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt#L34) + +the application context + diff --git a/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/index.md b/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/index.md index 5dba8754cf9..3faae5ed219 100644 --- a/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/index.md +++ b/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/index.md @@ -2,7 +2,7 @@ # GleanTestRule -`class GleanTestRule : TestWatcher` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt#L30) +`class GleanTestRule : TestWatcher` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt#L33) This implements a JUnit rule for writing tests for Glean SDK metrics. @@ -17,17 +17,24 @@ Example usage: val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) ``` +### Parameters + +`context` - the application context + +`configToUse` - an optional [Configuration](../../mozilla.components.service.glean.config/-configuration/index.md) to initialize the Glean SDK with + ### Constructors | Name | Summary | |---|---| -| [<init>](-init-.md) | `GleanTestRule(context: )`
    This implements a JUnit rule for writing tests for Glean SDK metrics. | +| [<init>](-init-.md) | `GleanTestRule(context: , configToUse: `[`Configuration`](../../mozilla.components.service.glean.config/-configuration/index.md)` = Configuration())`
    This implements a JUnit rule for writing tests for Glean SDK metrics. | ### Properties | Name | Summary | |---|---| -| [context](context.md) | `val context: ` | +| [configToUse](config-to-use.md) | `val configToUse: `[`Configuration`](../../mozilla.components.service.glean.config/-configuration/index.md)
    an optional [Configuration](../../mozilla.components.service.glean.config/-configuration/index.md) to initialize the Glean SDK with | +| [context](context.md) | `val context: `
    the application context | ### Functions diff --git a/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/starting.md b/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/starting.md index 86e9bfcf8e1..192e7577533 100644 --- a/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/starting.md +++ b/docs/api/mozilla.components.service.glean.testing/-glean-test-rule/starting.md @@ -2,4 +2,4 @@ # starting -`protected fun starting(description: Description?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt#L33) \ No newline at end of file +`protected fun starting(description: Description?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/testing/GleanTestRule.kt#L37) \ No newline at end of file diff --git a/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/handle-background-event.md b/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/handle-background-event.md index 4c52a15be1d..dd7aa4750ba 100644 --- a/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/handle-background-event.md +++ b/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/handle-background-event.md @@ -2,7 +2,7 @@ # handleBackgroundEvent -`fun handleBackgroundEvent(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L440) +`fun handleBackgroundEvent(): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L450) Handle the background event and send the appropriate pings. diff --git a/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/set-experiment-active.md b/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/set-experiment-active.md index a8dfe9dc6fe..ccb178fb9f0 100644 --- a/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/set-experiment-active.md +++ b/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/set-experiment-active.md @@ -2,7 +2,7 @@ # setExperimentActive -`fun setExperimentActive(experimentId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, branch: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, extra: `[`Map`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>? = null): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L255) +`fun setExperimentActive(experimentId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, branch: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, extra: `[`Map`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`>? = null): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L265) Indicate that an experiment is running. Glean will then add an experiment annotation to the environment which is sent with pings. This diff --git a/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/set-experiment-inactive.md b/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/set-experiment-inactive.md index 9aabce7994b..aeec0c77bbd 100644 --- a/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/set-experiment-inactive.md +++ b/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/set-experiment-inactive.md @@ -2,7 +2,7 @@ # setExperimentInactive -`fun setExperimentInactive(experimentId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L268) +`fun setExperimentInactive(experimentId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L278) Indicate that an experiment is no longer running. diff --git a/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/test-get-experiment-data.md b/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/test-get-experiment-data.md index c8e27c134f5..ed59f59f982 100644 --- a/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/test-get-experiment-data.md +++ b/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/test-get-experiment-data.md @@ -2,7 +2,7 @@ # testGetExperimentData -`fun testGetExperimentData(experimentId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`RecordedExperimentData`](../../mozilla.components.service.glean.storages/-recorded-experiment-data/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L291) +`fun testGetExperimentData(experimentId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`RecordedExperimentData`](../../mozilla.components.service.glean.storages/-recorded-experiment-data/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L301) Returns the stored data for the requested active experiment, for testing purposes only. diff --git a/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/test-is-experiment-active.md b/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/test-is-experiment-active.md index 5b9bea156ea..5aea5a3a392 100644 --- a/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/test-is-experiment-active.md +++ b/docs/api/mozilla.components.service.glean/-glean-internal-a-p-i/test-is-experiment-active.md @@ -2,7 +2,7 @@ # testIsExperimentActive -`fun testIsExperimentActive(experimentId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L279) +`fun testIsExperimentActive(experimentId: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`): `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L289) Tests whether an experiment is active, for testing purposes only. diff --git a/docs/api/mozilla.components.service.glean/-glean.md b/docs/api/mozilla.components.service.glean/-glean.md index a3b23cd816b..5433474b664 100644 --- a/docs/api/mozilla.components.service.glean/-glean.md +++ b/docs/api/mozilla.components.service.glean/-glean.md @@ -2,7 +2,7 @@ # Glean -`object Glean : `[`GleanInternalAPI`](-glean-internal-a-p-i/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L576) +`object Glean : `[`GleanInternalAPI`](-glean-internal-a-p-i/index.md) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt#L586) ### Inherited Functions diff --git a/docs/api/mozilla.components.support.test.rules/-webserver-rule/-init-.md b/docs/api/mozilla.components.support.android.test.rules/-webserver-rule/-init-.md similarity index 66% rename from docs/api/mozilla.components.support.test.rules/-webserver-rule/-init-.md rename to docs/api/mozilla.components.support.android.test.rules/-webserver-rule/-init-.md index 1da34244966..3daf4366386 100644 --- a/docs/api/mozilla.components.support.test.rules/-webserver-rule/-init-.md +++ b/docs/api/mozilla.components.support.android.test.rules/-webserver-rule/-init-.md @@ -1,4 +1,4 @@ -[android-components](../../index.md) / [mozilla.components.support.test.rules](../index.md) / [WebserverRule](index.md) / [<init>](./-init-.md) +[android-components](../../index.md) / [mozilla.components.support.android.test.rules](../index.md) / [WebserverRule](index.md) / [<init>](./-init-.md) # <init> diff --git a/docs/api/mozilla.components.support.test.rules/-webserver-rule/finished.md b/docs/api/mozilla.components.support.android.test.rules/-webserver-rule/finished.md similarity index 54% rename from docs/api/mozilla.components.support.test.rules/-webserver-rule/finished.md rename to docs/api/mozilla.components.support.android.test.rules/-webserver-rule/finished.md index 15ee850625b..46901c8b015 100644 --- a/docs/api/mozilla.components.support.test.rules/-webserver-rule/finished.md +++ b/docs/api/mozilla.components.support.android.test.rules/-webserver-rule/finished.md @@ -1,5 +1,5 @@ -[android-components](../../index.md) / [mozilla.components.support.test.rules](../index.md) / [WebserverRule](index.md) / [finished](./finished.md) +[android-components](../../index.md) / [mozilla.components.support.android.test.rules](../index.md) / [WebserverRule](index.md) / [finished](./finished.md) # finished -`protected fun finished(description: Description?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/support/test/src/main/java/mozilla/components/support/test/rules/WebserverRule.kt#L34) \ No newline at end of file +`protected fun finished(description: Description?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/support/android-test/src/main/java/mozilla/components/support/android/test/rules/WebserverRule.kt#L34) \ No newline at end of file diff --git a/docs/api/mozilla.components.support.test.rules/-webserver-rule/index.md b/docs/api/mozilla.components.support.android.test.rules/-webserver-rule/index.md similarity index 86% rename from docs/api/mozilla.components.support.test.rules/-webserver-rule/index.md rename to docs/api/mozilla.components.support.android.test.rules/-webserver-rule/index.md index 88ed037739c..8420c1b7bcc 100644 --- a/docs/api/mozilla.components.support.test.rules/-webserver-rule/index.md +++ b/docs/api/mozilla.components.support.android.test.rules/-webserver-rule/index.md @@ -1,8 +1,8 @@ -[android-components](../../index.md) / [mozilla.components.support.test.rules](../index.md) / [WebserverRule](./index.md) +[android-components](../../index.md) / [mozilla.components.support.android.test.rules](../index.md) / [WebserverRule](./index.md) # WebserverRule -`class WebserverRule : TestWatcher` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/support/test/src/main/java/mozilla/components/support/test/rules/WebserverRule.kt#L21) +`class WebserverRule : TestWatcher` [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/support/android-test/src/main/java/mozilla/components/support/android/test/rules/WebserverRule.kt#L21) A [TestWatcher](#) junit rule that will serve content from assets in the test package. diff --git a/docs/api/mozilla.components.support.test.rules/-webserver-rule/starting.md b/docs/api/mozilla.components.support.android.test.rules/-webserver-rule/starting.md similarity index 54% rename from docs/api/mozilla.components.support.test.rules/-webserver-rule/starting.md rename to docs/api/mozilla.components.support.android.test.rules/-webserver-rule/starting.md index 215fbc34965..d99df5494f1 100644 --- a/docs/api/mozilla.components.support.test.rules/-webserver-rule/starting.md +++ b/docs/api/mozilla.components.support.android.test.rules/-webserver-rule/starting.md @@ -1,5 +1,5 @@ -[android-components](../../index.md) / [mozilla.components.support.test.rules](../index.md) / [WebserverRule](index.md) / [starting](./starting.md) +[android-components](../../index.md) / [mozilla.components.support.android.test.rules](../index.md) / [WebserverRule](index.md) / [starting](./starting.md) # starting -`protected fun starting(description: Description?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/support/test/src/main/java/mozilla/components/support/test/rules/WebserverRule.kt#L30) \ No newline at end of file +`protected fun starting(description: Description?): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/support/android-test/src/main/java/mozilla/components/support/android/test/rules/WebserverRule.kt#L30) \ No newline at end of file diff --git a/docs/api/mozilla.components.support.test.rules/-webserver-rule/url.md b/docs/api/mozilla.components.support.android.test.rules/-webserver-rule/url.md similarity index 61% rename from docs/api/mozilla.components.support.test.rules/-webserver-rule/url.md rename to docs/api/mozilla.components.support.android.test.rules/-webserver-rule/url.md index 0ec549d8722..ce39fc6f442 100644 --- a/docs/api/mozilla.components.support.test.rules/-webserver-rule/url.md +++ b/docs/api/mozilla.components.support.android.test.rules/-webserver-rule/url.md @@ -1,5 +1,5 @@ -[android-components](../../index.md) / [mozilla.components.support.test.rules](../index.md) / [WebserverRule](index.md) / [url](./url.md) +[android-components](../../index.md) / [mozilla.components.support.android.test.rules](../index.md) / [WebserverRule](index.md) / [url](./url.md) # url -`fun url(path: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = ""): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/support/test/src/main/java/mozilla/components/support/test/rules/WebserverRule.kt#L26) \ No newline at end of file +`fun url(path: `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)` = ""): `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) [(source)](https://github.com/mozilla-mobile/android-components/blob/master/components/support/android-test/src/main/java/mozilla/components/support/android/test/rules/WebserverRule.kt#L26) \ No newline at end of file diff --git a/docs/api/mozilla.components.support.test.rules/index.md b/docs/api/mozilla.components.support.android.test.rules/index.md similarity index 75% rename from docs/api/mozilla.components.support.test.rules/index.md rename to docs/api/mozilla.components.support.android.test.rules/index.md index b38baee37c7..818a70ca5e1 100644 --- a/docs/api/mozilla.components.support.test.rules/index.md +++ b/docs/api/mozilla.components.support.android.test.rules/index.md @@ -1,6 +1,6 @@ -[android-components](../index.md) / [mozilla.components.support.test.rules](./index.md) +[android-components](../index.md) / [mozilla.components.support.android.test.rules](./index.md) -## Package mozilla.components.support.test.rules +## Package mozilla.components.support.android.test.rules ### Types diff --git a/docs/api/package-list b/docs/api/package-list index 350dc23953b..c470f7fbdcf 100644 --- a/docs/api/package-list +++ b/docs/api/package-list @@ -63,6 +63,7 @@ mozilla.components.browser.domains mozilla.components.browser.domains.autocomplete mozilla.components.browser.engine.gecko mozilla.components.browser.engine.gecko.fetch +mozilla.components.browser.engine.gecko.glean mozilla.components.browser.engine.gecko.integration mozilla.components.browser.engine.gecko.permission mozilla.components.browser.engine.gecko.prompt @@ -211,6 +212,7 @@ mozilla.components.support.android.test mozilla.components.support.android.test.espresso mozilla.components.support.android.test.espresso.matcher mozilla.components.support.android.test.leaks +mozilla.components.support.android.test.rules mozilla.components.support.base.android mozilla.components.support.base.android.view mozilla.components.support.base.facts @@ -239,7 +241,6 @@ mozilla.components.support.test mozilla.components.support.test.ext mozilla.components.support.test.robolectric mozilla.components.support.test.robolectric.shadow -mozilla.components.support.test.rules mozilla.components.support.utils mozilla.components.tooling.fetch.tests mozilla.components.tooling.lint diff --git a/docs/changelog.md b/docs/changelog.md index c06db1582fb..829e696afb1 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -4,23 +4,60 @@ title: Changelog permalink: /changelog/ --- -# 8.0.0-SNAPSHOT (In Development) +# 9.0.0-SNAPSHOT (In Development) -* [Commits](https://github.com/mozilla-mobile/android-components/compare/v7.0.0...master) -* [Milestone](https://github.com/mozilla-mobile/android-components/milestone/67?closed=1) +* [Commits](https://github.com/mozilla-mobile/android-components/compare/v8.0.0...master) +* [Milestone](https://github.com/mozilla-mobile/android-components/milestone/68?closed=1) * [Dependencies](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Dependencies.kt) * [Gecko](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Gecko.kt) * [Configuration](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Config.kt) -* **support-test** - * Fixed [#3893](https://github.com/mozilla-mobile/android-components/issues/3893) Moving WebserverRule to support-test. +* **browser-menu** + * Updated the styling of the menu to not have padding on top or bottom. Also modified size of `BrowserMenuItemToolbar` to match `BrowserToolbar`'s height + +* **feature-media** + * Do not display title/url/icon of website in media notification if website is opened in private mode. + +# 8.0.0 + +* [Commits](https://github.com/mozilla-mobile/android-components/compare/v7.0.0...v8.0.0) +* [Milestone](https://github.com/mozilla-mobile/android-components/milestone/67?closed=1) +* [Dependencies](https://github.com/mozilla-mobile/android-components/blob/v8.0.0/buildSrc/src/main/java/Dependencies.kt) +* [Gecko](https://github.com/mozilla-mobile/android-components/blob/v8.0.0/buildSrc/src/main/java/Gecko.kt) +* [Configuration](https://github.com/mozilla-mobile/android-components/blob/v8.0.0/buildSrc/src/main/java/Config.kt) + +* **service-glean** + * Timing distributions now use a functional bucketing algorithm that does not require fixed limits to be defined up front. + +* **support-android-test** + * Added `WebserverRule` - a junit rule that will run a webserver during tests serving content from assets in the test package ([#3893](https://github.com/mozilla-mobile/android-components/issues/3893)). + +* **browser-engine-gecko-nightly** + * The component now exposes an implementation of the Gecko runtime telemetry delegate, `glean.GeckoAdapter`, which can be used to collect Gecko metrics with the Glean SDK. * **browser-engine-gecko-beta** * The component now handles situations where the Android system kills the content process (without killing the main app process) in order to reclaim resources. In those situations the component will automatically recover and restore the last known state of those sessions. * **browser-toolbar** - * ⚠️ **This is a breaking change**: The `BrowserToolbar.siteSecurityColor` property has been replaced with the setter `BrowserToolbar.setSiteSecurityColor`. - * Added `BrowserToolbar.siteSecurityIcons` to use custom security icons with multiple colors in the toolbar. + * Changed `BrowserToolbar.siteSecurityColor` to use no icon color filter when the color is set to `Color.TRANSPARENT`. + * Added `BrowserToolbar.siteSecurityIcon` to use custom security icons with multiple colors in the toolbar. + +* **feature-sendtab** + * Added a `SendTabFeature` that observes account device events with optional support for push notifications. + + ```kotlin + SendTabFeature( + context, + accountManager, + pushFeature, // optional + pushService // optional; if you want the service to also be started/stopped based on account changes. + onTabsReceiver = { from, tabs -> /* Do cool things here! */ } + ) + ``` + +* **feature-media** + * `MediaFeature` is no longer showing a notification for playing media with a very short duration. + * Lowererd priority of media notification channel to avoid the media notification makign any sounds itself. # 7.0.0 diff --git a/samples/browser/src/main/java/org/mozilla/samples/browser/BrowserFragment.kt b/samples/browser/src/main/java/org/mozilla/samples/browser/BrowserFragment.kt index 995265d6bfa..6e8a7c4af5e 100644 --- a/samples/browser/src/main/java/org/mozilla/samples/browser/BrowserFragment.kt +++ b/samples/browser/src/main/java/org/mozilla/samples/browser/BrowserFragment.kt @@ -42,7 +42,8 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler { components.sessionUseCases.loadUrl) .addSessionProvider(components.sessionManager, components.tabsUseCases.selectTab) .addSearchProvider( - components.searchEngineManager.getDefaultSearchEngine(requireContext()), + requireContext(), + components.searchEngineManager, components.searchUseCases.defaultSearch, fetchClient = components.client, mode = SearchSuggestionProvider.Mode.MULTIPLE_SUGGESTIONS) diff --git a/samples/glean/build.gradle b/samples/glean/build.gradle index 9ff58a491b3..4f52f964a79 100644 --- a/samples/glean/build.gradle +++ b/samples/glean/build.gradle @@ -20,7 +20,7 @@ android { versionCode 1 versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "org.mozilla.samples.glean.GleanTestRunner" } buildTypes { @@ -51,8 +51,10 @@ dependencies { androidTestImplementation Dependencies.androidx_test_runner androidTestImplementation Dependencies.androidx_test_rules androidTestImplementation Dependencies.androidx_test_junit + androidTestImplementation Dependencies.androidx_test_uiautomator androidTestImplementation Dependencies.androidx_espresso_core androidTestImplementation Dependencies.androidx_work_testing + androidTestImplementation Dependencies.testing_mockwebserver } apply from: '../../components/service/glean/scripts/sdk_generator.gradle' diff --git a/samples/glean/src/androidTest/java/org/mozilla/samples/glean/GleanTestRunner.kt b/samples/glean/src/androidTest/java/org/mozilla/samples/glean/GleanTestRunner.kt new file mode 100644 index 00000000000..a9003146d17 --- /dev/null +++ b/samples/glean/src/androidTest/java/org/mozilla/samples/glean/GleanTestRunner.kt @@ -0,0 +1,89 @@ +/* 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.samples.glean + +import androidx.annotation.VisibleForTesting +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.runner.AndroidJUnitRunner +import okhttp3.mockwebserver.Dispatcher +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import okhttp3.mockwebserver.RecordedRequest + +/** + * Create a mock webserver that accepts all requests and replies with "OK". + * @return a [MockWebServer] instance + */ +private fun createMockWebServer(): MockWebServer { + val server = MockWebServer() + server.setDispatcher(object : Dispatcher() { + override fun dispatch(request: RecordedRequest): MockResponse { + return MockResponse().setBody("OK") + } + }) + return server +} + +/** + * Returns the currently active instance of the ping server. + * + * @return the active [MockWebServer] instance + */ +@VisibleForTesting(otherwise = VisibleForTesting.NONE) +internal fun getPingServer(): MockWebServer { + val testRunner: GleanTestRunner = InstrumentationRegistry.getInstrumentation() as GleanTestRunner + return testRunner.pingServer +} + +/** + * Returns the address the local ping server is listening to. + * + * @return a `String` containing the server address. + */ +@VisibleForTesting(otherwise = VisibleForTesting.NONE) +internal fun getPingServerAddress(): String { + val testRunner: GleanTestRunner = InstrumentationRegistry.getInstrumentation() as GleanTestRunner + return testRunner.pingServerAddress!! +} + +/** + * The test runner to be used in the instrumentation tests for the Glean SDK + * sample app in order to point it to a local ping server. + */ +@VisibleForTesting(otherwise = VisibleForTesting.NONE) +class GleanTestRunner : AndroidJUnitRunner() { + // Add a lazy ping server to the app runner. This is only initialized once + // since the `Application` object is re-used. + internal val pingServer: MockWebServer by lazy { createMockWebServer() } + internal var pingServerAddress: String? = null + + init { + // We need to start the server off the main thread, otherwise + // Android will throw a `NetworkOnMainThreadException`. Spawning + // a thread and joining seems fine. + val thread = Thread { + pingServer.start() + pingServerAddress = "http://${pingServer.hostName}:${pingServer.port}" + } + thread.start() + thread.join() + } + + /** + * Called before the application code runs, this starts the ping server. + */ + override fun onStart() { + super.onStart() + pingServer.start() + } + + /** + * Called after the application code cleans up, this stops the ping server. + */ + override fun onDestroy() { + super.onDestroy() + pingServer.shutdown() + } +} diff --git a/samples/glean/src/androidTest/java/org/mozilla/samples/glean/MainActivityTest.kt b/samples/glean/src/androidTest/java/org/mozilla/samples/glean/MainActivityTest.kt index 28db63e9b95..a291449df03 100644 --- a/samples/glean/src/androidTest/java/org/mozilla/samples/glean/MainActivityTest.kt +++ b/samples/glean/src/androidTest/java/org/mozilla/samples/glean/MainActivityTest.kt @@ -10,6 +10,7 @@ import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.rule.ActivityTestRule +import mozilla.components.service.glean.config.Configuration import mozilla.components.service.glean.testing.GleanTestRule import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue @@ -25,7 +26,10 @@ class MainActivityTest { val activityRule: ActivityTestRule = ActivityTestRule(MainActivity::class.java) @get:Rule - val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) + val gleanRule = GleanTestRule( + ApplicationProvider.getApplicationContext(), + Configuration(serverEndpoint = getPingServerAddress()) + ) @Test fun checkGleanClickData() { diff --git a/samples/glean/src/androidTest/java/org/mozilla/samples/glean/pings/BaselinePingTest.kt b/samples/glean/src/androidTest/java/org/mozilla/samples/glean/pings/BaselinePingTest.kt new file mode 100644 index 00000000000..aa3cd92c8ef --- /dev/null +++ b/samples/glean/src/androidTest/java/org/mozilla/samples/glean/pings/BaselinePingTest.kt @@ -0,0 +1,134 @@ +/* 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.samples.glean.pings + +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.rule.ActivityTestRule +import org.junit.Assert.assertEquals + +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.samples.glean.MainActivity +import org.mozilla.samples.glean.getPingServer +import androidx.test.uiautomator.UiDevice +import androidx.work.WorkInfo +import androidx.work.WorkManager +import androidx.work.testing.WorkManagerTestInitHelper +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout +import mozilla.components.service.glean.config.Configuration +import mozilla.components.service.glean.testing.GleanTestRule +import org.json.JSONObject +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.mozilla.samples.glean.getPingServerAddress +import java.util.concurrent.TimeUnit + +@RunWith(AndroidJUnit4::class) +class BaselinePingTest { + @get:Rule + val activityRule: ActivityTestRule = ActivityTestRule(MainActivity::class.java) + + @get:Rule + val gleanRule = GleanTestRule( + ApplicationProvider.getApplicationContext(), + Configuration(serverEndpoint = getPingServerAddress()) + ) + + @Before + fun clearWorkManager() { + val context = ApplicationProvider.getApplicationContext() + WorkManagerTestInitHelper.initializeTestWorkManager(context) + } + + private fun waitForPingContent( + pingName: String, + maxAttempts: Int = 3 + ): JSONObject? + { + val server = getPingServer() + + var attempts = 0 + do { + attempts += 1 + val request = server.takeRequest(20L, TimeUnit.SECONDS) + val docType = request.path.split("/")[3] + if (pingName == docType) { + return JSONObject(request.body.readUtf8()) + } + } while (attempts < maxAttempts) + + return null + } + + /** + * Sadly, the WorkManager still requires us to manually trigger the upload job. + * This function goes through all the active jobs by Glean (there should only be + * one!) and triggers them. + */ + private fun triggerEnqueuedUpload() { + // The tag is really internal to PingUploadWorker, but we can't do much more + // than copy-paste unless we want to increase our API surface. + val tag = "mozac_service_glean_ping_upload_worker" + val reasonablyHighCITimeoutMs = 5000L + + runBlocking { + withTimeout(reasonablyHighCITimeoutMs) { + do { + val workInfoList = WorkManager.getInstance().getWorkInfosByTag(tag).get() + workInfoList.forEach { workInfo -> + if (workInfo.state === WorkInfo.State.ENQUEUED) { + // Trigger WorkManager using TestDriver + val testDriver = WorkManagerTestInitHelper.getTestDriver() + testDriver.setAllConstraintsMet(workInfo.id) + return@withTimeout + } + } + } while (true) + } + } + } + + @Test + fun validateBaselinePing() { + // Wait for the app to be idle/ready. + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + device.waitForIdle() + + // Wait for 1 second: this should guarantee we have some valid duration in the + // ping. + Thread.sleep(1000) + + // Move it to background. + device.pressHome() + + // Wait for the upload job to be present and trigger it. + Thread.sleep(1000) // FIXME: for some reason, without this, WorkManager won't find the job + triggerEnqueuedUpload() + + // Validate the received data. + val baselinePing = waitForPingContent("baseline")!! + assertEquals("baseline", baselinePing.getJSONObject("ping_info")["ping_type"]) + + val metrics = baselinePing.getJSONObject("metrics") + + // Make sure we have a 'duration' field with a reasonable value: it should be >= 1, since + // we slept for 1000ms. + val timespans = metrics.getJSONObject("timespan") + assertTrue(timespans.getJSONObject("glean.baseline.duration").getLong("value") >= 1L) + + // Make sure there's no errors. + val errors = metrics.optJSONObject("labeled_counter")?.keys() + errors?.forEach { + assertFalse(it.startsWith("glean.error.")) + } + } +} diff --git a/samples/glean/src/main/AndroidManifest.xml b/samples/glean/src/main/AndroidManifest.xml index b1715f78ea2..8b6f2f6efef 100644 --- a/samples/glean/src/main/AndroidManifest.xml +++ b/samples/glean/src/main/AndroidManifest.xml @@ -3,12 +3,16 @@ - 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/. --> + + + + + + + + + + + + + + + + + + + + + + + + +