v129
harvey186 2024-08-26 10:00:43 +02:00
parent 331c06960a
commit c64e459308
2730 changed files with 194789 additions and 191263 deletions

0
.buildconfig.yml Executable file → Normal file
View File

0
.editorconfig Executable file → Normal file
View File

0
.gitattributes vendored Executable file → Normal file
View File

78
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,78 @@
name: "🐞 Bug report"
description: Create a report to help us improve.
title: "[Bug]: "
labels: ["🐞 bug", "needs:triage"]
body:
- type: markdown
attributes:
value: |
- Please do your best to search for duplicate issues before filing a new issue so we can keep our issue board clean.
- Have a look at ["I want to file an issue!"][info] for more information.
[info]: https://github.com/fork-maintainers/iceraven-browser#i-want-to-file-an-issue
- type: textarea
attributes:
label: Steps to reproduce
description: Steps to reproduce the behaviour.
placeholder: |
1. Have a tab open..
2. Go to..
3. Click on..
4. Observe..
validations:
required: true
- type: textarea
attributes:
label: Expected behaviour
placeholder: A menu should open..
validations:
required: true
- type: textarea
attributes:
label: Actual behaviour
placeholder: The app closes unexpectedly..
validations:
required: true
- type: markdown
attributes:
value: |
# Device information
- type: input
attributes:
label: Device name
description: The name of the device model and manufacturer.
placeholder: Google Pixel 2
validations:
required: false
- type: input
attributes:
label: Android version
description: You can find the Android version information in the About section of your device's system settings.
placeholder: Android 10
validations:
required: true
- type: input
attributes:
label: Iceraven version
description: You can find this information in Settings -> About Iceraven.
placeholder: 2.22.0
validations:
required: true
- type: textarea
attributes:
label: Device logs
description: |
Device logs or crash information can greatly aid in debugging. You can find some details here on how to [retrieve device logs or crash IDs][log].
[log]: https://github.com/fork-maintainers/iceraven-browser/blob/iceraven/docs/Logging-Crash-Information.md
validations:
required: false
- type: textarea
attributes:
label: Additional information
description: |
If you have any additional information for us, use the field below.
Please note, you can attach screenshots or screen recordings here, by
dragging and dropping files in the field below.
validations:
required: false

View File

@ -0,0 +1,40 @@
name: "⭐️ Feature request"
description: Suggest an idea for this project
title: "[Feature Request]: "
labels: ["🌟 feature request"]
body:
- type: markdown
attributes:
value: |
- Please do your best to search for duplicate issues before filing a new issue so we can keep our issue board clean
- Every issue should have exactly one feature request described in it. Please do not file feedback list tickets as it is difficult to parse them and address their individual points
- Feature Requests are better when theyre open-ended instead of demanding a specific solution e.g: “I want an easier way to do X” instead of “add Y”
- Read https://github.com/fork-maintainers/iceraven-browser#i-want-to-file-an-issue for more information
- type: textarea
attributes:
label: Feature Summary
description: What is the user problem or growth opportunity you want to see solved?
validations:
required: true
- type: textarea
attributes:
label: Feature Research
description: How do you know that this problem exists today? Why is this important?
validations:
required: true
- type: textarea
attributes:
label: Alternative Solution
description: Other possible solutions, if any.
validations:
required: false
- type: textarea
attributes:
label: Target beneficiaries
description: Who will benefit from it?
validations:
required: true

0
.github/workflows/ci.yml vendored Executable file → Normal file
View File

0
.github/workflows/disabled_workflows/build-contributor-pr.yml vendored Executable file → Normal file
View File

0
.github/workflows/disabled_workflows/fenix-sync-strings.yml vendored Executable file → Normal file
View File

0
.github/workflows/disabled_workflows/fenix-update-ac.yml vendored Executable file → Normal file
View File

View File

0
.github/workflows/disabled_workflows/glean-probe-scraper.yml vendored Executable file → Normal file
View File

0
.github/workflows/disabled_workflows/issue-linker.yml vendored Executable file → Normal file
View File

0
.github/workflows/disabled_workflows/milestone.yml vendored Executable file → Normal file
View File

0
.github/workflows/disabled_workflows/qa-needed.yml vendored Executable file → Normal file
View File

0
.github/workflows/disabled_workflows/reopen-for-qa-needed.yml vendored Executable file → Normal file
View File

0
.github/workflows/release.yml vendored Executable file → Normal file
View File

0
.gitignore vendored Executable file → Normal file
View File

0
.gitmodules vendored Executable file → Normal file
View File

0
CODE_OF_CONDUCT.md Executable file → Normal file
View File

0
Gemfile Executable file → Normal file
View File

0
Jenkinsfile vendored Executable file → Normal file
View File

22
README.md Executable file → Normal file
View File

@ -1,8 +1,8 @@
# Iceraven Browser! [![CI](https://github.com/fork-maintainers/iceraven-browser/actions/workflows/ci.yml/badge.svg)](https://github.com/fork-maintainers/iceraven-browser/actions/workflows/ci.yml) ![Release](https://img.shields.io/github/v/release/fork-maintainers/iceraven-browser) # LeOSium Browser! [![CI](https://github.com/fork-maintainers/iceraven-browser/actions/workflows/ci.yml/badge.svg)](https://github.com/fork-maintainers/iceraven-browser/actions/workflows/ci.yml) ![Release](https://img.shields.io/github/v/release/fork-maintainers/iceraven-browser)
Definitely not brought to you by Mozilla! Definitely not brought to you by Mozilla!
Iceraven Browser is a web browser for Android, based on [Mozilla's Fenix version of Firefox](https://github.com/mozilla-mobile/fenix/), [GeckoView](https://mozilla.github.io/geckoview/) and [Mozilla Android Components](https://mozac.org/). LeOSium Browser is a web browser for Android, based on [Mozilla's Fenix version of Firefox](https://github.com/mozilla-mobile/fenix/), [GeckoView](https://mozilla.github.io/geckoview/) and [Mozilla Android Components](https://mozac.org/).
Our goal is to be a close fork of the new Firefox for Android that seeks to provide users with more options, more opportunities to customize (including a broad extension library), and more information about the pages they visit and how their browsers are interacting with those pages. Our goal is to be a close fork of the new Firefox for Android that seeks to provide users with more options, more opportunities to customize (including a broad extension library), and more information about the pages they visit and how their browsers are interacting with those pages.
@ -11,15 +11,15 @@ Notable features include:
* The ability to *attempt* to install a much longer list of add-ons than Mozilla's Fenix version of Firefox accepts. Currently the browser queries [this AMO collection](https://addons.mozilla.org/en-US/firefox/collections/16201230/What-I-want-on-Fenix/) **Most of them will not work**, because they depend on code that Mozilla is still working on writing in `android-components`, but you may attempt to install them. If you don't see an add-on you want, you can [request it](https://github.com/fork-maintainers/iceraven-browser/issues/new). * The ability to *attempt* to install a much longer list of add-ons than Mozilla's Fenix version of Firefox accepts. Currently the browser queries [this AMO collection](https://addons.mozilla.org/en-US/firefox/collections/16201230/What-I-want-on-Fenix/) **Most of them will not work**, because they depend on code that Mozilla is still working on writing in `android-components`, but you may attempt to install them. If you don't see an add-on you want, you can [request it](https://github.com/fork-maintainers/iceraven-browser/issues/new).
* Option to suspend tabs to avoid being killed for memory (https://bugzilla.mozilla.org/show_bug.cgi?id=1807364) * Option to suspend tabs to avoid being killed for memory (https://bugzilla.mozilla.org/show_bug.cgi?id=1807364)
* Option not to display recently visited websites at HomePage * Option not to display recently visited websites at HomePage
* **No warranties or guarantees of security or updates or even stability**! Note that Iceraven Browser includes some unstable code written by Mozilla, with our own added modifications on top, all shipped with the stable version of GeckoView engine. Hence, the browser may contain bugs introduced upstream. Binaries are currently built automatically by our Github release automation. These binaries are signed with a debug key. When we finally publish this somewhere official like F-droid, we will sign the apks with a proper key suitable for public release. Due to the current way we create the releases and sign them, you may not want to rely on such "alpha" quality software as your primary web browser, as it will have bugs. So, use this browser only if you are comfortable with these limitations/potential risks. * **No warranties or guarantees of security or updates or even stability**! Note that LeOSium Browser includes some unstable code written by Mozilla, with our own added modifications on top, all shipped with the stable version of GeckoView engine. Hence, the browser may contain bugs introduced upstream. Binaries are currently built automatically by our Github release automation. These binaries are signed with a debug key. When we finally publish this somewhere official like F-droid, we will sign the apks with a proper key suitable for public release. Due to the current way we create the releases and sign them, you may not want to rely on such "alpha" quality software as your primary web browser, as it will have bugs. So, use this browser only if you are comfortable with these limitations/potential risks.
**Note/Disclaimer:** Iceraven Browser could not exist without the hardworking folks at the Mozilla Corporation who work on the Mozilla Android Components and Firefox projects, but it is not an official Mozilla product, and is not provided, endorsed, vetted, approved, or secured by Mozilla. **Note/Disclaimer:** LeOSium Browser could not exist without the hardworking folks at the Mozilla Corporation who work on the Mozilla Android Components and Firefox projects, but it is not an official Mozilla product, and is not provided, endorsed, vetted, approved, or secured by Mozilla.
In addition, we intend to try to cut down on telemetry and proprietary code to as great of an extent as possible as long as doing so does not compromise the user experience or make the fork too hard to maintain. Right now, we believe that no telemetry should be being sent to Mozilla anymore, but we cannot guarantee this; data may still be sent. Because of the way we have implemented this, the app may still appear to contain trackers when analyzed by tools that look for the presence of known tracking libraries. These detected trackers should actually be non-functional substitutes, many of which are sourced [from here](https://gitlab.com/relan/fennecbuild/-/blob/master/fenix-liberate.patch). **If you catch the app actually sending data to Mozilla, Adjust, Leanplum, Firebase, or any other such service, please open an issue!** Presumably any data that reaches Mozilla is governed by Mozilla's privacy policy, but as Iceraven Browser is, again **not a Mozilla product**, we can make no promises. In addition, we intend to try to cut down on telemetry and proprietary code to as great of an extent as possible as long as doing so does not compromise the user experience or make the fork too hard to maintain. Right now, we believe that no telemetry should be being sent to Mozilla anymore, but we cannot guarantee this; data may still be sent. Because of the way we have implemented this, the app may still appear to contain trackers when analyzed by tools that look for the presence of known tracking libraries. These detected trackers should actually be non-functional substitutes, many of which are sourced [from here](https://gitlab.com/relan/fennecbuild/-/blob/master/fenix-liberate.patch). **If you catch the app actually sending data to Mozilla, Adjust, Leanplum, Firebase, or any other such service, please open an issue!** Presumably any data that reaches Mozilla is governed by Mozilla's privacy policy, but as LeOSium Browser is, again **not a Mozilla product**, we can make no promises.
Iceraven Browser combines the power of Fenix (of which we are a fork) and the spirit of Fennec, with a respectful nod toward the grand tradition of Netscape Navigator, from which all Gecko-based projects came, including the earliest of our predecessors, the old Mozilla Phoenix and Mozilla Firefox desktop browsers. LeOSium Browser combines the power of Fenix (of which we are a fork) and the spirit of Fennec, with a respectful nod toward the grand tradition of Netscape Navigator, from which all Gecko-based projects came, including the earliest of our predecessors, the old Mozilla Phoenix and Mozilla Firefox desktop browsers.
That said, Iceraven Browser is an independent all-volunteer project, and has no affiliation with Netscape, Netscape Navigator, Mozilla, Mozilla Firefox, Mozila Phoenix, Debian, Debian Iceweasel, Parabola GNU/Linux-libre Iceweasel, America Online, or Verizon, among others. :) Basically, if you don't like the browser, it's not their fault. :) That said, LeOSium Browser is an independent all-volunteer project, and has no affiliation with Netscape, Netscape Navigator, Mozilla, Mozilla Firefox, Mozila Phoenix, Debian, Debian Iceweasel, Parabola GNU/Linux-libre Iceweasel, America Online, or Verizon, among others. :) Basically, if you don't like the browser, it's not their fault. :)
## 📥 Installation ## 📥 Installation
@ -27,11 +27,9 @@ Right now, releases are published as `.apk` files, through Github. You should do
1. **Determine what version you need**. If you have a newer, 64-bit device, or a device with more than 4 GB of memory, you probably want the `arm64-v8a` version. **Any ordinary phone or tablet should be able to use the `armeabi-v7a` version**, but it will be limited to using no more than 4 GB of memory. You almost certainly don't want the `x86` or `x86_64` versions; they are in case you are running Android on a PC. 1. **Determine what version you need**. If you have a newer, 64-bit device, or a device with more than 4 GB of memory, you probably want the `arm64-v8a` version. **Any ordinary phone or tablet should be able to use the `armeabi-v7a` version**, but it will be limited to using no more than 4 GB of memory. You almost certainly don't want the `x86` or `x86_64` versions; they are in case you are running Android on a PC.
2. [**Download the APK for the latest release from the Releases page**](https://github.com/fork-maintainers/iceraven-browser/releases). Make sure to pick the version you chose in step 1. 3. **Install the APK**. You will need to enable installation of apps from "unknown" (to Google) sources, and installatiuon of apps *by* whatever app you used to open the downloaded APK (i.e. your browser or file manager). Android will try to dissuade you from doing this, and suggest that it is dangerous. LeOSium is a browser for people who enjoy danger.
3. **Install the APK**. You will need to enable installation of apps from "unknown" (to Google) sources, and installatiuon of apps *by* whatever app you used to open the downloaded APK (i.e. your browser or file manager). Android will try to dissuade you from doing this, and suggest that it is dangerous. Iceraven is a browser for people who enjoy danger. 4. **Enjoy LeOSium**. Make sure to install the add-ons that are essential for you in the main menu under "Add-Ons". You may want to set LeOSium as your device's default browser app. If you do this, it will be able to provide so-called "Chrome" [custom tabs](https://developers.google.com/web/android/custom-tabs) for other applications, allowing you to use your add-ons there.
4. **Enjoy Iceraven**. Make sure to install the add-ons that are essential for you in the main menu under "Add-Ons". You may want to set Iceraven as your device's default browser app. If you do this, it will be able to provide so-called "Chrome" [custom tabs](https://developers.google.com/web/android/custom-tabs) for other applications, allowing you to use your add-ons there.
## 🔨 Building ## 🔨 Building
@ -78,7 +76,7 @@ cd iceraven-browser
echo "autosignReleaseWithDebugKey=" >> local.properties echo "autosignReleaseWithDebugKey=" >> local.properties
``` ```
6. Build the project. To build the Iceraven-branded release APKs, you can do: 6. Build the project. To build the LeOSium-branded release APKs, you can do:
```sh ```sh
./gradlew app:assemblefenixForkRelease -PversionName="$(git describe --tags HEAD)" ./gradlew app:assemblefenixForkRelease -PversionName="$(git describe --tags HEAD)"

0
SECURITY.md Executable file → Normal file
View File

@ -1 +0,0 @@
Subproject commit f03a5f2688acc3faffe488c75cea6658d079fea3

0
app/.experimenter.yaml Executable file → Normal file
View File

0
app/.gitignore vendored Executable file → Normal file
View File

0
app/benchmark.gradle Executable file → Normal file
View File

126
app/build.gradle Executable file → Normal file
View File

@ -1,17 +1,43 @@
import com.android.build.api.variant.FilterConfiguration import com.android.build.api.variant.FilterConfiguration
import org.apache.tools.ant.util.StringUtils import org.apache.tools.ant.util.StringUtils
buildscript {
repositories {
gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
maven {
url repository
if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) {
allowInsecureProtocol = true
}
}
}
}
dependencies {
classpath ComponentsDependencies.plugin_serialization
}
}
plugins { plugins {
id "com.jetbrains.python.envs" version "$python_envs_plugin" id "com.jetbrains.python.envs" version "$python_envs_plugin"
id "com.google.protobuf" version "$protobuf_plugin" id "com.google.protobuf" version "$protobuf_plugin"
} }
if (findProject(":geckoview") != null) {
buildDir "${topobjdir}/gradle/build/mobile/android/fenix"
}
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize' apply plugin: 'kotlin-parcelize'
apply plugin: 'jacoco' apply plugin: 'jacoco'
apply plugin: 'androidx.navigation.safeargs.kotlin' apply plugin: 'androidx.navigation.safeargs.kotlin'
apply plugin: 'com.google.android.gms.oss-licenses-plugin' apply plugin: 'com.google.android.gms.oss-licenses-plugin'
apply plugin: 'kotlinx-serialization'
if (findProject(":geckoview") != null) {
apply from: "${topsrcdir}/mobile/android/gradle/product_flavors.gradle"
}
import groovy.json.JsonOutput import groovy.json.JsonOutput
import org.gradle.internal.logging.text.StyledTextOutput.Style import org.gradle.internal.logging.text.StyledTextOutput.Style
@ -42,7 +68,7 @@ android {
testInstrumentationRunnerArguments clearPackageData: 'true' testInstrumentationRunnerArguments clearPackageData: 'true'
resValue "bool", "IS_DEBUG", "false" resValue "bool", "IS_DEBUG", "false"
buildConfigField "boolean", "USE_RELEASE_VERSIONING", "false" buildConfigField "boolean", "USE_RELEASE_VERSIONING", "false"
buildConfigField "String", "GIT_HASH", "\"\"" // see override in release builds for why it's blank. buildConfigField "String", "VCS_HASH", "\"\"" // see override in release builds for why it's blank.
// This should be the "public" base URL of AMO. // This should be the "public" base URL of AMO.
buildConfigField "String", "AMO_BASE_URL", "\"https://addons.mozilla.org\"" buildConfigField "String", "AMO_BASE_URL", "\"https://addons.mozilla.org\""
buildConfigField "String", "AMO_COLLECTION_NAME", "\"Extensions-for-Android\"" buildConfigField "String", "AMO_COLLECTION_NAME", "\"Extensions-for-Android\""
@ -95,8 +121,8 @@ android {
matchingFallbacks = ['release'] // Use on the "release" build type in dependencies (AARs) matchingFallbacks = ['release'] // Use on the "release" build type in dependencies (AARs)
// Changing the build config can cause files that depend on BuildConfig.java to recompile // Changing the build config can cause files that depend on BuildConfig.java to recompile
// so we only set the git hash in release builds to avoid possible recompilation in debug builds. // so we only set the vcs hash in release builds to avoid possible recompilation in debug builds.
// buildConfigField "String", "GIT_HASH", "\"${Config.getGitHash()}\"" buildConfigField "String", "VCS_HASH", "\"${Config.getVcsHash()}\""
if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) { if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) {
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
@ -221,6 +247,11 @@ android {
animationsDisabled = true animationsDisabled = true
} }
if (findProject(":geckoview") != null) {
project.configureProductFlavors.delegate = it
project.configureProductFlavors()
}
flavorDimensions.add("product") flavorDimensions.add("product")
productFlavors { productFlavors {
@ -275,8 +306,8 @@ android {
} }
packagingOptions { packagingOptions {
resources { resources {
excludes += ['META-INF/atomicfu.kotlin_module', 'META-INF/AL2.0', 'META-INF/LGPL2.1', excludes += ['MANIFEST.MF', 'META-INF/atomicfu.kotlin_module', 'META-INF/AL2.0',
'META-INF/LICENSE.md', 'META-INF/LICENSE-notice.md'] 'META-INF/LGPL2.1', 'META-INF/LICENSE.md', 'META-INF/LICENSE-notice.md']
} }
jniLibs { jniLibs {
useLegacyPackaging true useLegacyPackaging true
@ -330,7 +361,9 @@ android.applicationVariants.configureEach { variant ->
// same version code. Therefore we need to have different version codes for our ARM and x86 // same version code. Therefore we need to have different version codes for our ARM and x86
// builds. // builds.
// def versionName = variant.buildType.name == 'nightly' ? Config.nightlyVersionName() : Config.releaseVersionName(project) // def versionName = variant.buildType.name == 'nightly' ?
// "${Config.nightlyVersionName(project)}" :
// "${Config.releaseVersionName(project)}"
// println("versionName override: $versionName") // println("versionName override: $versionName")
variant.outputs.each { output -> variant.outputs.each { output ->
@ -539,7 +572,21 @@ nimbus {
fenixRelease: "release", fenixRelease: "release",
fenixForkDebug: "forkDebug", fenixForkDebug: "forkDebug",
fenixForkRelease: "forkRelease", fenixForkRelease: "forkRelease",
fenixBenchmark: "developer" fenixBenchmark: "developer",
withGeckoBinariesFenixDebug: "developer",
withGeckoBinariesFenixNightly: "nightly",
withGeckoBinariesFenixBeta: "beta",
withGeckoBinariesFenixRelease: "release",
withGeckoBinariesFenixForkDebug: "forkDebug",
withGeckoBinariesFenixForkRelease: "forkRelease",
withGeckoBinariesFenixBenchmark: "developer",
withoutGeckoBinariesFenixDebug: "developer",
withoutGeckoBinariesFenixNightly: "nightly",
withoutGeckoBinariesFenixBeta: "beta",
withoutGeckoBinariesFenixRelease: "release",
withoutGeckoBinariesFenixForkDebug: "forkDebug",
withoutGeckoBinariesFenixForkRelease: "forkRelease",
withoutGeckoBinariesFenixBenchmark: "developer",
] ]
// This is generated by the FML and should be checked into git. // This is generated by the FML and should be checked into git.
// It will be fetched by Experimenter (the Nimbus experiment website) // It will be fetched by Experimenter (the Nimbus experiment website)
@ -554,6 +601,8 @@ tasks.withType(KotlinCompile).configureEach {
} }
dependencies { dependencies {
implementation ComponentsDependencies.kotlin_json
implementation platform(ComponentsDependencies.androidx_compose_bom) implementation platform(ComponentsDependencies.androidx_compose_bom)
androidTestImplementation platform(ComponentsDependencies.androidx_compose_bom) androidTestImplementation platform(ComponentsDependencies.androidx_compose_bom)
@ -670,7 +719,6 @@ dependencies {
implementation ComponentsDependencies.androidx_compose_animation implementation ComponentsDependencies.androidx_compose_animation
implementation ComponentsDependencies.androidx_compose_foundation implementation ComponentsDependencies.androidx_compose_foundation
implementation ComponentsDependencies.androidx_compose_material implementation ComponentsDependencies.androidx_compose_material
implementation FenixDependencies.androidx_legacy
implementation ComponentsDependencies.androidx_biometric implementation ComponentsDependencies.androidx_biometric
implementation ComponentsDependencies.androidx_paging implementation ComponentsDependencies.androidx_paging
implementation ComponentsDependencies.androidx_preferences implementation ComponentsDependencies.androidx_preferences
@ -679,6 +727,7 @@ dependencies {
implementation ComponentsDependencies.androidx_navigation_ui implementation ComponentsDependencies.androidx_navigation_ui
implementation ComponentsDependencies.androidx_compose_navigation implementation ComponentsDependencies.androidx_compose_navigation
implementation ComponentsDependencies.androidx_recyclerview implementation ComponentsDependencies.androidx_recyclerview
implementation ComponentsDependencies.androidx_swiperefreshlayout
implementation ComponentsDependencies.androidx_lifecycle_common implementation ComponentsDependencies.androidx_lifecycle_common
implementation ComponentsDependencies.androidx_lifecycle_livedata implementation ComponentsDependencies.androidx_lifecycle_livedata
@ -691,45 +740,37 @@ dependencies {
implementation ComponentsDependencies.androidx_core_ktx implementation ComponentsDependencies.androidx_core_ktx
implementation FenixDependencies.androidx_core_splashscreen implementation FenixDependencies.androidx_core_splashscreen
implementation FenixDependencies.androidx_transition implementation FenixDependencies.androidx_transition
implementation FenixDependencies.androidx_viewpager2
implementation ComponentsDependencies.androidx_work_runtime implementation ComponentsDependencies.androidx_work_runtime
implementation FenixDependencies.androidx_datastore implementation ComponentsDependencies.androidx_datastore
implementation ComponentsDependencies.androidx_data_store_preferences implementation ComponentsDependencies.androidx_datastore_preferences
implementation FenixDependencies.protobuf_javalite implementation FenixDependencies.protobuf_javalite
implementation ComponentsDependencies.google_material implementation ComponentsDependencies.google_material
androidTestImplementation ComponentsDependencies.androidx_test_uiautomator constraints {
implementation (ComponentsDependencies.androidx_tracing) {
because 'AndroidX Test gets force-downgraded to 1.0.0 and breaks otherwise'
}
}
androidTestImplementation FenixDependencies.fastlane androidTestImplementation FenixDependencies.fastlane
// This Falcon version is added to maven central now required for Screengrab // This Falcon version is added to maven central now required for Screengrab
androidTestImplementation FenixDependencies.falcon androidTestImplementation FenixDependencies.falcon
androidTestImplementation ComponentsDependencies.androidx_compose_ui_test androidTestImplementation(ComponentsDependencies.androidx_espresso_contrib) {
androidTestImplementation ComponentsDependencies.androidx_espresso_core, {
exclude group: 'com.android.support', module: 'support-annotations'
}
androidTestImplementation(FenixDependencies.espresso_contrib) {
exclude module: 'appcompat-v7'
exclude module: 'support-v4'
exclude module: 'support-annotations'
exclude module: 'recyclerview-v7'
exclude module: 'design'
exclude module: 'espresso-core'
exclude module: 'protobuf-lite' exclude module: 'protobuf-lite'
} }
androidTestImplementation ComponentsDependencies.androidx_espresso_core
androidTestImplementation ComponentsDependencies.androidx_espresso_idling_resource
androidTestImplementation ComponentsDependencies.androidx_espresso_intents
androidTestImplementation ComponentsDependencies.androidx_test_core androidTestImplementation ComponentsDependencies.androidx_test_core
androidTestImplementation FenixDependencies.espresso_idling_resources
androidTestImplementation FenixDependencies.espresso_intents
androidTestImplementation ComponentsDependencies.androidx_test_runner
androidTestImplementation ComponentsDependencies.androidx_test_rules
androidTestUtil FenixDependencies.orchestrator
androidTestImplementation ComponentsDependencies.androidx_espresso_core, {
exclude group: 'com.android.support', module: 'support-annotations'
}
androidTestImplementation ComponentsDependencies.androidx_test_junit androidTestImplementation ComponentsDependencies.androidx_test_junit
androidTestImplementation ComponentsDependencies.androidx_test_rules
androidTestImplementation ComponentsDependencies.androidx_test_runner
androidTestImplementation ComponentsDependencies.androidx_test_uiautomator
androidTestUtil ComponentsDependencies.androidx_test_orchestrator
androidTestImplementation ComponentsDependencies.androidx_compose_ui_test
androidTestImplementation ComponentsDependencies.androidx_work_testing androidTestImplementation ComponentsDependencies.androidx_work_testing
androidTestImplementation FenixDependencies.androidx_benchmark_junit4 androidTestImplementation FenixDependencies.androidx_benchmark_junit4
androidTestImplementation ComponentsDependencies.testing_mockwebserver androidTestImplementation ComponentsDependencies.testing_mockwebserver
@ -751,7 +792,7 @@ dependencies {
// depend on a separate library for unit tests. This will be removed in future releases. // depend on a separate library for unit tests. This will be removed in future releases.
testImplementation "org.mozilla.telemetry:glean-native-forUnitTests:${project.ext.glean_version}" testImplementation "org.mozilla.telemetry:glean-native-forUnitTests:${project.ext.glean_version}"
lintChecks project(":mozilla-lint-rules") lintPublish project(":mozilla-lint-rules")
lintChecks project(':tooling-lint') lintChecks project(':tooling-lint')
} }
@ -880,8 +921,8 @@ afterEvaluate {
break break
case ResultType.FAILURE: case ResultType.FAILURE:
out.style(Style.Failure).println(" FAILURE") def testId = descriptor.getClassName() + "." + descriptor.getName()
logger.lifecycle("", result.getException()) out.style(Style.Failure).println(" TEST-UNEXPECTED-FAIL | " + testId + " | " + result.getException())
break break
case ResultType.SKIPPED: case ResultType.SKIPPED:
@ -897,15 +938,10 @@ if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopsrcd
if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopobjdir')) { if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopobjdir')) {
ext.topobjdir = gradle."localProperties.dependencySubstitutions.geckoviewTopobjdir" ext.topobjdir = gradle."localProperties.dependencySubstitutions.geckoviewTopobjdir"
} }
ext.topsrcdir = StringUtils.removeSuffix(gradle."localProperties.dependencySubstitutions.geckoviewTopsrcdir", File.separator) ext.topsrcdir = gradle."localProperties.dependencySubstitutions.geckoviewTopsrcdir"
apply from: "${topsrcdir}/substitute-local-geckoview.gradle" apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
} }
if (gradle.hasProperty('localProperties.autoPublish.glean.dir')) {
ext.gleanSrcDir = gradle."localProperties.autoPublish.glean.dir"
apply from: "../${gleanSrcDir}/build-scripts/substitute-local-glean.gradle"
}
android.applicationVariants.configureEach { variant -> android.applicationVariants.configureEach { variant ->
tasks.register("apkSize${variant.name.capitalize()}", ApkSizeTask) { tasks.register("apkSize${variant.name.capitalize()}", ApkSizeTask) {
variantName = variant.name variantName = variant.name
@ -934,4 +970,4 @@ def getSupportedLocales() {
} }
// Enable expiration by major version. // Enable expiration by major version.
ext.gleanExpireByVersion = 26 ext.gleanExpireByVersion = 29

1565
app/lint-baseline.xml Executable file → Normal file

File diff suppressed because it is too large Load Diff

8
app/lint.xml Executable file → Normal file
View File

@ -46,15 +46,15 @@
<issue id="UselessLeaf" severity="error" /> <issue id="UselessLeaf" severity="error" />
<issue id="UselessParent" severity="error" /> <issue id="UselessParent" severity="error" />
<issue id="UnusedNamespace" severity="error" /> <issue id="UnusedNamespace" severity="error" />
<!-- Performance: checks we'd like to eventually set to error. -->
<issue id="UseCompoundDrawables" severity="warning" />
<issue id="Overdraw" severity="warning" />
<issue id="UnusedResources" severity="error"> <issue id="UnusedResources" severity="error">
<!-- Using an automated process to remove localized strings after they are removed from the default strings.xml <!-- Using an automated process to remove localized strings after they are removed from the default strings.xml
means the files for localized strings will contain unused resources for a few days after the original removal operation. --> means the files for localized strings will contain unused resources for a few days after the original removal operation. -->
<ignore path="**/values-*/strings.xml" /> <ignore path="**/values-*/strings.xml" />
</issue> </issue>
<issue id="UseCompoundDrawables" severity="error" />
<!-- Performance: checks we'd like to eventually set to error. -->
<issue id="Overdraw" severity="warning" />
<!-- Performance: checks that we're unsure of the value of that we might want to investigate. --> <!-- Performance: checks that we're unsure of the value of that we might want to investigate. -->
<issue id="UnpackedNativeCode" severity="informational" /> <issue id="UnpackedNativeCode" severity="informational" />

57
app/messaging-evergreen-messages.fml.yaml Executable file → Normal file
View File

@ -35,7 +35,6 @@ import:
- I_AM_DEFAULT_BROWSER - I_AM_DEFAULT_BROWSER
style: PERSISTENT style: PERSISTENT
button-label: preferences_set_as_default_browser button-label: preferences_set_as_default_browser
triggers: triggers:
USER_ESTABLISHED_INSTALL: "number_of_app_launches >=4" USER_ESTABLISHED_INSTALL: "number_of_app_launches >=4"
@ -53,3 +52,59 @@ import:
exclude-if-any: exclude-if-any:
- I_AM_DEFAULT_BROWSER - I_AM_DEFAULT_BROWSER
action: MAKE_DEFAULT_BROWSER action: MAKE_DEFAULT_BROWSER
# This message displays as a microsurvey prompt after the user taps on the `Print` menu.
- channel: developer
value:
messages:
microsurvey-printing-example:
title: microsurvey_prompt_printing_title
text: microsurvey_survey_printing_title
surface: microsurvey
trigger-if-all:
- RECENTLY_PRINTED
style: MICRO_SURVEY
microsurvey-config:
utm-content: "homepage"
icon: ic_print
answers:
- text: likert_scale_option_1
ordering: 0
- text: likert_scale_option_2
ordering: 1
- text: likert_scale_option_3
ordering: 2
- text: likert_scale_option_4
ordering: 3
- text: likert_scale_option_5
ordering: 4
- text: likert_scale_option_6
ordering: 5
# This message displays as a microsurvey prompt after the users tap on the `Print` menu.
- channel: nightly
value:
messages:
microsurvey-printing-example:
title: microsurvey_prompt_printing_title
text: microsurvey_survey_printing_title
surface: microsurvey
trigger-if-all:
- RECENTLY_PRINTED
style: MICRO_SURVEY
microsurvey-config:
utm-content: "homepage"
icon: ic_print
answers:
- text: likert_scale_option_1
ordering: 0
- text: likert_scale_option_2
ordering: 1
- text: likert_scale_option_3
ordering: 2
- text: likert_scale_option_4
ordering: 3
- text: likert_scale_option_5
ordering: 4
- text: likert_scale_option_6
ordering: 5

9
app/messaging-fenix.fml.yaml Executable file → Normal file
View File

@ -44,6 +44,11 @@ import:
INACTIVE_4_DAYS: "'app_launched'|eventLastSeen('Days', 0) >= 4" INACTIVE_4_DAYS: "'app_launched'|eventLastSeen('Days', 0) >= 4"
INACTIVE_5_DAYS: "'app_launched'|eventLastSeen('Days', 0) >= 5" INACTIVE_5_DAYS: "'app_launched'|eventLastSeen('Days', 0) >= 5"
# Behavioral Targeting Events
# See https://experimenter.info/mobile-behavioral-targeting for more info
RECENTLY_PRINTED: "'print_tapped'|eventLastSeen('Hours') <= 24"
SECOND_HOMEPAGE_VIEW: "'home_screen_displayed'|eventSum('Years', 4, 0) >= 2"
# Has the user signed in the last 4 years # Has the user signed in the last 4 years
FXA_SIGNED_IN: "'sync_auth.sign_in'|eventLastSeen('Years', 0) <= 4" FXA_SIGNED_IN: "'sync_auth.sign_in'|eventLastSeen('Years', 0) <= 4"
FXA_NOT_SIGNED_IN: "'sync_auth.sign_in'|eventLastSeen('Years', 0) > 4" FXA_NOT_SIGNED_IN: "'sync_auth.sign_in'|eventLastSeen('Years', 0) > 4"
@ -94,10 +99,14 @@ import:
NOTIFICATION: NOTIFICATION:
priority: 50 priority: 50
max-display-count: 1 max-display-count: 1
MICRO_SURVEY:
priority: 50
max-display-count: 5
$$surfaces: $$surfaces:
- homescreen - homescreen
- notification - notification
- survey - survey
- microsurvey
- channel: developer - channel: developer
value: value:

563
app/metrics.yaml Executable file → Normal file
View File

@ -212,6 +212,7 @@ events:
expires: never expires: never
marketing_notification_allowed: marketing_notification_allowed:
type: boolean type: boolean
lifetime: application
description: | description: |
True if marketing notifications are allowed, otherwise false. True if marketing notifications are allowed, otherwise false.
bugs: bugs:
@ -854,7 +855,9 @@ events:
notification_emails: notification_emails:
- android-probes@mozilla.com - android-probes@mozilla.com
expires: never expires: never
translations_action:
translations:
action:
type: event type: event
description: | description: |
An area inside the translations feature was tapped. An area inside the translations feature was tapped.
@ -866,18 +869,126 @@ events:
A string containing the name of the item the user tapped. These items A string containing the name of the item the user tapped. These items
include: include:
main_flow_toolbar, main_flow_browser, page_settings, global_settings, main_flow_toolbar, main_flow_browser, page_settings, global_settings,
global_lang_settings, global_site_settings, downloads global_lang_settings, global_site_settings, downloads, global_settings_from_preferences
type: string type: string
bugs: bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1883968 - https://bugzilla.mozilla.org/show_bug.cgi?id=1883968
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886851
- https://bugzilla.mozilla.org/show_bug.cgi?id=1890838
data_reviews: data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1883968#c6 - https://bugzilla.mozilla.org/show_bug.cgi?id=1883968#c6
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886851#c8
data_sensitivity: data_sensitivity:
- interaction - interaction
notification_emails: notification_emails:
- android-probes@mozilla.com - android-probes@mozilla.com
expires: never expires: never
offer_event:
type: event
description: |
The translations engine decided the user may be interested in a translation or that the user
should be offered a translation.
An "expected" event means the user is expected to want to translate and we should show the feature on the toolbar.
An "offer" event means we should popup the translations dialog.
extra_keys:
item:
description: |
A string containing the type of signal sent by the translations engine.
These signals include:
expected, offer
type: string
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886851
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886851#c8
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
translate_requested:
type: event
description: |
The user requested a translation of the page.
extra_keys:
to_language:
description: |
A string containing the BCP 47 that the user is translating the page to. Predefined based
on published translation models. For example, possible values are:
"en", "es", "fr", and all other translations engine "to" language codes.
type: string
from_language:
description: |
A string containing the BCP 47 that the user is translating the page from. Predefined based
on published translation models. For example, possible values are:
"en", "es", "fr", and all other translations engine "from" language codes.
type: string
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886221
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886221#c3
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
translate_success:
type: event
description: |
The user requested a translation of the page and it completed successfully.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886221
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886221#c3
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
translate_failed:
type: event
description: |
The user requested a translation of the page and it failed.
extra_keys:
error:
description: |
A string containing the name of the error that occurred. Possible values are predefined
in TranslationError and include:
unknown, unexpected-null, missing-session-coordinator, engine-not-supported, unknown-engine-support
could-not-translate, could-not-restore, could-not-determine-translation-download-size, could-not-load-languages,
could-not-load-settings, could-not-load-language-settings, could-not-load-never-translate-sites,
language-not-supported, model-could-not-retrieve, model-could-not-delete, model-could-not-download,
model-language-required, model-download-required
type: string
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886221
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886221#c3
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
engine_supported:
type: event
description: |
The translations engine for translating pages is only supported on certain devices.
This probe indicates if the device supports the translations engine or not.
extra_keys:
support:
description: |
A string describing the support of the engine, either:
supported, unsupported,
type: string
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886221
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1886221#c3
data_sensitivity:
- technical
notification_emails:
- android-probes@mozilla.com
expires: never
splash_screen: splash_screen:
first_launch_extended: first_launch_extended:
type: event type: event
@ -1563,6 +1674,22 @@ onboarding:
metadata: metadata:
tags: tags:
- Onboarding - Onboarding
started:
type: event
description: |
User started onboarding.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1872968
data_reviews:
- https://phabricator.services.mozilla.com/D215034
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Onboarding
search_shortcuts: search_shortcuts:
selected: selected:
@ -1784,6 +1911,39 @@ login_dialog:
tags: tags:
- Logins - Logins
generated_password_dialog:
shown:
type: event
description: |
The password generator prompt was pressed
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1877238
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1877238
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Logins
filled:
type: event
description: |
The password generator prompt "Use password" was pressed
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1877238
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1877238
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Logins
metrics: metrics:
default_browser: default_browser:
type: boolean type: boolean
@ -2539,21 +2699,6 @@ metrics:
metadata: metadata:
tags: tags:
- Performance - Performance
install_source:
type: string
lifetime: application
description: |
Used to identify the source the app was installed from.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/22138
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22224#issuecomment-956749994
- https://github.com/mozilla-mobile/fenix/pull/23453#issuecomment-1024694220
data_sensitivity:
- technical
notification_emails:
- android-probes@mozilla.com
expires: never
inactive_tabs_count: inactive_tabs_count:
type: quantity type: quantity
description: | description: |
@ -2598,6 +2743,7 @@ metrics:
- Wallpapers - Wallpapers
notifications_allowed: notifications_allowed:
type: boolean type: boolean
lifetime: application
description: | description: |
True if notifications are allowed, otherwise false. True if notifications are allowed, otherwise false.
send_in_pings: send_in_pings:
@ -2681,6 +2827,7 @@ metrics:
customize_home: customize_home:
most_visited_sites: most_visited_sites:
type: boolean type: boolean
lifetime: application
description: | description: |
An indication of whether the most visited sites An indication of whether the most visited sites
are enabled to be displayed are enabled to be displayed
@ -2700,6 +2847,7 @@ customize_home:
expires: never expires: never
jump_back_in: jump_back_in:
type: boolean type: boolean
lifetime: application
description: | description: |
An indication of whether the Jump back An indication of whether the Jump back
in section is enabled to be displayed in section is enabled to be displayed
@ -2717,11 +2865,12 @@ customize_home:
notification_emails: notification_emails:
- android-probes@mozilla.com - android-probes@mozilla.com
expires: never expires: never
recently_saved: bookmarks:
type: boolean type: boolean
lifetime: application
description: | description: |
An indication of whether the recently An indication of whether the recently
saved section is enabled to be displayed saved section is enabled to be displayed. This was previously customize_home.recently_saved.
send_in_pings: send_in_pings:
- metrics - metrics
bugs: bugs:
@ -2738,6 +2887,7 @@ customize_home:
expires: never expires: never
recently_visited: recently_visited:
type: boolean type: boolean
lifetime: application
description: | description: |
An indication of whether the Recently An indication of whether the Recently
visited section is enabled to be displayed visited section is enabled to be displayed
@ -2757,6 +2907,7 @@ customize_home:
expires: never expires: never
pocket: pocket:
type: boolean type: boolean
lifetime: application
description: | description: |
An indication of whether Pocket is enabled to be displayed An indication of whether Pocket is enabled to be displayed
send_in_pings: send_in_pings:
@ -2778,6 +2929,7 @@ customize_home:
- PocketIntegration - PocketIntegration
sponsored_pocket: sponsored_pocket:
type: boolean type: boolean
lifetime: application
description: | description: |
An indication of whether Pocket sponsored stories are enabled An indication of whether Pocket sponsored stories are enabled
to be displayed to be displayed
@ -2799,6 +2951,7 @@ customize_home:
- PocketIntegration - PocketIntegration
contile: contile:
type: boolean type: boolean
lifetime: application
description: | description: |
An indication of whether Contile is enabled to be displayed An indication of whether Contile is enabled to be displayed
send_in_pings: send_in_pings:
@ -2827,7 +2980,8 @@ customize_home:
toggled. toggled.
We currently track: most_visited_sites, jump_back_in, We currently track: most_visited_sites, jump_back_in,
recently_visited, recently_saved, pocket, and contile. recently_visited, bookmarks, pocket, and contile.
We previously tracked bookmarks as recently_saved.
enabled: enabled:
type: boolean type: boolean
description: "Whether or not the preference is *now* enabled" description: "Whether or not the preference is *now* enabled"
@ -2845,6 +2999,7 @@ customize_home:
expires: never expires: never
opening_screen: opening_screen:
type: string type: string
lifetime: application
description: | description: |
What opening screen preference the user has selected What opening screen preference the user has selected
under "Customize Home". under "Customize Home".
@ -2865,6 +3020,7 @@ customize_home:
preferences: preferences:
studies_enabled: studies_enabled:
type: boolean type: boolean
lifetime: application
description: > description: >
A metric indicating whether or not the user has studies enabled A metric indicating whether or not the user has studies enabled
default: true default: true
@ -2898,6 +3054,7 @@ preferences:
expires: never expires: never
search_suggestions_enabled: search_suggestions_enabled:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has search suggestions enabled Whether or not the user has search suggestions enabled
default: true default: true
@ -2922,6 +3079,7 @@ preferences:
- Settings - Settings
remote_debugging_enabled: remote_debugging_enabled:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has remote debugging enabled Whether or not the user has remote debugging enabled
default: false default: false
@ -2947,6 +3105,7 @@ preferences:
- Settings - Settings
telemetry_enabled: telemetry_enabled:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has telemetry enabled. Note we should Whether or not the user has telemetry enabled. Note we should
never receive a "false" value for this since telemetry would never receive a "false" value for this since telemetry would
@ -2973,6 +3132,7 @@ preferences:
- Settings - Settings
enhanced_tracking_protection: enhanced_tracking_protection:
type: string type: string
lifetime: application
description: | description: |
What type of enhanced tracking protection the user has enabled. What type of enhanced tracking protection the user has enabled.
"standard," "strict," "custom," or "" (if disabled) "standard," "strict," "custom," or "" (if disabled)
@ -3000,6 +3160,7 @@ preferences:
- Settings - Settings
etp_custom_cookies_selection: etp_custom_cookies_selection:
type: string type: string
lifetime: application
description: | description: |
The option user has selected in the "Custom" mode of the The option user has selected in the "Custom" mode of the
Enhanced Tracking Protection settings. Enhanced Tracking Protection settings.
@ -3027,6 +3188,7 @@ preferences:
- Settings - Settings
bookmarks_suggestion: bookmarks_suggestion:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has enabled bookmark search suggestions Whether or not the user has enabled bookmark search suggestions
default: true default: true
@ -3052,6 +3214,7 @@ preferences:
- Settings - Settings
browsing_history_suggestion: browsing_history_suggestion:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has enabled browsing history suggestions. Whether or not the user has enabled browsing history suggestions.
default: true default: true
@ -3077,6 +3240,7 @@ preferences:
- Settings - Settings
clipboard_suggestions_enabled: clipboard_suggestions_enabled:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has enabled clipboard search suggestions. Whether or not the user has enabled clipboard search suggestions.
default: true default: true
@ -3102,6 +3266,7 @@ preferences:
- Settings - Settings
search_shortcuts_enabled: search_shortcuts_enabled:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has enabled search shortcuts. Whether or not the user has enabled search shortcuts.
default: true default: true
@ -3126,6 +3291,7 @@ preferences:
- Settings - Settings
signed_in_sync: signed_in_sync:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user is signed into FxA Whether or not the user is signed into FxA
default: false default: false
@ -3152,6 +3318,7 @@ preferences:
- Settings - Settings
sync_items: sync_items:
type: string_list type: string_list
lifetime: application
description: | description: |
The list of items the user has chosen to sync with FxA. The list of items the user has chosen to sync with FxA.
default: "" if the user is signed out. Otherwise defaults to default: "" if the user is signed out. Otherwise defaults to
@ -3179,6 +3346,7 @@ preferences:
- Settings - Settings
voice_search_enabled: voice_search_enabled:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has enabled the voice search button. Whether or not the user has enabled the voice search button.
default: true default: true
@ -3206,6 +3374,7 @@ preferences:
- Settings - Settings
toolbar_position_setting: toolbar_position_setting:
type: string type: string
lifetime: application
description: | description: |
The position of the toolbar The position of the toolbar
default: bottom (defaults to top if the user has accessibility services) default: bottom (defaults to top if the user has accessibility services)
@ -3230,6 +3399,7 @@ preferences:
- Settings - Settings
accessibility_services: accessibility_services:
type: string_list type: string_list
lifetime: application
description: | description: |
Whether or not the user has touch exploration or switch services enabled. Whether or not the user has touch exploration or switch services enabled.
These are built into the Android OS, not Fenix prefs. These are built into the Android OS, not Fenix prefs.
@ -3254,6 +3424,7 @@ preferences:
- Settings - Settings
open_links_in_app_enabled: open_links_in_app_enabled:
type: string type: string
lifetime: application
description: | description: |
The user has the open links in apps feature enabled. The user has the open links in apps feature enabled.
"ask_before_opening", "always" or "never". "ask_before_opening", "always" or "never".
@ -3274,6 +3445,7 @@ preferences:
- Settings - Settings
user_theme: user_theme:
type: string type: string
lifetime: application
description: | description: |
The theme the user has enabled. "light," "dark," "system," or "battery" The theme the user has enabled. "light," "dark," "system," or "battery"
default: "system" for API 28+, else "light" default: "system" for API 28+, else "light"
@ -3298,6 +3470,7 @@ preferences:
- Settings - Settings
inactive_tabs_enabled: inactive_tabs_enabled:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has the inactive tabs feature enabled. Whether or not the user has the inactive tabs feature enabled.
default: true default: true
@ -5436,6 +5609,55 @@ tabs_tray:
- interaction - interaction
expires: never expires: never
tab_strip:
new_tab_tapped:
type: event
description: |
A user clicked new tab button in tab strip
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1882111
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1882111
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Tabs
close_tab:
type: event
description: |
A user closed the tab via tab strip
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1882111
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1882111
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Tabs
select_tab:
type: event
description: |
A user selected a tab via tab strip
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1882111
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1882111
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
metadata:
tags:
- Tabs
collections: collections:
renamed: renamed:
@ -6521,6 +6743,7 @@ logins:
- Logins - Logins
saved_all: saved_all:
type: quantity type: quantity
lifetime: application
description: | description: |
Counter of number of passwords currently saved by user. Counter of number of passwords currently saved by user.
bugs: bugs:
@ -6905,11 +7128,11 @@ top_sites:
expires: never expires: never
context_id: context_id:
type: uuid type: uuid
lifetime: application
description: | description: |
A UUID that is unjoinable with other browser metrics. This ID will not be A UUID that is unjoinable with other browser metrics. This ID will not be
shared with AdM, only for internal uses. This ID is shared across all shared with AdM, only for internal uses. This ID is shared across all
contextual services features. contextual services features.
lifetime: application
send_in_pings: send_in_pings:
- topsites-impression - topsites-impression
bugs: bugs:
@ -7466,6 +7689,7 @@ first_session:
- Attribution - Attribution
distribution_id: distribution_id:
type: string type: string
lifetime: application
description: | description: |
A string containing the distribution identifier. This is currently used A string containing the distribution identifier. This is currently used
to identify installs from Mozilla Online. to identify installs from Mozilla Online.
@ -7553,6 +7777,28 @@ first_session:
tags: tags:
- Performance - Performance
- Attribution - Attribution
install_source:
type: string
lifetime: application
description: |
Used to identify the source the app was installed from.
send_in_pings:
- metrics
- first-session
- baseline
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1898363
- https://bugzilla.mozilla.org/show_bug.cgi?id=1908383
data_reviews:
- https://phabricator.services.mozilla.com/D212913
- https://phabricator.services.mozilla.com/D216935
data_sensitivity:
- technical
notification_emails:
- android-probes@mozilla.com
expires: never
no_lint:
- BASELINE_PING
play_store_attribution: play_store_attribution:
install_referrer_response: install_referrer_response:
type: text type: text
@ -7912,6 +8158,7 @@ addons:
- WebExtensions - WebExtensions
has_installed_addons: has_installed_addons:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has installed add-ons on the device. Whether or not the user has installed add-ons on the device.
send_in_pings: send_in_pings:
@ -7935,6 +8182,7 @@ addons:
- WebExtensions - WebExtensions
has_enabled_addons: has_enabled_addons:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user has enabled add-ons on the device. Whether or not the user has enabled add-ons on the device.
send_in_pings: send_in_pings:
@ -7958,6 +8206,7 @@ addons:
- WebExtensions - WebExtensions
installed_addons: installed_addons:
type: string_list type: string_list
lifetime: application
description: | description: |
A list of all installed add-ons on the device. A list of all installed add-ons on the device.
send_in_pings: send_in_pings:
@ -7981,6 +8230,7 @@ addons:
- WebExtensions - WebExtensions
enabled_addons: enabled_addons:
type: string_list type: string_list
lifetime: application
description: | description: |
A list of all enabled add-ons on the device. A list of all enabled add-ons on the device.
send_in_pings: send_in_pings:
@ -9291,6 +9541,7 @@ awesomebar:
android_autofill: android_autofill:
supported: supported:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not Android Autofill is supported by the device and is Whether or not Android Autofill is supported by the device and is
supported for this user. supported for this user.
@ -9308,6 +9559,7 @@ android_autofill:
expires: never expires: never
enabled: enabled:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not Firefox is the Android Autofill provider for this user. Whether or not Firefox is the Android Autofill provider for this user.
provider. provider.
@ -9716,11 +9968,11 @@ recent_tabs:
- android-probes@mozilla.com - android-probes@mozilla.com
expires: never expires: never
recent_bookmarks: home_bookmarks:
shown: shown:
type: event type: event
description: | description: |
Recent bookmarks section was shown to the user. Bookmarks section of home was shown to the user. This was previously recent_bookmarks.shown.
bugs: bugs:
- https://github.com/mozilla-mobile/fenix/issues/22103 - https://github.com/mozilla-mobile/fenix/issues/22103
data_reviews: data_reviews:
@ -9737,8 +9989,8 @@ recent_bookmarks:
lifetime: application lifetime: application
description: | description: |
A counter that indicates the number of times that a user A counter that indicates the number of times that a user
has clicked on a recently saved bookmark from the home has clicked on a bookmark from the home
screen. screen. This was previously recent_bookmarks.bookmark_clicked.
send_in_pings: send_in_pings:
- metrics - metrics
bugs: bugs:
@ -9758,8 +10010,8 @@ recent_bookmarks:
lifetime: application lifetime: application
description: | description: |
A counter that indicates the number of times that a user A counter that indicates the number of times that a user
has clicked the show all button for recently saved bookmarks has clicked the show all button for bookmarks
on the home screen. on the home screen. This was previously recent_bookmarks.show_all_bookmarks.
send_in_pings: send_in_pings:
- metrics - metrics
bugs: bugs:
@ -9774,11 +10026,11 @@ recent_bookmarks:
notification_emails: notification_emails:
- android-probes@mozilla.com - android-probes@mozilla.com
expires: never expires: never
recent_bookmarks_count: bookmarks_count:
type: quantity type: quantity
description: | description: |
The number of bookmarked items appearing in the The number of bookmarked items appearing in the
Recently Saved section on the home page. Bookmarks section on the home page. This was previously recent_bookmarks.recent_bookmarks_count.
bugs: bugs:
- https://github.com/mozilla-mobile/fenix/issues/22075 - https://github.com/mozilla-mobile/fenix/issues/22075
data_reviews: data_reviews:
@ -9818,6 +10070,7 @@ recent_searches:
credit_cards: credit_cards:
saved: saved:
type: counter type: counter
lifetime: application
description: | description: |
A counter of the number of credit cards that have been saved A counter of the number of credit cards that have been saved
manually by the user. manually by the user.
@ -11169,6 +11422,7 @@ shopping:
shopping.settings: shopping.settings:
component_opted_out: component_opted_out:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not the user opted out of review quality check feature. Whether or not the user opted out of review quality check feature.
send_in_pings: send_in_pings:
@ -11188,6 +11442,7 @@ shopping.settings:
- Shopping - Shopping
nimbus_disabled_shopping: nimbus_disabled_shopping:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or not Nimbus has disabled the use of the shopping component. Whether or not Nimbus has disabled the use of the shopping component.
send_in_pings: send_in_pings:
@ -11207,6 +11462,7 @@ shopping.settings:
- Shopping - Shopping
user_has_onboarded: user_has_onboarded:
type: boolean type: boolean
lifetime: application
description: | description: |
Whether or the user has completed the review quality check onboarding. Whether or the user has completed the review quality check onboarding.
send_in_pings: send_in_pings:
@ -11226,6 +11482,7 @@ shopping.settings:
- Shopping - Shopping
disabled_ads: disabled_ads:
type: boolean type: boolean
lifetime: application
description: | description: |
Indicates if the user has disabled ads. Indicates if the user has disabled ads.
send_in_pings: send_in_pings:
@ -11410,3 +11667,249 @@ debug_drawer:
notification_emails: notification_emails:
- android-probes@mozilla.com - android-probes@mozilla.com
expires: never expires: never
navigation_bar:
navigation_bar_cfr_shown:
type: event
description: |
Navigation bar CFR was shown to the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889474
data_reviews:
- https://phabricator.services.mozilla.com/D211225
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
navigation_bar_cfr_dismissed:
type: event
description: |
A user has dismissed the navigation bar CFR.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889474
data_reviews:
- https://phabricator.services.mozilla.com/D211225
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
home_search_tapped:
type: event
description: |
When navigation bar search button is tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
home_tab_tray_tapped:
type: event
description: |
When navigation bar tab tray button is tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
home_tab_tray_long_tapped:
type: event
description: |
When navigation bar tab tray button is long tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1894512
data_reviews:
- https://phabricator.services.mozilla.com/D214362
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
home_menu_tapped:
type: event
description: |
When navigation bar menu button is tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
browser_back_tapped:
type: event
description: |
When navigation bar back button is tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
browser_back_long_tapped:
type: event
description: |
When navigation bar back button is long tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
browser_forward_tapped:
type: event
description: |
When navigation bar forward button is tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
browser_forward_long_tapped:
type: event
description: |
When navigation bar forward button is long tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
browser_tab_tray_tapped:
type: event
description: |
When navigation bar tab tray button is tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
browser_tab_tray_long_tapped:
type: event
description: |
When navigation bar tab tray button is long tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1894512
data_reviews:
- https://phabricator.services.mozilla.com/D214362
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
browser_menu_tapped:
type: event
description: |
When navigation bar menu button is tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
browser_home_tapped:
type: event
description: |
When navigation bar home button is tapped by the user.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
address_toolbar:
share_tapped:
type: event
description: |
When share button is tapped on the toolbar.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
reload_tapped:
type: event
description: |
When reload button is tapped on the toolbar.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
cancel_tapped:
type: event
description: |
When cancel button is tapped on the toolbar.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1889484
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
nimbus_system:
recorded_nimbus_context:
type: object
structure:
type: object
properties:
is_first_run:
type: boolean
description: |
The Nimbus context object that is recorded to Glean
bugs:
- 'https://bugzilla.mozilla.org/show_bug.cgi?id=1898552'
data_reviews:
- 'https://bugzilla.mozilla.org/show_bug.cgi?id=1898552#c3'
data_sensitivity:
- interaction
notification_emails:
- chumphreys@mozilla.com
- project-nimbus@mozilla.com
expires: never

52
app/nimbus.fml.yaml Executable file → Normal file
View File

@ -55,7 +55,7 @@ features:
{ {
"top-sites": true, "top-sites": true,
"jump-back-in": true, "jump-back-in": true,
"recently-saved": true, "bookmarks": true,
"recent-explorations": true, "recent-explorations": true,
"pocket": true, "pocket": true,
"pocket-sponsored-stories": true, "pocket-sponsored-stories": true,
@ -66,7 +66,7 @@ features:
"sections-enabled": { "sections-enabled": {
"top-sites": true, "top-sites": true,
"jump-back-in": true, "jump-back-in": true,
"recently-saved": true, "bookmarks": true,
"recent-explorations": true, "recent-explorations": true,
"pocket": true, "pocket": true,
} }
@ -250,6 +250,7 @@ features:
glean: glean:
description: "A feature that provides server-side configurations for Glean metrics (aka Server Knobs)." description: "A feature that provides server-side configurations for Glean metrics (aka Server Knobs)."
allow-coenrollment: true
variables: variables:
metrics-enabled: metrics-enabled:
description: "A map of metric base-identifiers to booleans representing the state of the 'enabled' flag for that metric." description: "A map of metric base-identifiers to booleans representing the state of the 'enabled' flag for that metric."
@ -259,6 +260,10 @@ features:
description: "Enables precise event timestamps for Glean events" description: "Enables precise event timestamps for Glean events"
type: Boolean type: Boolean
default: false default: false
delay-ping-lifetime-io:
description: "Glean will delay io for ping lifetime metrics"
type: Boolean
default: true
splash-screen: splash-screen:
description: "A feature that extends splash screen duration, allowing additional data fetching time for the app's initial run." description: "A feature that extends splash screen duration, allowing additional data fetching time for the app's initial run."
@ -421,6 +426,45 @@ features:
type: Boolean type: Boolean
default: false default: false
navigation-toolbar:
description: Feature for navigation toolbar.
variables:
enabled:
description: >
When the feature is enabled then the user will see the new navigation toolbar.
type: Boolean
default: false
remote-tab-management:
description: >
Features that let users manage tabs on other devices that are
connected to the same Mozilla account.
variables:
close-tabs-enabled:
description: >
Whether the feature to close synced tabs is enabled. When enabled,
this device will allow other devices to close tabs that are open on this device, and
show a "close" button for tabs that are currently open on other supported devices
in the synced tabs tray.
type: Boolean
default: false
suggest-shipped-domains:
description: Feature that suggests domains from the shipped domain list.
variables:
enabled:
description: >
Suggest domains from the shipped domain list.
type: Boolean
default: true
defaults:
- channel: nightly
value:
enabled: false
- channel: developer
value:
enabled: false
types: types:
objects: {} objects: {}
@ -430,8 +474,8 @@ types:
variants: variants:
top-sites: top-sites:
description: The frecency and pinned sites. description: The frecency and pinned sites.
recently-saved: bookmarks:
description: The sites the user has bookmarked recently. description: The sites the user has bookmarked.
jump-back-in: jump-back-in:
description: The tabs the user was looking immediately before being interrupted. description: The tabs the user was looking immediately before being interrupted.
recent-explorations: recent-explorations:

0
app/onboarding.fml.yaml Executable file → Normal file
View File

0
app/pbm.fml.yaml Executable file → Normal file
View File

0
app/pings.yaml Executable file → Normal file
View File

0
app/proguard-rules.pro vendored Executable file → Normal file
View File

24
app/src/androidTest/assets/pages/addressForm.html Executable file → Normal file
View File

@ -1,17 +1,17 @@
<html> <html>
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width" />
<title>Address_Form</title> <title>Address_Form</title>
</head> </head>
<body> <body>
<form> <form>
<p>Street Address: <input id="streetAddress" type="text"></p> <p>Street Address: <input id="streetAddress" type="text" /></p>
<p>City: <input id="city" type="text"></p> <p>City: <input id="city" type="text" /></p>
<p>Zip Code: <input id="zipCode" type="text"></p> <p>Zip Code: <input id="zipCode" type="text" /></p>
<p>Country: <input id="country" type="text"></p> <p>Country: <input id="country" type="text" /></p>
<p>Telephone: <input id="telephone" type="text"></p> <p>Telephone: <input id="telephone" type="text" /></p>
<p>Email: <input id="email" type="text"></p> <p>Email: <input id="email" type="text" /></p>
<p>Apartment, suite, etc. <input id="apartment" type="text"></p> <p>Apartment, suite, etc. <input id="apartment" type="text" /></p>
</form> </form>
</body> </body>
</html> </html>

20
app/src/androidTest/assets/pages/audioMediaPage.html Executable file → Normal file
View File

@ -1,13 +1,13 @@
<html> <html>
<head> <head>
<title>Audio_Test_Page</title> <title>Audio_Test_Page</title>
</head> </head>
<body> <body>
<p id="testContent">Page content: audio player</p> <p id="testContent">Page content: audio player</p>
<div class="audioPlayer"> <div class="audioPlayer">
<audio id="audioSample" controls loop> <audio id="audioSample" controls loop>
<source src="../resources/audioSample.mp3"> <source src="../resources/audioSample.mp3" />
</audio> </audio>
</div> </div>
</body> </body>
</html> </html>

38
app/src/androidTest/assets/pages/creditCardForm.html Executable file → Normal file
View File

@ -1,17 +1,31 @@
<html> <html>
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width" />
<title>Credit_Card_Form</title> <title>Credit_Card_Form</title>
</head> </head>
<body> <body>
<form> <form>
<p>Card information</p> <p>Card information</p>
<p>Card Number: <input id="cardNumber" type="text" placeholder="1234 1234 1234 1234"></p> <p>
<p>Name on card: <input id="nameOnCard"type="text" placeholder="Name on card"></p> Card Number:
<p> Expiry date: <input id="cardNumber" type="text" placeholder="1234 1234 1234 1234" />
<input id="expiryMonthAndYear" inputmode="numerical" placeholder="MM / YYYY" type="text" /> </p>
</p> <p>
<p><input type="submit" id="submit" value="Submit" aria-label="submit"/></p> Name on card:
<input id="nameOnCard" type="text" placeholder="Name on card" />
</p>
<p>
Expiry date:
<input
id="expiryMonthAndYear"
inputmode="numerical"
placeholder="MM / YYYY"
type="text"
/>
</p>
<p>
<input type="submit" id="submit" value="Submit" aria-label="submit" />
</p>
</form> </form>
</body> </body>
</html> </html>

View File

@ -1,15 +1,19 @@
<html> <html>
<!-- This Source Code Form is subject to the terms of the Mozilla Public <!-- 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 - 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/. -->
<!-- This asset is using the code behind <!-- This asset is using the code behind
- https://www.mozilla-anti-tracking.com/test/dfpi/storage_access_api.html - https://www.mozilla-anti-tracking.com/test/dfpi/storage_access_api.html
- test page. - test page.
- Source repository: https://github.com/mozilla/anti-tracking-test-pages --> - Source repository: https://github.com/mozilla/anti-tracking-test-pages -->
<body> <body>
<h2>Cross-site cookies storage access test</h2> <h2>Cross-site cookies storage access test</h2>
<h3>anti-tracker-test.com</h3> <h3>anti-tracker-test.com</h3>
<h4>different site, cross-origin iframe</h4> <h4>different site, cross-origin iframe</h4>
<iframe width=500 height=1000 src="https://mozilla-mobile.github.io/testapp/anti-tracker-test_set_storage_with_sa_api.html"></iframe> <iframe
</body> width="500"
height="1000"
src="https://mozilla-mobile.github.io/testapp/anti-tracker-test_set_storage_with_sa_api.html"
></iframe>
</body>
</html> </html>

34
app/src/androidTest/assets/pages/externalLinks.html Executable file → Normal file
View File

@ -1,29 +1,31 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Html_Control_Form</title> <title>Html_Control_Form</title>
<meta charset="utf-8"> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width" />
</head> </head>
<p>Misc Link Types</p> <p>Misc Link Types</p>
<section> <section>
<a href="mailto://example@example.com">Email link</a> <a href="mailto://example@example.com">Email link</a>
</section> </section>
<section> <section>
<a href="tel://1234567890">Telephone link</a> <a href="tel://1234567890">Telephone link</a>
</section> </section>
<section> <section>
<a href="vnd.youtube://@Mozilla">Youtube schema link</a> <a href="vnd.youtube://@Mozilla">Youtube schema link</a>
</section> </section>
<section> <section>
<a href="https://m.youtube.com/user/mozilla?cbrd=1">Youtube full link</a> <a href="https://m.youtube.com/user/mozilla?cbrd=1">Youtube full link</a>
</section> </section>
<section> <section>
<a href="http://play.google.com/store/apps/details?id=org.mozilla.firefox">Playstore link</a> <a href="http://play.google.com/store/apps/details?id=org.mozilla.firefox"
</section> >Playstore link</a
>
</section>
</html> </html>

14
app/src/androidTest/assets/pages/generic1.html Executable file → Normal file
View File

@ -1,10 +1,10 @@
<html> <html>
<head> <head>
<title>Test_Page_1</title> <title>Test_Page_1</title>
</head> </head>
<body> <body>
<h1> <h1>
<p id="testContent">Page content: 1</p> <p id="testContent">Page content: 1</p>
</h1> </h1>
</body> </body>
</html> </html>

14
app/src/androidTest/assets/pages/generic2.html Executable file → Normal file
View File

@ -1,10 +1,10 @@
<html> <html>
<head> <head>
<title>Test_Page_2</title> <title>Test_Page_2</title>
</head> </head>
<body> <body>
<h1> <h1>
<p id="testContent">Page content: 2</p> <p id="testContent">Page content: 2</p>
</h1> </h1>
</body> </body>
</html> </html>

27
app/src/androidTest/assets/pages/generic3.html Executable file → Normal file
View File

@ -1,16 +1,19 @@
<html> <html>
<head> <head>
<title>Test_Page_3</title> <title>Test_Page_3</title>
</head> </head>
<body> <body>
<h1> <h1>
<p id="testContent">Page content: 3</p> <p id="testContent">Page content: 3</p>
<p> <p>
<a href="https://play.google.com/store/apps/details?id=org.mozilla.fenix">Mozilla Playstore link</a> <a
</p> href="https://play.google.com/store/apps/details?id=org.mozilla.fenix"
<p> >Mozilla Playstore link</a
>
</p>
<p>
<a href="../resources/pdfForm.pdf">PDF form file</a> <a href="../resources/pdfForm.pdf">PDF form file</a>
</p> </p>
</h1> </h1>
</body> </body>
</html> </html>

16
app/src/androidTest/assets/pages/generic4.html Executable file → Normal file
View File

@ -1,20 +1,20 @@
<html> <html>
<head> <head>
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>Test_Page_4</title> <title>Test_Page_4</title>
</head> </head>
<body> <body>
<p id="testContent">Page content: 4</p> <p id="testContent">Page content: 4</p>
<a href="generic1.html">Link 1</a> <a href="generic1.html">Link 1</a>
<a href="generic2.html">Link 2</a> <a href="generic2.html">Link 2</a>
<a href="generic3.html">Link 3</a> <a href="generic3.html">Link 3</a>
<p> <p>
<a href="../resources/rabbit.jpg"> <a href="../resources/rabbit.jpg">
<img src="../resources/rabbit.jpg" alt="test_link_image"> <img src="../resources/rabbit.jpg" alt="test_link_image" />
</a> </a>
</p> </p>
<p> <p>
<img src="../resources/rabbit.jpg" alt="test_no_link_image"> <img src="../resources/rabbit.jpg" alt="test_no_link_image" />
</p> </p>
</body> </body>
</html> </html>

View File

@ -1,15 +1,14 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width" />
<body> <body>
<script type = "text/javascript" > <script type="text/javascript">
const gpcValue = navigator.globalPrivacyControl const gpcValue = navigator.globalPrivacyControl;
if (gpcValue) { if (gpcValue) {
document.write('<p>GPC is enabled.</p>'); document.write("<p>GPC is enabled.</p>");
} else { } else {
document.write('<p>GPC not enabled.</p>'); document.write("<p>GPC not enabled.</p>");
} }
</script> </script>
</body>
</body>
</html> </html>

0
app/src/androidTest/assets/pages/htmlControls.html Executable file → Normal file
View File

60
app/src/androidTest/assets/pages/lorem-ipsum.html Executable file → Normal file
View File

@ -1,36 +1,36 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta charset="utf-8" />
<title>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
eirmod tempor invidunt
</title>
<meta content="width=device-width, initial-scale=1" name="viewport" />
</head>
<head> <body>
<meta charset="utf-8"/> <p id="testContent">Page content: lorem ipsum</p>
<title>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
eirmod tempor invidunt</title>
<meta content="width=device-width, initial-scale=1"
name="viewport"/>
</head>
<body> <h1>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
<p id="testContent">Page content: lorem ipsum</p> eirmod tempor invidunt
</h1>
<h1>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt</h1>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed
diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.
</p>
</body>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed
diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed
diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam
erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea
rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum
dolor sit amet.
</p>
</body>
</html> </html>

68
app/src/androidTest/assets/pages/mutedVideoPage.html Executable file → Normal file
View File

@ -1,49 +1,51 @@
<!DOCTYPE HTML> <!DOCTYPE html>
<!-- This Source Code Form is subject to the terms of the Mozilla Public <!-- 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 - 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/. -->
<html> <html>
<head> <head>
<title>Muted_Video_Test_Page</title> <title>Muted_Video_Test_Page</title>
</head> </head>
<body> <body>
<p id="testContent">Page content: muted video player</p> <p id="testContent">Page content: muted video player</p>
<div class="playbackState"> <div class="playbackState">
<p>Media file not playing</p> <p>Media file not playing</p>
</div> </div>
<div id="video-container" style="text-align:center"> <div id="video-container" style="text-align: center">
<button onclick="play()">Play</button> <button onclick="play()">Play</button>
<button onclick="pause()">Pause</button> <button onclick="pause()">Pause</button>
<button onclick="fullscreen()">Full Screen</button> <button onclick="fullscreen()">Full Screen</button>
<br><br> <br /><br />
<video id="mutedVideo" width="420" autoplay muted controls loop> <video id="mutedVideo" width="420" autoplay muted controls loop>
<source src="../resources/clip.mp4" type="video/mp4"> <source src="../resources/clip.mp4" type="video/mp4" />
Your browser does not support HTML video. Your browser does not support HTML video.
</video> </video>
</div> </div>
<script> <script>
const mutedVideo = document.getElementById("mutedVideo"); const mutedVideo = document.getElementById("mutedVideo");
function play() { function play() {
mutedVideo.play(); mutedVideo.play();
} }
function pause() { function pause() {
mutedVideo.pause(); mutedVideo.pause();
} }
function fullscreen() { function fullscreen() {
mutedVideo.requestFullscreen(); mutedVideo.requestFullscreen();
} }
mutedVideo.addEventListener('playing', (event) => { mutedVideo.addEventListener("playing", _event => {
document.querySelector('.playbackState').innerHTML="Media file is playing"; document.querySelector(".playbackState").innerHTML =
}); "Media file is playing";
});
mutedVideo.addEventListener('pause', (event) => { mutedVideo.addEventListener("pause", _event => {
document.querySelector('.playbackState').innerHTML="Media file is paused"; document.querySelector(".playbackState").innerHTML =
}); "Media file is paused";
</script> });
</body> </script>
</body>
</html> </html>

37
app/src/androidTest/assets/pages/password.html Executable file → Normal file
View File

@ -1,22 +1,23 @@
<html> <html>
<head>
<meta name="viewport" content="width=device-width" />
</head>
<head> <body aria-label="body">
<meta name="viewport" content="width=device-width"> <form method="GET" action="passwordsubmit.html">
</head> <p>
Username: <input id="username" type="text" value="test@example.com" />
<body aria-label="body"> </p>
<p>
<form method="GET" action="passwordsubmit.html"> Password: <input id="password" type="password" value="verysecret" />
<p>Username: <input id="username" type="text" value="test@example.com"></p> </p>
<p>Password: <input id="password" type="password" value="verysecret"></p> <p>
<p><input type="submit" id="submit" value="Login" aria-label="submit"/></p> <input type="submit" id="submit" value="Login" aria-label="submit" />
</form> </p>
</form>
</body> </body>
<script>
document.getElementById("password").value = Math.random().toString();
</script>
<script>
document.getElementById("password").value = Math.random().toString();
</script>
</html> </html>

13
app/src/androidTest/assets/pages/passwordsubmit.html Executable file → Normal file
View File

@ -1,9 +1,8 @@
<html> <html>
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width" />
</head> </head>
<body aria-label="body"> <body aria-label="body">
<p>Password submitted. Nope just a test.</p> <p>Password submitted. Nope just a test.</p>
</body> </body>
</html> </html>

60
app/src/androidTest/assets/pages/refresh.html Executable file → Normal file
View File

@ -1,44 +1,40 @@
<html> <html>
<script> <script>
function setCookie(newVal) {
function setCookie(newVal){ window.document.cookie = "pageStatus = " + newVal + ";";
window.document.cookie = "pageStatus = " + newVal + ";";
} }
function readCookie(name) { function readCookie(name) {
var nameEQ = name + "="; var nameEQ = name + "=";
var ca = document.cookie.split(';'); var ca = document.cookie.split(";");
for(var i=0;i < ca.length;i++) { for (var i = 0; i < ca.length; i++) {
var c = ca[i]; var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length); while (c.charAt(0) == " ") c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
} }
return null; return null;
} }
function valSwap(){ function valSwap() {
currentCookie = readCookie("pageStatus"); currentCookie = readCookie("pageStatus");
if(currentCookie == null) { if (currentCookie == null) {
setCookie("DEFAULT"); setCookie("DEFAULT");
} }
if (currentCookie.localeCompare("REFRESHED") == 0) { if (currentCookie.localeCompare("REFRESHED") == 0) {
setCookie("DEFAULT"); setCookie("DEFAULT");
return "DEFAULT"; return "DEFAULT";
} else { }
setCookie("REFRESHED"); setCookie("REFRESHED");
return "REFRESHED"; return "REFRESHED";
}
} }
var textToShow = valSwap(); var textToShow = valSwap();
window.addEventListener('DOMContentLoaded', (event) => { window.addEventListener("DOMContentLoaded", _event => {
document.querySelector('h1').innerHTML = textToShow; document.querySelector("h1").innerHTML = textToShow;
}); });
</script> </script>
<body> <body>
<h1>DEFAULT</h1> <h1>DEFAULT</h1>
</body> </body>
</html> </html>

34
app/src/androidTest/assets/pages/storage_check.html Executable file → Normal file
View File

@ -1,23 +1,21 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width" />
<body> <body>
<h1>Storage check</h1>
<h1>Storage check</h1> <script type="text/javascript">
if (sessionStorage.getItem("sessionTest") == "session storage") {
document.write("<p>Session storage has value</p>");
} else {
document.write("<p>Session storage empty</p>");
}
<script type="text/javascript"> if (localStorage.getItem("localTest") == "local storage") {
if (sessionStorage.getItem('sessionTest') == 'session storage') { document.write("<p>Local storage has value</p>");
document.write('<p>Session storage has value</p>'); } else {
} else { document.write("<p>Local storage empty</p>");
document.write('<p>Session storage empty</p>'); }
} </script>
</body>
if (localStorage.getItem('localTest') == 'local storage') {
document.write('<p>Local storage has value</p>');
} else {
document.write('<p>Local storage empty</p>');
}
</script>
</body>
</html> </html>

42
app/src/androidTest/assets/pages/storage_write.html Executable file → Normal file
View File

@ -1,28 +1,30 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width" />
<body> <body>
<h1>Storage Write</h1>
<h1>Storage Write</h1> <p id="cookies"></p>
<button id="setCookies">Set cookies</button>
<p id="cookies"></p> <script type="text/javascript">
<button id="setCookies">Set cookies</button> (function () {
document.getElementById("cookies").textContent = document.cookie
? document.cookie
: "No cookies set";
})();
<script type="text/javascript"> document
(function() { .getElementById("setCookies")
document.getElementById("cookies").textContent = document.cookie?document.cookie:"No cookies set"; .addEventListener("click", function () {
})(); document.cookie = "user=android";
document.getElementById("cookies").textContent = document.cookie;
});
document.getElementById("setCookies").addEventListener("click", function() { sessionStorage.setItem("sessionTest", "session storage");
document.cookie = "user=android"; localStorage.setItem("localTest", "local storage");
document.getElementById("cookies").textContent = document.cookie;
});
sessionStorage.setItem('sessionTest', 'session storage'); document.write("<p>Values written to storage</p>");
localStorage.setItem('localTest', 'local storage'); </script>
</body>
document.write('<p>Values written to storage</p>');
</script>
</body>
</html> </html>

2
app/src/androidTest/assets/pages/trackingPage.html Executable file → Normal file
View File

@ -75,7 +75,7 @@
updateCookieStatus(event.data, list); updateCookieStatus(event.data, list);
} }
}); });
}, false); });
</script> </script>
</body> </body>
</html> </html>

68
app/src/androidTest/assets/pages/videoMediaPage.html Executable file → Normal file
View File

@ -1,49 +1,51 @@
<!DOCTYPE HTML> <!DOCTYPE html>
<!-- This Source Code Form is subject to the terms of the Mozilla Public <!-- 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 - 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/. -->
<html> <html>
<head> <head>
<title>Video_Test_Page</title> <title>Video_Test_Page</title>
</head> </head>
<body> <body>
<p id="testContent">Page content: video player</p> <p id="testContent">Page content: video player</p>
<div class="playbackState"> <div class="playbackState">
<p>Media file not playing</p> <p>Media file not playing</p>
</div> </div>
<div id="video-container" style="text-align:center"> <div id="video-container" style="text-align: center">
<button onclick="play()">Play</button> <button onclick="play()">Play</button>
<button onclick="pause()">Pause</button> <button onclick="pause()">Pause</button>
<button onclick="fullscreen()">Full Screen</button> <button onclick="fullscreen()">Full Screen</button>
<br><br> <br /><br />
<video id="video" width="420" autoplay controls loop> <video id="video" width="420" autoplay controls loop>
<source src="../resources/clip.mp4" type="video/mp4"> <source src="../resources/clip.mp4" type="video/mp4" />
Your browser does not support HTML video. Your browser does not support HTML video.
</video> </video>
</div> </div>
<script> <script>
const video = document.getElementById("video"); const video = document.getElementById("video");
function play() { function play() {
video.play(); video.play();
} }
function pause() { function pause() {
video.pause(); video.pause();
} }
function fullscreen() { function fullscreen() {
video.requestFullscreen(); video.requestFullscreen();
} }
video.addEventListener('playing', (event) => { video.addEventListener("playing", _event => {
document.querySelector('.playbackState').innerHTML="Media file is playing"; document.querySelector(".playbackState").innerHTML =
}); "Media file is playing";
});
video.addEventListener('pause', (event) => { video.addEventListener("pause", _event => {
document.querySelector('.playbackState').innerHTML="Media file is paused"; document.querySelector(".playbackState").innerHTML =
}); "Media file is paused";
</script> });
</body> </script>
</body>
</html> </html>

0
app/src/androidTest/assets/resources/TestTTC.ttc Executable file → Normal file
View File

0
app/src/androidTest/assets/resources/TestTTF.ttf Executable file → Normal file
View File

0
app/src/androidTest/assets/resources/TestTT_-LICENSE Executable file → Normal file
View File

0
app/src/androidTest/assets/resources/audioSample.mp3 Executable file → Normal file
View File

0
app/src/androidTest/assets/resources/clip.mp4 Executable file → Normal file
View File

0
app/src/androidTest/assets/resources/pdfForm.pdf Executable file → Normal file
View File

0
app/src/androidTest/assets/resources/rabbit.jpg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

0
app/src/androidTest/assets/resources/trackingAPI.js Executable file → Normal file
View File

View File

View File

View File

@ -4,6 +4,7 @@
package org.mozilla.fenix.experimentintegration package org.mozilla.fenix.experimentintegration
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
@ -14,7 +15,7 @@ import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.homeScreen
class GenericExperimentIntegrationTest { class GenericExperimentIntegrationTest {
private val experimentName = "Viewpoint" private val experimentName = InstrumentationRegistry.getArguments().getString("EXP_NAME", "Viewpoint")
@get:Rule @get:Rule
val activityTestRule = HomeActivityTestRule( val activityTestRule = HomeActivityTestRule(
@ -49,6 +50,16 @@ class GenericExperimentIntegrationTest {
} }
} }
@Test
fun testExperimentEnrolled() {
homeScreen {
}.openThreeDotMenu {
}.openSettings {
}.openExperimentsMenu {
verifyExperimentEnrolled(experimentName)
}
}
@Test @Test
fun testExperimentUnenrolled() { fun testExperimentUnenrolled() {
homeScreen { homeScreen {

View File

@ -15,6 +15,7 @@ pytest-metadata = "*"
pytest-variables = "*" pytest-variables = "*"
pyyaml = "*" pyyaml = "*"
requests = "*" requests = "*"
flask = "*"
[dev-packages] [dev-packages]
black = "*" black = "*"

View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "6dae5ac51aa7817578a25597da1ef783475050538443ba344c88a78969e68fd9" "sha256": "63efd7c433d2a687c37ff17bb314d329abc432cf1e83116483a813a76d83518d"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -24,117 +24,142 @@
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==0.6.0" "version": "==0.6.0"
}, },
"blinker": {
"hashes": [
"sha256:1779309f71bf239144b9399d06ae925637cf6634cf6bd131104184531bf67c01",
"sha256:8f77b09d3bf7c795e969e9486f39c2c5e9c39d4ee07424be2bc594ece9642d83"
],
"markers": "python_version >= '3.8'",
"version": "==1.8.2"
},
"certifi": { "certifi": {
"hashes": [ "hashes": [
"sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082", "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f",
"sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9" "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"
], ],
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.6'",
"version": "==2023.7.22" "version": "==2024.2.2"
}, },
"charset-normalizer": { "charset-normalizer": {
"hashes": [ "hashes": [
"sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843", "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027",
"sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786", "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087",
"sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e", "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786",
"sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8", "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8",
"sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4", "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09",
"sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa", "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185",
"sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d", "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574",
"sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82", "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e",
"sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7", "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519",
"sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895", "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898",
"sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d", "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269",
"sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a", "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3",
"sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382", "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f",
"sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678", "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6",
"sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b", "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8",
"sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e", "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a",
"sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741", "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73",
"sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4", "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc",
"sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596", "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714",
"sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9", "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2",
"sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69", "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc",
"sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c", "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce",
"sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77", "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d",
"sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13", "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e",
"sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459", "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6",
"sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e", "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269",
"sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7", "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96",
"sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908", "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d",
"sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a", "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a",
"sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f", "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4",
"sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8", "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77",
"sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482", "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d",
"sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d", "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0",
"sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d", "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed",
"sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545", "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068",
"sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34", "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac",
"sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86", "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25",
"sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6", "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8",
"sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe", "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab",
"sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e", "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26",
"sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc", "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2",
"sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7", "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db",
"sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd", "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f",
"sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c", "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5",
"sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557", "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99",
"sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a", "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c",
"sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89", "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d",
"sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078", "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811",
"sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e", "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa",
"sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4", "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a",
"sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403", "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03",
"sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0", "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b",
"sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89", "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04",
"sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115", "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c",
"sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9", "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001",
"sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05", "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458",
"sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a", "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389",
"sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec", "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99",
"sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56", "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985",
"sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38", "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537",
"sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479", "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238",
"sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c", "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f",
"sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e", "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d",
"sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd", "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796",
"sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186", "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a",
"sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455", "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143",
"sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c", "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8",
"sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65", "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c",
"sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78", "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5",
"sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287", "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5",
"sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df", "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711",
"sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43", "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4",
"sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1", "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6",
"sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7", "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c",
"sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989", "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7",
"sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a", "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4",
"sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63", "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b",
"sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884", "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae",
"sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649", "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12",
"sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810", "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c",
"sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828", "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae",
"sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4", "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8",
"sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2", "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887",
"sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd", "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b",
"sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5", "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4",
"sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe", "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f",
"sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293", "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5",
"sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e", "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33",
"sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e", "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519",
"sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8" "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"
], ],
"markers": "python_full_version >= '3.7.0'", "markers": "python_full_version >= '3.7.0'",
"version": "==3.3.0" "version": "==3.3.2"
},
"click": {
"hashes": [
"sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
"sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"
],
"markers": "python_version >= '3.7'",
"version": "==8.1.7"
},
"flask": {
"hashes": [
"sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3",
"sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==3.0.3"
}, },
"idna": { "idna": {
"hashes": [ "hashes": [
"sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc",
"sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"
], ],
"markers": "python_version >= '3.5'", "markers": "python_version >= '3.5'",
"version": "==3.4" "version": "==3.7"
}, },
"iniconfig": { "iniconfig": {
"hashes": [ "hashes": [
@ -144,253 +169,233 @@
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==2.0.0" "version": "==2.0.0"
}, },
"itsdangerous": {
"hashes": [
"sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef",
"sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"
],
"markers": "python_version >= '3.8'",
"version": "==2.2.0"
},
"jinja2": { "jinja2": {
"hashes": [ "hashes": [
"sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa", "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369",
"sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90" "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"
], ],
"index": "pypi",
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==3.1.3" "version": "==3.1.4"
}, },
"markupsafe": { "markupsafe": {
"hashes": [ "hashes": [
"sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e", "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf",
"sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e", "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff",
"sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431", "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f",
"sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686", "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3",
"sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c", "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532",
"sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559", "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f",
"sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc", "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617",
"sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb", "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df",
"sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939", "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4",
"sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c", "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906",
"sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0", "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f",
"sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4", "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4",
"sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9", "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8",
"sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575", "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371",
"sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba", "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2",
"sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d", "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465",
"sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd", "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52",
"sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3", "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6",
"sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00", "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169",
"sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155", "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad",
"sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac", "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2",
"sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52", "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0",
"sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f", "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029",
"sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8", "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f",
"sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b", "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a",
"sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007", "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced",
"sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24", "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5",
"sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea", "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c",
"sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198", "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf",
"sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0", "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9",
"sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee", "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb",
"sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be", "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad",
"sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2", "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3",
"sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1", "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1",
"sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707", "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46",
"sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6", "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc",
"sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c", "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a",
"sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58", "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee",
"sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823", "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900",
"sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779", "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5",
"sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636", "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea",
"sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c", "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f",
"sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad", "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5",
"sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee", "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e",
"sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc", "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a",
"sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2", "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f",
"sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48", "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50",
"sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7", "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a",
"sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e", "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b",
"sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b", "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4",
"sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa", "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff",
"sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5", "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2",
"sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e", "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46",
"sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb", "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b",
"sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9", "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf",
"sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57", "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5",
"sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc", "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5",
"sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc", "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab",
"sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2", "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd",
"sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11" "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==2.1.3" "version": "==2.1.5"
}, },
"packaging": { "packaging": {
"hashes": [ "hashes": [
"sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5",
"sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==23.2" "version": "==24.0"
}, },
"pluggy": { "pluggy": {
"hashes": [ "hashes": [
"sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12", "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1",
"sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7" "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"
], ],
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==1.3.0" "version": "==1.5.0"
}, },
"pydantic": { "pydantic": {
"hashes": [ "hashes": [
"sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7", "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5",
"sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1" "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==2.4.2"
},
"pydantic-core": {
"hashes": [
"sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e",
"sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33",
"sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7",
"sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7",
"sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea",
"sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4",
"sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0",
"sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7",
"sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94",
"sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff",
"sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82",
"sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd",
"sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893",
"sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e",
"sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d",
"sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901",
"sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9",
"sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c",
"sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7",
"sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891",
"sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f",
"sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a",
"sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9",
"sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5",
"sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e",
"sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a",
"sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c",
"sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f",
"sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514",
"sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b",
"sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302",
"sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096",
"sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0",
"sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27",
"sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884",
"sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a",
"sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357",
"sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430",
"sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221",
"sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325",
"sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4",
"sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05",
"sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55",
"sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875",
"sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970",
"sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc",
"sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6",
"sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f",
"sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b",
"sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d",
"sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15",
"sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118",
"sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee",
"sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e",
"sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6",
"sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208",
"sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede",
"sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3",
"sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e",
"sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada",
"sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175",
"sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a",
"sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c",
"sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f",
"sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58",
"sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f",
"sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a",
"sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a",
"sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921",
"sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e",
"sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904",
"sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776",
"sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52",
"sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf",
"sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8",
"sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f",
"sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b",
"sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63",
"sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c",
"sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f",
"sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468",
"sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e",
"sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab",
"sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2",
"sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb",
"sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb",
"sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132",
"sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b",
"sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607",
"sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934",
"sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698",
"sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e",
"sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561",
"sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de",
"sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b",
"sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a",
"sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595",
"sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402",
"sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881",
"sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429",
"sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5",
"sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7",
"sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c",
"sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531",
"sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6",
"sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521"
],
"markers": "python_version >= '3.7'",
"version": "==2.10.1"
},
"pytest": {
"hashes": [
"sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002",
"sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"
],
"index": "pypi",
"markers": "python_version >= '3.7'",
"version": "==7.4.2"
},
"pytest-html": {
"hashes": [
"sha256:88682b9e8e51392472546a70a2139b27d6bc1834a4afd3e41da33c9d9f91e4a4",
"sha256:907c3e68462df129d3ee96dee58bd63f70216b06421836b22fd3fd57ef314acb"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==4.0.2" "version": "==2.7.1"
},
"pydantic-core": {
"hashes": [
"sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b",
"sha256:042473b6280246b1dbf530559246f6842b56119c2926d1e52b631bdc46075f2a",
"sha256:05b7133a6e6aeb8df37d6f413f7705a37ab4031597f64ab56384c94d98fa0e90",
"sha256:0680b1f1f11fda801397de52c36ce38ef1c1dc841a0927a94f226dea29c3ae3d",
"sha256:0d69b4c2f6bb3e130dba60d34c0845ba31b69babdd3f78f7c0c8fae5021a253e",
"sha256:1404c69d6a676245199767ba4f633cce5f4ad4181f9d0ccb0577e1f66cf4c46d",
"sha256:182245ff6b0039e82b6bb585ed55a64d7c81c560715d1bad0cbad6dfa07b4027",
"sha256:1a388a77e629b9ec814c1b1e6b3b595fe521d2cdc625fcca26fbc2d44c816804",
"sha256:1d90c3265ae107f91a4f279f4d6f6f1d4907ac76c6868b27dc7fb33688cfb347",
"sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400",
"sha256:219da3f096d50a157f33645a1cf31c0ad1fe829a92181dd1311022f986e5fbe3",
"sha256:22057013c8c1e272eb8d0eebc796701167d8377441ec894a8fed1af64a0bf399",
"sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349",
"sha256:224c421235f6102e8737032483f43c1a8cfb1d2f45740c44166219599358c2cd",
"sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c",
"sha256:269322dcc3d8bdb69f054681edff86276b2ff972447863cf34c8b860f5188e2e",
"sha256:2728b01246a3bba6de144f9e3115b532ee44bd6cf39795194fb75491824a1413",
"sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3",
"sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e",
"sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3",
"sha256:390193c770399861d8df9670fb0d1874f330c79caaca4642332df7c682bf6b91",
"sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce",
"sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c",
"sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb",
"sha256:4456f2dca97c425231d7315737d45239b2b51a50dc2b6f0c2bb181fce6207664",
"sha256:470b94480bb5ee929f5acba6995251ada5e059a5ef3e0dfc63cca287283ebfa6",
"sha256:4774f3184d2ef3e14e8693194f661dea5a4d6ca4e3dc8e39786d33a94865cefd",
"sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3",
"sha256:553ef617b6836fc7e4df130bb851e32fe357ce36336d897fd6646d6058d980af",
"sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043",
"sha256:6a46e22a707e7ad4484ac9ee9f290f9d501df45954184e23fc29408dfad61350",
"sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7",
"sha256:75250dbc5290e3f1a0f4618db35e51a165186f9034eff158f3d490b3fed9f8a0",
"sha256:75f7e9488238e920ab6204399ded280dc4c307d034f3924cd7f90a38b1829563",
"sha256:78363590ef93d5d226ba21a90a03ea89a20738ee5b7da83d771d283fd8a56761",
"sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72",
"sha256:800d60565aec896f25bc3cfa56d2277d52d5182af08162f7954f938c06dc4ee3",
"sha256:82d5d4d78e4448683cb467897fe24e2b74bb7b973a541ea1dcfec1d3cbce39fb",
"sha256:852e966fbd035a6468fc0a3496589b45e2208ec7ca95c26470a54daed82a0788",
"sha256:868649da93e5a3d5eacc2b5b3b9235c98ccdbfd443832f31e075f54419e1b96b",
"sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c",
"sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038",
"sha256:95b9d5e72481d3780ba3442eac863eae92ae43a5f3adb5b4d0a1de89d42bb250",
"sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec",
"sha256:997abc4df705d1295a42f95b4eec4950a37ad8ae46d913caeee117b6b198811c",
"sha256:9b5155ff768083cb1d62f3e143b49a8a3432e6789a3abee8acd005c3c7af1c74",
"sha256:9e08e867b306f525802df7cd16c44ff5ebbe747ff0ca6cf3fde7f36c05a59a81",
"sha256:9fdad8e35f278b2c3eb77cbdc5c0a49dada440657bf738d6905ce106dc1de439",
"sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75",
"sha256:a8309f67285bdfe65c372ea3722b7a5642680f3dba538566340a9d36e920b5f0",
"sha256:ae0a8a797a5e56c053610fa7be147993fe50960fa43609ff2a9552b0e07013e8",
"sha256:b14d82cdb934e99dda6d9d60dc84a24379820176cc4a0d123f88df319ae9c150",
"sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438",
"sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae",
"sha256:b89ed9eb7d616ef5714e5590e6cf7f23b02d0d539767d33561e3675d6f9e3857",
"sha256:c4fcf5cd9c4b655ad666ca332b9a081112cd7a58a8b5a6ca7a3104bc950f2038",
"sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374",
"sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f",
"sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241",
"sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592",
"sha256:cc1cfd88a64e012b74e94cd00bbe0f9c6df57049c97f02bb07d39e9c852e19a4",
"sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d",
"sha256:cfeecd1ac6cc1fb2692c3d5110781c965aabd4ec5d32799773ca7b1456ac636b",
"sha256:d4d938ec0adf5167cb335acb25a4ee69a8107e4984f8fbd2e897021d9e4ca21b",
"sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182",
"sha256:d91cb5ea8b11607cc757675051f61b3d93f15eca3cefb3e6c704a5d6e8440f4e",
"sha256:d9319e499827271b09b4e411905b24a426b8fb69464dfa1696258f53a3334641",
"sha256:e0e8b1be28239fc64a88a8189d1df7fad8be8c1ae47fcc33e43d4be15f99cc70",
"sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9",
"sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a",
"sha256:e23ec367a948b6d812301afc1b13f8094ab7b2c280af66ef450efc357d2ae543",
"sha256:e25add29b8f3b233ae90ccef2d902d0ae0432eb0d45370fe315d1a5cf231004b",
"sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f",
"sha256:ef26c9e94a8c04a1b2924149a9cb081836913818e55681722d7f29af88fe7b38",
"sha256:eff2de745698eb46eeb51193a9f41d67d834d50e424aef27df2fcdee1b153845",
"sha256:f0a21cbaa69900cbe1a2e7cad2aa74ac3cf21b10c3efb0fa0b80305274c0e8a2",
"sha256:f459a5ce8434614dfd39bbebf1041952ae01da6bed9855008cb33b875cb024c0",
"sha256:f93a8a2e3938ff656a7c1bc57193b1319960ac015b6e87d76c76bf14fe0244b4",
"sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242"
],
"markers": "python_version >= '3.8'",
"version": "==2.18.2"
},
"pytest": {
"hashes": [
"sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233",
"sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==8.2.0"
},
"pytest-html": {
"hashes": [
"sha256:70a01e8ae5800f4a074b56a4cb1025c8f4f9b038bba5fe31e3c98eb996686f07",
"sha256:c8152cea03bd4e9bee6d525573b67bbc6622967b72b9628dda0ea3e2a0b5dd71"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==4.1.1"
}, },
"pytest-metadata": { "pytest-metadata": {
"hashes": [ "hashes": [
"sha256:769a9c65d2884bd583bc626b0ace77ad15dbe02dd91a9106d47fd46d9c2569ca", "sha256:c8e0844db684ee1c798cfa38908d20d67d0463ecb6137c72e91f418558dd5f4b",
"sha256:a17b1e40080401dc23177599208c52228df463db191c1a573ccdffacd885e190" "sha256:d2a29b0355fbc03f168aa96d41ff88b1a3b44a3b02acbe491801c98a048017c8"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.8'",
"version": "==3.0.0" "version": "==3.1.1"
}, },
"pytest-variables": { "pytest-variables": {
"hashes": [ "hashes": [
"sha256:190d9d4da5a6013eb02df2049f6047d911cdbe44c5b1734a6acc1748433c93d0", "sha256:4719b07f0f6e5d07829b19284a99d9159543a2e0336311f7bc4ee3b1617f595d",
"sha256:ab84235417afac5a0a7dd4c3918287d9c7329d2e16d570d6e943f8d8e02533b9" "sha256:4c864d2b7093f9053a2bed61e4b1d027bb26456924e637fcef2d1455d32732b1"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.8'",
"version": "==3.0.0" "version": "==3.1.0"
}, },
"pyyaml": { "pyyaml": {
"hashes": [ "hashes": [
@ -423,6 +428,7 @@
"sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4",
"sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba",
"sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8",
"sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef",
"sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5",
"sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd",
"sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3",
@ -460,46 +466,58 @@
}, },
"typing-extensions": { "typing-extensions": {
"hashes": [ "hashes": [
"sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0", "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0",
"sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef" "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"
], ],
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==4.8.0" "version": "==4.11.0"
}, },
"urllib3": { "urllib3": {
"hashes": [ "hashes": [
"sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84", "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d",
"sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e" "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.8'",
"version": "==2.0.7" "version": "==2.2.1"
},
"werkzeug": {
"hashes": [
"sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18",
"sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8"
],
"markers": "python_version >= '3.8'",
"version": "==3.0.3"
} }
}, },
"develop": { "develop": {
"black": { "black": {
"hashes": [ "hashes": [
"sha256:0e232f24a337fed7a82c1185ae46c56c4a6167fb0fe37411b43e876892c76699", "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474",
"sha256:30b78ac9b54cf87bcb9910ee3d499d2bc893afd52495066c49d9ee6b21eee06e", "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1",
"sha256:31946ec6f9c54ed7ba431c38bc81d758970dd734b96b8e8c2b17a367d7908171", "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0",
"sha256:31b9f87b277a68d0e99d2905edae08807c007973eaa609da5f0c62def6b7c0bd", "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8",
"sha256:47c4510f70ec2e8f9135ba490811c071419c115e46f143e4dce2ac45afdcf4c9", "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96",
"sha256:481167c60cd3e6b1cb8ef2aac0f76165843a374346aeeaa9d86765fe0dd0318b", "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1",
"sha256:6901631b937acbee93c75537e74f69463adaf34379a04eef32425b88aca88a23", "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04",
"sha256:76baba9281e5e5b230c9b7f83a96daf67a95e919c2dfc240d9e6295eab7b9204", "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021",
"sha256:7fb5fc36bb65160df21498d5a3dd330af8b6401be3f25af60c6ebfe23753f747", "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94",
"sha256:960c21555be135c4b37b7018d63d6248bdae8514e5c55b71e994ad37407f45b8", "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d",
"sha256:a3c2ddb35f71976a4cfeca558848c2f2f89abc86b06e8dd89b5a65c1e6c0f22a", "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c",
"sha256:c870bee76ad5f7a5ea7bd01dc646028d05568d33b0b09b7ecfc8ec0da3f3f39c", "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7",
"sha256:d3d9129ce05b0829730323bdcb00f928a448a124af5acf90aa94d9aba6969604", "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c",
"sha256:db451a3363b1e765c172c3fd86213a4ce63fb8524c938ebd82919bf2a6e28c6a", "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc",
"sha256:e223b731a0e025f8ef427dd79d8cd69c167da807f5710add30cdf131f13dd62e", "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7",
"sha256:f20ff03f3fdd2fd4460b4f631663813e57dc277e37fb216463f3b907aa5a9bdd", "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d",
"sha256:f74892b4b836e5162aa0452393112a574dac85e13902c57dfbaaf388e4eda37c", "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c",
"sha256:f8dc7d50d94063cdfd13c82368afd8588bac4ce360e4224ac399e769d6704e98" "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741",
"sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce",
"sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb",
"sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063",
"sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==23.10.0" "version": "==24.4.2"
}, },
"click": { "click": {
"hashes": [ "hashes": [
@ -511,12 +529,12 @@
}, },
"flake8": { "flake8": {
"hashes": [ "hashes": [
"sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23", "sha256:33f96621059e65eec474169085dc92bf26e7b2d47366b70be2f67ab80dc25132",
"sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5" "sha256:a6dfbb75e03252917f2473ea9653f7cd799c3064e54d4c8140044c5c065f53c3"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_full_version >= '3.8.1'", "markers": "python_full_version >= '3.8.1'",
"version": "==6.1.0" "version": "==7.0.0"
}, },
"mccabe": { "mccabe": {
"hashes": [ "hashes": [
@ -536,27 +554,27 @@
}, },
"packaging": { "packaging": {
"hashes": [ "hashes": [
"sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5",
"sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==23.2" "version": "==24.0"
}, },
"pathspec": { "pathspec": {
"hashes": [ "hashes": [
"sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20", "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08",
"sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3" "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.8'",
"version": "==0.11.2" "version": "==0.12.1"
}, },
"platformdirs": { "platformdirs": {
"hashes": [ "hashes": [
"sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3", "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf",
"sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e" "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.8'",
"version": "==3.11.0" "version": "==4.2.1"
}, },
"pycodestyle": { "pycodestyle": {
"hashes": [ "hashes": [
@ -568,11 +586,11 @@
}, },
"pyflakes": { "pyflakes": {
"hashes": [ "hashes": [
"sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774", "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f",
"sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc" "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"
], ],
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==3.1.0" "version": "==3.2.0"
} }
} }
} }

View File

@ -89,8 +89,8 @@ class SurveyExperimentIntegrationTest {
browserScreen { browserScreen {
verifySurveyNoThanksButton() verifySurveyNoThanksButton()
verifySurveyButton() verifySurveyButton()
}.clickNoThanksSurveyButton {
verifyTabCounter("0")
} }
checkExperimentExists()
} }
} }

View File

@ -0,0 +1,19 @@
import logging
import os
from pathlib import Path
logging.getLogger(__name__).addHandler(logging.NullHandler())
class ADBrun(object):
binary = "adbrun"
logger = logging.getLogger()
here = Path()
def launch(self):
# First close sim if any then launch
os.system(
"~/Library/Android/sdk/platform-tools/adb devices | grep emulator | cut -f1 | while read line; do ~/Library/Android/sdk/platform-tools/adb -s $line emu kill; done"
)
# Then launch sim
os.system("sh launchSimScript.sh")

View File

@ -5,9 +5,10 @@
import json import json
import logging import logging
import os import os
from pathlib import Path import random
import subprocess import subprocess
import time import time
from pathlib import Path
import pytest import pytest
import requests import requests
@ -18,16 +19,65 @@ from experimentintegration.models.models import TelemetryModel
KLAATU_SERVER_URL = "http://localhost:1378" KLAATU_SERVER_URL = "http://localhost:1378"
KLAATU_LOCAL_SERVER_URL = "http://localhost:1378" KLAATU_LOCAL_SERVER_URL = "http://localhost:1378"
here = Path() here = Path().cwd()
def pytest_addoption(parser): def pytest_addoption(parser):
parser.addoption(
"--experiment", action="store", help="The experiments experimenter URL"
)
parser.addoption( parser.addoption(
"--stage", action="store_true", default=None, help="Use the stage server" "--stage", action="store_true", default=None, help="Use the stage server"
) )
parser.addoption(
"--experiment-feature",
action="store",
help="Feature name you want to test against",
)
parser.addoption(
"--experiment", action="store", help="Feature name you want to test against"
)
parser.addoption(
"--experiment-branch",
action="store",
default="control",
help="Experiment Branch you want to test on",
)
def pytest_runtest_setup(item):
envnames = [mark.name for mark in item.iter_markers()]
if envnames:
if item.config.getoption("--experiment-feature") not in envnames:
pytest.skip("test does not match feature name")
def start_process(path, command):
module_path = Path(path)
try:
process = subprocess.Popen(
command,
encoding="utf-8",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
cwd=module_path.absolute(),
)
stdout, stderr = process.communicate(timeout=5)
if process.returncode != 0:
raise Exception(stderr)
except subprocess.TimeoutExpired:
logging.info(f"{module_path.name} started")
return process
@pytest.fixture(name="nimbus_cli_args")
def fixture_nimbus_cli_args():
return ""
@pytest.fixture(name="experiment_branch")
def fixture_experiment_branch(request):
return request.config.getoption("--experiment-branch")
@pytest.fixture(name="load_branches") @pytest.fixture(name="load_branches")
@ -65,17 +115,19 @@ def gradlewbuild(gradlewbuild_log):
@pytest.fixture(name="experiment_data") @pytest.fixture(name="experiment_data")
def fixture_experiment_data(experiment_url): def fixture_experiment_data(experiment_url, request):
data = requests.get(experiment_url).json() data = requests.get(experiment_url).json()
branches = next(iter(data.get("branches")), None) branches = next(iter(data.get("branches")), None)
features = next(iter(branches.get("features")), None) features = next(iter(branches.get("features")), None)
if features.get("messages"): match request.config.getoption("--experiment-feature"):
for item in features["value"]["messages"].values(): case "messaging_survey":
item["surface"] = "homescreen" if features.get("value").get("messages"):
item["style"] = "URGENT" for item in features["value"]["messages"].values():
for count, trigger in enumerate(item["trigger"]): if "USER_EN-US_SPEAKER" in item["trigger-if-all"]:
if "USER_EN_SPEAKER" not in trigger: item["trigger-if-all"] = ["ALWAYS"]
del item["trigger"][count] case _:
pass
logging.debug(f"JSON Data used for this test: {data}")
return [data] return [data]
@ -86,9 +138,9 @@ def fixture_experiment_url(request, variables):
if slug := request.config.getoption("--experiment"): if slug := request.config.getoption("--experiment"):
# Build URL from slug # Build URL from slug
if request.config.getoption("--stage"): if request.config.getoption("--stage"):
url = f"{variables['urls']['stage_server']}/api/v6/experiments/{slug}" url = f"{variables['urls']['stage_server']}/api/v6/experiments/{slug}/"
else: else:
url = f"{variables['urls']['prod_server']}/api/v6/experiments/{slug}" url = f"{variables['urls']['prod_server']}/api/v6/experiments/{slug}/"
else: else:
try: try:
data = requests.get(f"{KLAATU_SERVER_URL}/experiment").json() data = requests.get(f"{KLAATU_SERVER_URL}/experiment").json()
@ -126,24 +178,26 @@ def fixture_experiment_slug(experiment_data):
return experiment_data[0]["slug"] return experiment_data[0]["slug"]
@pytest.fixture(name="ping_server", autouse=True, scope="session")
def fixture_ping_server():
process = start_process("ping_server", ["python", "ping_server.py"])
yield "http://localhost:5000"
process.terminate()
@pytest.fixture(name="delete_telemetry_pings")
def fixture_delete_telemetry_pings(variables):
def runner():
requests.delete(f"{variables['urls']['telemetry_server']}/pings")
return runner
@pytest.fixture(name="start_app") @pytest.fixture(name="start_app")
def fixture_start_app(): def fixture_start_app(run_nimbus_cli_command):
def _(): def _():
command = f"nimbus-cli --app fenix --channel developer open" command = "nimbus-cli --app fenix --channel developer open"
try: run_nimbus_cli_command(command)
out = subprocess.check_output(
command,
cwd=os.path.join(here, os.pardir),
stderr=subprocess.STDOUT,
universal_newlines=True,
shell=True,
)
except subprocess.CalledProcessError as e:
out = e.output
raise
finally:
with open(gradlewbuild_log, "w") as f:
f.write(out)
time.sleep( time.sleep(
15 15
) # Wait a while as there's no real way to know when the app has started ) # Wait a while as there's no real way to know when the app has started
@ -204,12 +258,19 @@ def fixture_check_ping_for_experiment(experiment_slug, variables):
return _check_ping_for_experiment return _check_ping_for_experiment
@pytest.fixture(name="setup_experiment") @pytest.fixture(name="open_app")
def fixture_setup_experiment(experiment_slug, json_data, gradlewbuild_log, variables): def fixture_open_app(run_nimbus_cli_command):
def _(branch): def _():
requests.delete(f"{variables['urls']['telemetry_server']}/pings") command = "nimbus-cli --app fenix --channel developer open"
logging.info(f"Testing experiment {experiment_slug}, BRANCH: {branch[0]}") run_nimbus_cli_command(command)
command = f"nimbus-cli --app fenix --channel developer enroll {experiment_slug} --branch {branch[0]} --file {json_data} --reset-app" time.sleep(5)
return _
@pytest.fixture(name="run_nimbus_cli_command")
def fixture_run_nimbus_cli_command(gradlewbuild_log):
def _run_nimbus_cli_command(command):
logging.info(f"Running command {command}") logging.info(f"Running command {command}")
try: try:
out = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) out = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
@ -219,6 +280,34 @@ def fixture_setup_experiment(experiment_slug, json_data, gradlewbuild_log, varia
finally: finally:
with open(gradlewbuild_log, "w") as f: with open(gradlewbuild_log, "w") as f:
f.write(f"{out}") f.write(f"{out}")
return _run_nimbus_cli_command
@pytest.fixture(name="set_experiment_test_name")
def fixture_set_experiment_test_name(experiment_data):
# Get a random word from the experiments userFacingName attribute.
exp_name = experiment_data[0]["userFacingName"].split()
os.environ["EXP_NAME"] = exp_name[random.randint(0, len(exp_name))]
@pytest.fixture(name="setup_experiment")
def fixture_setup_experiment(
experiment_slug,
json_data,
experiment_branch,
nimbus_cli_args,
run_nimbus_cli_command,
set_experiment_test_name,
delete_telemetry_pings,
):
def _():
delete_telemetry_pings()
logging.info(
f"Testing experiment {experiment_slug}, BRANCH: {experiment_branch}"
)
command = f"nimbus-cli --app fenix --channel developer enroll {experiment_slug} --branch {experiment_branch} --file {json_data} --reset-app {nimbus_cli_args}"
run_nimbus_cli_command(command)
time.sleep( time.sleep(
15 15
) # Wait a while as there's no real way to know when the app has started ) # Wait a while as there's no real way to know when the app has started

View File

@ -1,8 +1,20 @@
# 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/.
import argparse
import subprocess import subprocess
from pathlib import Path from pathlib import Path
import yaml import yaml
parser = argparse.ArgumentParser("Options for android apk downloader")
parser.add_argument(
"--test-files", nargs="+", help="List of test files to generate tests from"
)
args = parser.parse_args()
def search_for_smoke_tests(tests_name): def search_for_smoke_tests(tests_name):
"""Searches for smoke tests within the requested test module.""" """Searches for smoke tests within the requested test module."""
@ -21,16 +33,16 @@ def search_for_smoke_tests(tests_name):
code = file.read().split(" ") code = file.read().split(" ")
code = [item for item in code if item != ""] code = [item for item in code if item != ""]
# Gets the class name from the path e.g.: .ui/HomescreenTest.kt
class_name = f"{file_name.name.strip('kt').strip('.').split('/')[-1]}"
# This is a custom annotation found in fenix/customannotations/SmokeTest.kt
for count, item in enumerate(code): for count, item in enumerate(code):
if "class" in item or "@SmokeTest" in item: if "@SmokeTest" in item:
locations.append(count) locations.append(count)
for location in locations: for location in locations:
if len(test_names) == 0: test_names.append(f"{class_name}#{code[location+3].strip('()')}")
class_name = code[location + 1]
test_names.append(class_name)
else:
test_names.append(f"{class_name}#{code[location+3].strip('()')}")
return test_names return test_names
@ -61,10 +73,10 @@ def generate_smoke_tests(tests_names=None):
tests.append( tests.append(
f""" f"""
@pytest.mark.smoke_test @pytest.mark.smoke_test
def test_smoke_{test_name}(setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment): def test_smoke_{test_name}(setup_experiment, gradlewbuild, open_app):
setup_experiment(load_branches) setup_experiment()
open_app()
gradlewbuild.test("{test}", smoke=True) gradlewbuild.test("{test}", smoke=True)
assert check_ping_for_experiment
""" """
) )
with open(pytest_file, "a") as file: with open(pytest_file, "a") as file:
@ -73,10 +85,16 @@ def test_smoke_{test_name}(setup_experiment, gradlewbuild, load_branches, check_
if __name__ == "__main__": if __name__ == "__main__":
test_modules = None test_modules = []
args = parser.parse_args()
if args.test_files:
test_modules = args.test_files
else:
with open("variables.yaml", "r") as file:
tests = yaml.safe_load(file)
test_modules = [test for test in tests.get("smoke_tests")]
create_test_file() create_test_file()
with open("variables.yaml", "r") as file: print(f"Created tests for modules: {test_modules}")
test_modules = yaml.safe_load(file) for item in test_modules:
for item in test_modules.get("smoke_tests"):
tests = search_for_smoke_tests(item) tests = search_for_smoke_tests(item)
generate_smoke_tests(tests) generate_smoke_tests(tests)

View File

@ -2,7 +2,7 @@ import logging
import os import os
import subprocess import subprocess
from syncintegration.adbrun import ADBrun from experimentintegration.adbrun import ADBrun
here = os.path.dirname(__file__) here = os.path.dirname(__file__)
logging.getLogger(__name__).addHandler(logging.NullHandler()) logging.getLogger(__name__).addHandler(logging.NullHandler())
@ -22,11 +22,7 @@ class GradlewBuild(object):
# Change path accordingly to go to root folder to run gradlew # Change path accordingly to go to root folder to run gradlew
os.chdir("../../../../../../../..") os.chdir("../../../../../../../..")
test_type = "ui" if smoke else "experimentintegration" test_type = "ui" if smoke else "experimentintegration"
cmd = f"adb shell am instrument -w -e class org.mozilla.fenix.{test_type}.{identifier} org.mozilla.fenix.debug.test/androidx.test.runner.AndroidJUnitRunner" cmd = f"adb shell am instrument -w -e class org.mozilla.fenix.{test_type}.{identifier} -e EXP_NAME '{os.getenv('EXP_NAME', '').replace('(', '').replace(')', '')}' org.mozilla.fenix.debug.test/androidx.test.runner.AndroidJUnitRunner"
# if smoke:
# cmd = f"adb shell am instrument -w -e class org.mozilla.fenix.ui.{identifier} org.mozilla.fenix.debug.test/androidx.test.runner.AndroidJUnitRunner"
# else:
# cmd = f"adb shell am instrument -w -e class org.mozilla.fenix.experimentintegration.{identifier} org.mozilla.fenix.debug.test/androidx.test.runner.AndroidJUnitRunner"
self.logger.info("Running cmd: {}".format(cmd)) self.logger.info("Running cmd: {}".format(cmd))
@ -35,6 +31,7 @@ class GradlewBuild(object):
out = subprocess.check_output( out = subprocess.check_output(
cmd, encoding="utf8", shell=True, stderr=subprocess.STDOUT cmd, encoding="utf8", shell=True, stderr=subprocess.STDOUT
) )
logging.debug(out)
if "FAILURES" in out: if "FAILURES" in out:
raise (AssertionError(out)) raise (AssertionError(out))
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:

View File

@ -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/.
import json
import os
import zlib
from flask import Flask, request
from flask.json import jsonify
app = Flask("ping_server")
PINGS = []
@app.route("/pings", methods=["GET", "DELETE"])
def pings():
if request.method == "GET":
return jsonify(PINGS)
if request.method == "DELETE":
PINGS.clear()
return ""
@app.route(
"/submit/<path:telemetry>",
methods=["POST"],
)
def submit(telemetry):
if request.method == "POST":
request_data = request.get_data()
if request.headers.get("Content-Encoding") == "gzip":
request_data = zlib.decompress(request_data, zlib.MAX_WBITS | 16)
ping_data = json.loads(request_data)
# Store JSON data to self.pings to be used by wait_for_pings()
PINGS.append(ping_data)
return ""
return ""
if __name__ == "__main__":
port = int(os.environ.get("PORT", 5000))
app.run(debug=True, host="0.0.0.0", port=port)

View File

@ -2,3 +2,8 @@
addopts = --verbose --html=results/index.html --self-contained-html --variables=variables.yaml addopts = --verbose --html=results/index.html --self-contained-html --variables=variables.yaml
log_cli = true log_cli = true
log_cli_level = info log_cli_level = info
markers =
smoke_test: Smoke tests
messaging_survey: Survey message experiments
messaging_homescreen: homescreen message experiments
generic_test: Generic tests

View File

@ -1,25 +1,34 @@
import pytest import pytest
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True) @pytest.mark.generic_test
def test_experiment_unenrolls_via_studies_toggle( def test_experiment_unenrolls_via_studies_toggle(
setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment setup_experiment, gradlewbuild, open_app
): ):
setup_experiment(load_branches) setup_experiment()
open_app()
gradlewbuild.test("GenericExperimentIntegrationTest#disableStudiesViaStudiesToggle") gradlewbuild.test("GenericExperimentIntegrationTest#disableStudiesViaStudiesToggle")
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
gradlewbuild.test("GenericExperimentIntegrationTest#testExperimentUnenrolled") gradlewbuild.test("GenericExperimentIntegrationTest#testExperimentUnenrolled")
assert check_ping_for_experiment(reason="unenrollment", branch=load_branches[0])
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True) @pytest.mark.generic_test
def test_experiment_unenrolls_via_secret_menu( def test_experiment_enrolls(
setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment setup_experiment, gradlewbuild, open_app, check_ping_for_experiment, load_branches
): ):
setup_experiment(load_branches) setup_experiment()
open_app()
gradlewbuild.test("GenericExperimentIntegrationTest#testExperimentEnrolled")
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
@pytest.mark.generic_test
def test_experiment_unenrolls_via_secret_menu(
setup_experiment, gradlewbuild, load_branches, open_app, check_ping_for_experiment
):
setup_experiment()
open_app()
gradlewbuild.test( gradlewbuild.test(
"GenericExperimentIntegrationTest#testExperimentUnenrolledViaSecretMenu" "GenericExperimentIntegrationTest#testExperimentUnenrolledViaSecretMenu"
) )
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
gradlewbuild.test("GenericExperimentIntegrationTest#testExperimentUnenrolled") gradlewbuild.test("GenericExperimentIntegrationTest#testExperimentUnenrolled")
assert check_ping_for_experiment(reason="unenrollment", branch=load_branches[0]) assert check_ping_for_experiment(reason="unenrollment", branch=load_branches[0])

View File

@ -5,43 +5,31 @@
import pytest import pytest
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True) @pytest.mark.messaging_survey
def test_survey_navigates_correctly( def test_survey_navigates_correctly(setup_experiment, gradlewbuild):
setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment setup_experiment()
):
setup_experiment(load_branches)
gradlewbuild.test("SurveyExperimentIntegrationTest#checkSurveyNavigatesCorrectly") gradlewbuild.test("SurveyExperimentIntegrationTest#checkSurveyNavigatesCorrectly")
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True) @pytest.mark.messaging_survey
def test_survey_no_thanks_navigates_correctly( def test_survey_no_thanks_navigates_correctly(setup_experiment, gradlewbuild):
setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment setup_experiment()
):
setup_experiment(load_branches)
gradlewbuild.test( gradlewbuild.test(
"SurveyExperimentIntegrationTest#checkSurveyNoThanksNavigatesCorrectly" "SurveyExperimentIntegrationTest#checkSurveyNoThanksNavigatesCorrectly"
) )
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True) @pytest.mark.messaging_homescreen
def test_homescreen_survey_dismisses_correctly( def test_homescreen_survey_dismisses_correctly(setup_experiment, gradlewbuild):
setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment setup_experiment()
):
setup_experiment(load_branches)
gradlewbuild.test( gradlewbuild.test(
"SurveyExperimentIntegrationTest#checkHomescreenSurveyDismissesCorrectly" "SurveyExperimentIntegrationTest#checkHomescreenSurveyDismissesCorrectly"
) )
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])
@pytest.mark.parametrize("load_branches", [("branch")], indirect=True) @pytest.mark.messaging_survey
def test_survey_landscape_looks_correct( def test_survey_landscape_looks_correct(setup_experiment, gradlewbuild):
setup_experiment, gradlewbuild, load_branches, check_ping_for_experiment setup_experiment()
):
setup_experiment(load_branches)
gradlewbuild.test( gradlewbuild.test(
"SurveyExperimentIntegrationTest#checkSurveyLandscapeLooksCorrect" "SurveyExperimentIntegrationTest#checkSurveyLandscapeLooksCorrect"
) )
assert check_ping_for_experiment(reason="enrollment", branch=load_branches[0])

View File

@ -5,6 +5,33 @@
urls: urls:
stage_server: "https://stage.experimenter.nonprod.dataops.mozgcp.net" stage_server: "https://stage.experimenter.nonprod.dataops.mozgcp.net"
prod_server: "https://experimenter.services.mozilla.com" prod_server: "https://experimenter.services.mozilla.com"
telemetry_server: "http://172.25.58.187:5000" telemetry_server: "http://127.0.0.1:5000"
smoke_tests: smoke_tests:
- "AddressAutofillTest" - AddressAutofillTest
- BookmarksTest
- CookieBannerBlockerTest
- CrashReportingTest
- CreditCardAutofillTest
- CustomTabsTest
- DownloadTest
- EnhancedTrackingProtectionTest
- FirefoxSuggestTest
- HistoryTest
- HomeScreenTest
- LoginsTest
- MainMenuTest
- MediaNotificationTest
- OnboardingTest
- PDFViewerTest
- RecentlyClosedTabsTest
- SearchTest
- SettingsDeleteBrowsingDataTest
- SettingsAddonsTest
- SettingsGeneralTest
- SettingsHomepageTest
- SettingsSearchTest
- SitePermissionsTest
- SponsoredShortcutsTest
- TabbedBrowsingTest
- TextSelectionTest
- TopSitesTest

View File

View File

@ -46,6 +46,7 @@ import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
import org.mozilla.fenix.helpers.Constants.PackageName.PIXEL_LAUNCHER import org.mozilla.fenix.helpers.Constants.PackageName.PIXEL_LAUNCHER
import org.mozilla.fenix.helpers.Constants.PackageName.YOUTUBE_APP import org.mozilla.fenix.helpers.Constants.PackageName.YOUTUBE_APP
import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime
import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort
import org.mozilla.fenix.helpers.TestHelper.appContext import org.mozilla.fenix.helpers.TestHelper.appContext
@ -308,6 +309,9 @@ object AppAndSystemHelper {
Log.i(TAG, "assertExternalAppOpens: Matched open intent to $appPackageName.") Log.i(TAG, "assertExternalAppOpens: Matched open intent to $appPackageName.")
} catch (e: AssertionFailedError) { } catch (e: AssertionFailedError) {
Log.i(TAG, "assertExternalAppOpens: Intent match failure. ${e.message}") Log.i(TAG, "assertExternalAppOpens: Intent match failure. ${e.message}")
} finally {
// Stop the app from running in the background
forceCloseApp(appPackageName)
} }
} else { } else {
Log.i(TAG, "assertExternalAppOpens: Trying to verify the \"Could not open file\" message.") Log.i(TAG, "assertExternalAppOpens: Trying to verify the \"Could not open file\" message.")
@ -331,6 +335,9 @@ object AppAndSystemHelper {
.waitForExists(waitingTime), .waitForExists(waitingTime),
) )
Log.i(TAG, "assertNativeAppOpens: App package name matched.") Log.i(TAG, "assertNativeAppOpens: App package name matched.")
// Stop the app from running in the background
forceCloseApp(appPackageName)
} else { } else {
Log.i(TAG, "assertNativeAppOpens: Trying to verify the page redirect URL.") Log.i(TAG, "assertNativeAppOpens: Trying to verify the page redirect URL.")
BrowserRobot().verifyUrl(url) BrowserRobot().verifyUrl(url)
@ -342,6 +349,15 @@ object AppAndSystemHelper {
Log.i(TAG, "assertYoutubeAppOpens: Trying to check the intent to YouTube.") Log.i(TAG, "assertYoutubeAppOpens: Trying to check the intent to YouTube.")
intended(toPackage(YOUTUBE_APP)) intended(toPackage(YOUTUBE_APP))
Log.i(TAG, "assertYoutubeAppOpens: Verified the intent matches YouTube.") Log.i(TAG, "assertYoutubeAppOpens: Verified the intent matches YouTube.")
// Stop the app from running in the background
forceCloseApp(YOUTUBE_APP)
}
fun forceCloseApp(appPackageName: String) {
Log.i(TAG, "forceCloseApp: Trying to stop the $appPackageName app from running in the background.")
mDevice.executeShellCommand("am force-stop $appPackageName")
Log.i(TAG, "forceCloseApp: Force-stopped the $appPackageName app.")
} }
/** /**
@ -586,4 +602,13 @@ object AppAndSystemHelper {
e.printStackTrace() e.printStackTrace()
} }
} }
fun dismissSetAsDefaultBrowserOnboardingDialog() {
Log.i(TAG, "dismissSetAsDefaultBrowserOnboardingDialog: Detected API ${Build.VERSION.SDK_INT}")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Log.i(TAG, "dismissSetAsDefaulltBrowserOnboardingDialog: Trying to click the \"Cancel\" dialog button.")
itemWithResIdContainingText("android:id/button2", "Cancel").click()
Log.i(TAG, "dismissSetAsDefaulltBrowserOnboardingDialog: Clicked the \"Cancel\" dialog button.")
}
}
} }

View File

View File

@ -32,8 +32,8 @@ object Constants {
const val RETRY_COUNT = 3 const val RETRY_COUNT = 3
val searchEngineCodes = mapOf( val searchEngineCodes = mapOf(
"LeOSearch" to "client=firefox-b-m", "Google" to "client=firefox-b-m",
"Bing" to "firefox&pc=MOZB&form=MOZMBA", "LeOSearch" to "firefox&pc=MOZB&form=MOZMBA",
"DuckDuckGo" to "t=fpas", "DuckDuckGo" to "t=fpas",
) )

Some files were not shown because too many files have changed in this diff Show More