1 import com.android.build.api.variant.FilterConfiguration
2 import org.apache.tools.ant.util.StringUtils
5 id "com.jetbrains.python.envs" version "$python_envs_plugin"
6 id "com.google.protobuf" version "$protobuf_plugin"
9 apply plugin: 'com.android.application'
10 apply plugin: 'kotlin-android'
11 apply plugin: 'kotlin-parcelize'
12 apply plugin: 'jacoco'
13 apply plugin: 'androidx.navigation.safeargs.kotlin'
14 apply plugin: 'com.google.android.gms.oss-licenses-plugin'
16 import groovy.json.JsonOutput
17 import org.gradle.internal.logging.text.StyledTextOutput.Style
18 import org.gradle.internal.logging.text.StyledTextOutputFactory
19 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
21 import static org.gradle.api.tasks.testing.TestResult.ResultType
23 apply from: 'benchmark.gradle'
26 project.maybeConfigForJetpackBenchmark(it)
27 if (project.hasProperty("testBuildType")) {
28 // Allowing to configure the test build type via command line flag (./gradlew -PtestBuildType=beta ..)
29 // in order to run UI tests against other build variants than debug in automation.
30 testBuildType project.property("testBuildType")
34 applicationId "org.mozilla"
35 minSdkVersion config.minSdkVersion
36 compileSdk config.compileSdkVersion
37 targetSdkVersion config.targetSdkVersion
39 versionName Config.generateDebugVersionName()
40 vectorDrawables.useSupportLibrary = true
41 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
42 testInstrumentationRunnerArguments clearPackageData: 'true'
43 resValue "bool", "IS_DEBUG", "false"
44 buildConfigField "boolean", "USE_RELEASE_VERSIONING", "false"
45 buildConfigField "String", "GIT_HASH", "\"\"" // see override in release builds for why it's blank.
46 // This should be the "public" base URL of AMO.
47 buildConfigField "String", "AMO_BASE_URL", "\"https://addons.mozilla.org\""
48 buildConfigField "String", "AMO_COLLECTION_NAME", "\"Extensions-for-Android\""
49 buildConfigField "String", "AMO_COLLECTION_USER", "\"mozilla\""
50 // These add-ons should be excluded for Mozilla Online builds.
51 buildConfigField "String[]", "MOZILLA_ONLINE_ADDON_EXCLUSIONS",
53 "\"uBlock0@raymondhill.net\"," +
54 "\"firefox@ghostery.com\"," +
55 "\"jid1-MnnxcxisBPnSXQ@jetpack\"," +
56 "\"adguardadblocker@adguard.com\"," +
57 "\"foxyproxy@eric.h.jung\"," +
58 "\"{73a6fe31-595d-460b-a920-fcc0f8843232}\"," +
59 "\"jid1-BoFifL9Vbdl2zQ@jetpack\"," +
60 "\"woop-NoopscooPsnSXQ@jetpack\"," +
61 "\"adnauseam@rednoise.org\"" +
63 // This should be the base URL used to call the AMO API.
64 buildConfigField "String", "AMO_SERVER_URL", "\"https://services.addons.mozilla.org\""
66 def deepLinkSchemeValue = "fenix-dev"
67 buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\""
69 // This allows overriding the target activity for MozillaOnline builds, which happens
70 // as part of the defaultConfig below.
71 def targetActivity = "HomeActivity"
73 // Build flag for "Mozilla Online" variants. See `Config.isMozillaOnline`.
74 if (project.hasProperty("mozillaOnline") || gradle.hasProperty("localProperties.mozillaOnline")) {
75 buildConfigField "boolean", "MOZILLA_ONLINE", "true"
76 targetActivity = "MozillaOnlineHomeActivity"
78 buildConfigField "boolean", "MOZILLA_ONLINE", "false"
81 manifestPlaceholders = [
82 "targetActivity": targetActivity,
83 "deepLinkScheme": deepLinkSchemeValue
87 def releaseTemplate = {
88 // We allow disabling optimization by passing `-PdisableOptimization` to gradle. This is used
89 // in automation for UI testing non-debug builds.
90 shrinkResources !project.hasProperty("disableOptimization")
91 minifyEnabled !project.hasProperty("disableOptimization")
92 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
93 matchingFallbacks = ['release'] // Use on the "release" build type in dependencies (AARs)
95 // Changing the build config can cause files that depend on BuildConfig.java to recompile
96 // so we only set the git hash in release builds to avoid possible recompilation in debug builds.
97 buildConfigField "String", "GIT_HASH", "\"${Config.getGitHash()}\""
99 if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) {
100 signingConfig signingConfigs.debug
103 if (gradle.hasProperty("localProperties.debuggable")) {
110 shrinkResources false
112 applicationIdSuffix ".fenix.debug"
113 resValue "bool", "IS_DEBUG", "true"
114 pseudoLocalesEnabled true
116 nightly releaseTemplate >> {
117 applicationIdSuffix ".fenix"
118 buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
119 def deepLinkSchemeValue = "fenix-nightly"
120 buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\""
121 manifestPlaceholders.putAll([
122 "deepLinkScheme": deepLinkSchemeValue
125 beta releaseTemplate >> {
126 buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
127 applicationIdSuffix ".firefox_beta"
128 def deepLinkSchemeValue = "fenix-beta"
129 buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\""
130 manifestPlaceholders.putAll([
131 // This release type is meant to replace Firefox (Beta channel) and therefore needs to inherit
132 // its sharedUserId for all eternity. See:
133 // https://searchfox.org/mozilla-esr68/search?q=moz_android_shared_id&case=false®exp=false&path=
134 // Shipping an app update without sharedUserId can have
135 // fatal consequences. For example see:
136 // - https://issuetracker.google.com/issues/36924841
137 // - https://issuetracker.google.com/issues/36905922
138 "sharedUserId": "org.mozilla.firefox.sharedID",
139 "deepLinkScheme": deepLinkSchemeValue,
142 release releaseTemplate >> {
143 buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
144 applicationIdSuffix ".firefox"
145 def deepLinkSchemeValue = "fenix"
146 buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\""
147 manifestPlaceholders.putAll([
148 // This release type is meant to replace Firefox (Release channel) and therefore needs to inherit
149 // its sharedUserId for all eternity. See:
150 // https://searchfox.org/mozilla-esr68/search?q=moz_android_shared_id&case=false®exp=false&path=
151 // Shipping an app update without sharedUserId can have
152 // fatal consequences. For example see:
153 // - https://issuetracker.google.com/issues/36924841
154 // - https://issuetracker.google.com/issues/36905922
155 "sharedUserId": "org.mozilla.firefox.sharedID",
156 "deepLinkScheme": deepLinkSchemeValue,
159 benchmark releaseTemplate >> {
160 initWith buildTypes.nightly
161 applicationIdSuffix ".fenix"
172 // All JavaScript code used internally by GeckoView is packaged in a
173 // file called omni.ja. If this file is compressed in the APK,
174 // GeckoView must uncompress it before it can do anything else which
175 // causes a significant delay on startup.
178 // manifest.template.json is converted to manifest.json at build time.
179 // No need to package the template in the APK.
180 ignoreAssetsPattern "manifest.template.json"
184 execution 'ANDROIDX_TEST_ORCHESTRATOR'
185 unitTests.includeAndroidResources = true
186 animationsDisabled = true
189 flavorDimensions.add("product")
199 resources.srcDirs += ['src/androidTest/resources']
209 include "x86", "armeabi-v7a", "arm64-v8a", "x86_64"
214 sourceCompatibility JavaVersion.VERSION_17
215 targetCompatibility JavaVersion.VERSION_17
219 // Profiler issues require us to temporarily package native code compressed to
220 // match the previous APK packaging.
221 // https://bugzilla.mozilla.org/show_bug.cgi?id=1865634
224 it.useLegacyPackaging = true
229 // Because we have runtime language selection we will keep all strings and languages
236 lintConfig file("lint.xml")
237 baseline file("lint-baseline.xml")
241 excludes += ['META-INF/atomicfu.kotlin_module', 'META-INF/AL2.0', 'META-INF/LGPL2.1',
242 'META-INF/LICENSE.md', 'META-INF/LICENSE-notice.md']
245 useLegacyPackaging true
251 unitTests.returnDefaultValues = true
254 // We keep running into memory issues when running our tests. With this config we
255 // reserve more memory and also create a new process after every 80 test classes. This
256 // is a band-aid solution and eventually we should try to find and fix the leaks
259 maxHeapSize = "3072m"
260 minHeapSize = "1024m"
269 kotlinCompilerExtensionVersion = Versions.compose_compiler
272 namespace 'org.mozilla.fenix'
275 android.applicationVariants.configureEach { variant ->
277 // -------------------------------------------------------------------------------------------------
278 // Generate version codes for builds
279 // -------------------------------------------------------------------------------------------------
281 def isDebug = variant.buildType.resValues['bool/IS_DEBUG']?.value ?: false
282 def useReleaseVersioning = variant.buildType.buildConfigFields['USE_RELEASE_VERSIONING']?.value ?: false
284 println("----------------------------------------------")
285 println("Variant name: " + variant.name)
286 println("Application ID: " + [variant.applicationId, variant.buildType.applicationIdSuffix].findAll().join())
287 println("Build type: " + variant.buildType.name)
288 println("Flavor: " + variant.flavorName)
289 println("Telemetry enabled: " + !isDebug)
291 if (useReleaseVersioning) {
292 // The Google Play Store does not allow multiple APKs for the same app that all have the
293 // same version code. Therefore we need to have different version codes for our ARM and x86
296 def versionName = variant.buildType.name == 'nightly' ? Config.nightlyVersionName() : Config.releaseVersionName(project)
297 println("versionName override: $versionName")
299 variant.outputs.each { output ->
300 def isMozillaOnline = project.hasProperty("mozillaOnline") || gradle.hasProperty("localProperties.mozillaOnline")
301 def abi = output.getFilter(FilterConfiguration.FilterType.ABI.name())
302 // If it is a Mozilla Online build, use a unified version code of armeabi-v7a
303 def arch = (isMozillaOnline) ? "armeabi-v7a" : abi
304 def aab = project.hasProperty("aab")
305 // We use the same version code generator, that we inherited from Fennec, across all channels - even on
306 // channels that never shipped a Fennec build.
307 def versionCodeOverride = Config.generateFennecVersionCode(arch, aab)
309 println("versionCode for $abi = $versionCodeOverride, isMozillaOnline = $isMozillaOnline")
311 if (versionName != null) {
312 output.versionNameOverride = versionName
314 output.versionCodeOverride = versionCodeOverride
316 } else if (gradle.hasProperty("localProperties.branchBuild.fenix.version")) {
317 def versionName = gradle.getProperty("localProperties.branchBuild.fenix.version")
318 println("versionName override: $versionName")
319 variant.outputs.each { output ->
320 output.versionNameOverride = versionName
324 // -------------------------------------------------------------------------------------------------
325 // BuildConfig: Set variables for Sentry, Crash Reporting, and Telemetry
326 // -------------------------------------------------------------------------------------------------
328 buildConfigField 'String', 'SENTRY_TOKEN', 'null'
330 buildConfigField 'boolean', 'CRASH_REPORTING', 'true'
331 // Reading sentry token from local file (if it exists). In a release task on taskcluster it will be available.
333 def token = new File("${rootDir}/.sentry_token").text.trim()
334 buildConfigField 'String', 'SENTRY_TOKEN', '"' + token + '"'
335 } catch (FileNotFoundException ignored) {}
337 buildConfigField 'boolean', 'CRASH_REPORTING', 'false'
341 buildConfigField 'boolean', 'TELEMETRY', 'true'
343 buildConfigField 'boolean', 'TELEMETRY', 'false'
346 def buildDate = Config.generateBuildDate()
347 // Setting buildDate with every build changes the generated BuildConfig, which slows down the
348 // build. Only do this for non-debug builds, to speed-up builds produced during local development.
350 buildConfigField 'String', 'BUILD_DATE', '"debug build"'
352 buildConfigField 'String', 'BUILD_DATE', '"' + buildDate + '"'
355 // -------------------------------------------------------------------------------------------------
356 // Adjust: Read token from local file if it exists (Only release builds)
357 // -------------------------------------------------------------------------------------------------
359 print("Adjust token: ")
363 def token = new File("${rootDir}/.adjust_token").text.trim()
364 buildConfigField 'String', 'ADJUST_TOKEN', '"' + token + '"'
365 println "(Added from .adjust_token file)"
366 } catch (FileNotFoundException ignored) {
367 buildConfigField 'String', 'ADJUST_TOKEN', 'null'
371 buildConfigField 'String', 'ADJUST_TOKEN', 'null'
375 // -------------------------------------------------------------------------------------------------
376 // MLS: Read token from local file if it exists
377 // -------------------------------------------------------------------------------------------------
382 def token = new File("${rootDir}/.mls_token").text.trim()
383 buildConfigField 'String', 'MLS_TOKEN', '"' + token + '"'
384 println "(Added from .mls_token file)"
385 } catch (FileNotFoundException ignored) {
386 buildConfigField 'String', 'MLS_TOKEN', '""'
390 // -------------------------------------------------------------------------------------------------
391 // Nimbus: Read endpoint from local.properties of a local file if it exists
392 // -------------------------------------------------------------------------------------------------
394 print("Nimbus endpoint: ")
398 def url = new File("${rootDir}/.nimbus").text.trim()
399 buildConfigField 'String', 'NIMBUS_ENDPOINT', '"' + url + '"'
400 println "(Added from .nimbus file)"
401 } catch (FileNotFoundException ignored) {
402 buildConfigField 'String', 'NIMBUS_ENDPOINT', 'null'
405 } else if (gradle.hasProperty("localProperties.nimbus.remote-settings.url")) {
406 def url=gradle.getProperty("localProperties.nimbus.remote-settings.url")
407 buildConfigField 'String', 'NIMBUS_ENDPOINT', '"' + url + '"'
408 println "(Added from local.properties file)"
410 buildConfigField 'String', 'NIMBUS_ENDPOINT', 'null'
414 // -------------------------------------------------------------------------------------------------
415 // Glean: Read custom server URL from local.properties of a local file if it exists
416 // -------------------------------------------------------------------------------------------------
418 print("Glean custom server URL: ")
420 if (gradle.hasProperty("localProperties.glean.custom.server.url")) {
421 def url=gradle.getProperty("localProperties.glean.custom.server.url")
422 buildConfigField 'String', 'GLEAN_CUSTOM_URL', url
423 println "(Added from local.properties file)"
425 buildConfigField 'String', 'GLEAN_CUSTOM_URL', 'null'
429 // -------------------------------------------------------------------------------------------------
430 // BuildConfig: Set flag for official builds; similar to MOZILLA_OFFICIAL in mozilla-central.
431 // -------------------------------------------------------------------------------------------------
433 if (project.hasProperty("official") || gradle.hasProperty("localProperties.official")) {
434 buildConfigField 'Boolean', 'MOZILLA_OFFICIAL', 'true'
436 buildConfigField 'Boolean', 'MOZILLA_OFFICIAL', 'false'
439 // -------------------------------------------------------------------------------------------------
440 // BuildConfig: Set remote wallpaper URL using local file if it exists
441 // -------------------------------------------------------------------------------------------------
443 print("Wallpaper URL: ")
446 def token = new File("${rootDir}/.wallpaper_url").text.trim()
447 buildConfigField 'String', 'WALLPAPER_URL', '"' + token + '"'
448 println "(Added from .wallpaper_url file)"
449 } catch (FileNotFoundException ignored) {
450 buildConfigField 'String', 'WALLPAPER_URL', '""'
454 // -------------------------------------------------------------------------------------------------
455 // BuildConfig: Set the Pocket consumer key from a local file if it exists
456 // -------------------------------------------------------------------------------------------------
458 print("Pocket consumer key: ")
461 def token = new File("${rootDir}/.pocket_consumer_key").text.trim()
462 buildConfigField 'String', 'POCKET_CONSUMER_KEY', '"' + token + '"'
463 println "(Added from .pocket_consumer_key file)"
464 } catch (FileNotFoundException ignored) {
465 buildConfigField 'String', 'POCKET_CONSUMER_KEY', '""'
469 // -------------------------------------------------------------------------------------------------
470 // BuildConfig: Set flag to disable LeakCanary in debug (on CI builds)
471 // -------------------------------------------------------------------------------------------------
474 if (project.hasProperty("disableLeakCanary") || gradle.hasProperty("localProperties.disableLeakCanary")) {
475 buildConfigField "boolean", "LEAKCANARY", "false"
476 println("LeakCanary enabled in debug: false")
478 buildConfigField "boolean", "LEAKCANARY", "true"
479 println("LeakCanary enabled in debug: true")
482 buildConfigField "boolean", "LEAKCANARY", "false"
487 // Generate Kotlin code for the Fenix Glean metrics.
488 apply plugin: "org.mozilla.telemetry.glean-gradle-plugin"
489 apply plugin: "org.mozilla.appservices.nimbus-gradle-plugin"
492 // The path to the Nimbus feature manifest file
493 manifestFile = "nimbus.fml.yaml"
494 // The fully qualified class name for the generated features.
495 // Map from the variant name to the channel as experimenter and nimbus understand it.
496 // If nimbus's channels were accurately set up well for this project, then this
497 // shouldn't be needed.
499 fenixDebug: "developer",
500 fenixNightly: "nightly",
502 fenixRelease: "release",
503 fenixBenchmark: "developer",
505 // This is generated by the FML and should be checked into git.
506 // It will be fetched by Experimenter (the Nimbus experiment website)
507 // and used to inform experiment configuration.
508 experimenterManifest = ".experimenter.yaml"
509 applicationServicesDir = gradle.hasProperty('localProperties.autoPublish.application-services.dir')
510 ? gradle.getProperty('localProperties.autoPublish.application-services.dir') : null
513 tasks.withType(KotlinCompile).configureEach {
514 kotlinOptions.freeCompilerArgs += "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
518 implementation project(':browser-engine-gecko')
520 implementation ComponentsDependencies.kotlin_coroutines
521 testImplementation ComponentsDependencies.testing_coroutines
522 implementation ComponentsDependencies.androidx_appcompat
523 implementation ComponentsDependencies.androidx_constraintlayout
524 implementation ComponentsDependencies.androidx_coordinatorlayout
525 implementation FenixDependencies.google_accompanist_drawablepainter
527 implementation ComponentsDependencies.thirdparty_sentry
529 implementation project(':compose-awesomebar')
530 implementation project(':compose-cfr')
532 implementation project(':concept-awesomebar')
533 implementation project(':concept-base')
534 implementation project(':concept-engine')
535 implementation project(':concept-menu')
536 implementation project(':concept-push')
537 implementation project(':concept-storage')
538 implementation project(':concept-sync')
539 implementation project(':concept-toolbar')
540 implementation project(':concept-tabstray')
542 implementation project(':browser-domains')
543 implementation project(':browser-icons')
544 implementation project(':browser-menu')
545 implementation project(':browser-menu2')
546 implementation project(':browser-session-storage')
547 implementation project(':browser-state')
548 implementation project(':browser-storage-sync')
549 implementation project(':browser-tabstray')
550 implementation project(':browser-thumbnails')
551 implementation project(':browser-toolbar')
553 implementation project(':feature-addons')
554 implementation project(':feature-accounts')
555 implementation project(':feature-app-links')
556 implementation project(':feature-autofill')
557 implementation project(':feature-awesomebar')
558 implementation project(':feature-contextmenu')
559 implementation project(':feature-customtabs')
560 implementation project(':feature-downloads')
561 implementation project(':feature-fxsuggest')
562 implementation project(':feature-intent')
563 implementation project(':feature-media')
564 implementation project(':feature-prompts')
565 implementation project(':feature-push')
566 implementation project(':feature-privatemode')
567 implementation project(':feature-pwa')
568 implementation project(':feature-qr')
569 implementation project(':feature-search')
570 implementation project(':feature-session')
571 implementation project(':feature-syncedtabs')
572 implementation project(':feature-toolbar')
573 implementation project(':feature-tabs')
574 implementation project(':feature-findinpage')
575 implementation project(':feature-logins')
576 implementation project(':feature-sitepermissions')
577 implementation project(':feature-readerview')
578 implementation project(':feature-tab-collections')
579 implementation project(':feature-recentlyclosed')
580 implementation project(':feature-top-sites')
581 implementation project(':feature-share')
582 implementation project(':feature-accounts-push')
583 implementation project(':feature-webauthn')
584 implementation project(':feature-webcompat')
585 implementation project(':feature-webnotifications')
586 implementation project(':feature-webcompat-reporter')
588 implementation project(':service-pocket')
589 implementation project(':service-contile')
590 implementation project(':service-digitalassetlinks')
591 implementation project(':service-sync-autofill')
592 implementation project(':service-sync-logins')
593 implementation project(':service-firefox-accounts')
594 implementation project(':service-glean')
595 implementation project(':service-location')
596 implementation project(':service-nimbus')
598 implementation project(':support-webextensions')
599 implementation project(':support-base')
600 implementation project(':support-rusterrors')
601 implementation project(':support-images')
602 implementation project(':support-ktx')
603 implementation project(':support-rustlog')
604 implementation project(':support-utils')
605 implementation project(':support-locale')
607 implementation project(':ui-colors')
608 implementation project(':ui-icons')
609 implementation project(':lib-publicsuffixlist')
610 implementation project(':ui-widgets')
611 implementation project(':ui-tabcounter')
613 implementation project(':lib-crash')
614 implementation project(':lib-crash-sentry')
615 implementation project(':lib-push-firebase')
616 implementation project(':lib-state')
617 implementation project(':lib-dataprotect')
619 debugImplementation ComponentsDependencies.leakcanary
620 debugImplementation ComponentsDependencies.androidx_compose_ui_tooling
622 implementation ComponentsDependencies.androidx_activity_compose
623 implementation FenixDependencies.androidx_activity_ktx
624 implementation ComponentsDependencies.androidx_annotation
625 implementation ComponentsDependencies.androidx_compose_ui
626 implementation ComponentsDependencies.androidx_compose_ui_tooling_preview
627 implementation ComponentsDependencies.androidx_compose_animation
628 implementation ComponentsDependencies.androidx_compose_foundation
629 implementation ComponentsDependencies.androidx_compose_material
630 implementation FenixDependencies.androidx_legacy
631 implementation ComponentsDependencies.androidx_biometric
632 implementation ComponentsDependencies.androidx_paging
633 implementation ComponentsDependencies.androidx_preferences
634 implementation ComponentsDependencies.androidx_fragment
635 implementation FenixDependencies.androidx_navigation_fragment
636 implementation FenixDependencies.androidx_navigation_ui
637 implementation ComponentsDependencies.androidx_compose_navigation
638 implementation ComponentsDependencies.androidx_recyclerview
639 implementation ComponentsDependencies.androidx_lifecycle_common
640 implementation ComponentsDependencies.androidx_lifecycle_livedata
641 implementation ComponentsDependencies.androidx_lifecycle_process
642 implementation ComponentsDependencies.androidx_lifecycle_runtime
644 implementation ComponentsDependencies.androidx_lifecycle_viewmodel
645 implementation ComponentsDependencies.androidx_core
646 implementation ComponentsDependencies.androidx_core_ktx
647 implementation FenixDependencies.androidx_core_splashscreen
648 implementation FenixDependencies.androidx_transition
649 implementation ComponentsDependencies.androidx_work_runtime
650 implementation FenixDependencies.androidx_datastore
651 implementation ComponentsDependencies.androidx_data_store_preferences
652 implementation FenixDependencies.protobuf_javalite
653 implementation ComponentsDependencies.google_material
655 implementation FenixDependencies.adjust
656 implementation FenixDependencies.installreferrer // Required by Adjust
658 implementation FenixDependencies.google_ads_id // Required for the Google Advertising ID
660 // Required for in-app reviews
661 implementation FenixDependencies.google_play_review
662 implementation FenixDependencies.google_play_review_ktx
664 implementation FenixDependencies.androidx_profileinstaller
666 androidTestImplementation ComponentsDependencies.androidx_test_uiautomator
667 androidTestImplementation FenixDependencies.fastlane
668 // This Falcon version is added to maven central now required for Screengrab
669 androidTestImplementation FenixDependencies.falcon
671 androidTestImplementation ComponentsDependencies.androidx_compose_ui_test
673 androidTestImplementation ComponentsDependencies.androidx_espresso_core, {
674 exclude group: 'com.android.support', module: 'support-annotations'
677 androidTestImplementation(FenixDependencies.espresso_contrib) {
678 exclude module: 'appcompat-v7'
679 exclude module: 'support-v4'
680 exclude module: 'support-annotations'
681 exclude module: 'recyclerview-v7'
682 exclude module: 'design'
683 exclude module: 'espresso-core'
684 exclude module: 'protobuf-lite'
687 androidTestImplementation ComponentsDependencies.androidx_test_core
688 androidTestImplementation FenixDependencies.espresso_idling_resources
689 androidTestImplementation FenixDependencies.espresso_intents
691 androidTestImplementation ComponentsDependencies.androidx_test_runner
692 androidTestImplementation ComponentsDependencies.androidx_test_rules
693 androidTestUtil FenixDependencies.orchestrator
694 androidTestImplementation ComponentsDependencies.androidx_espresso_core, {
695 exclude group: 'com.android.support', module: 'support-annotations'
698 androidTestImplementation ComponentsDependencies.androidx_test_junit
699 androidTestImplementation ComponentsDependencies.androidx_work_testing
700 androidTestImplementation FenixDependencies.androidx_benchmark_junit4
701 androidTestImplementation ComponentsDependencies.testing_mockwebserver
702 testImplementation project(':support-test')
703 testImplementation project(':support-test-libstate')
704 testImplementation ComponentsDependencies.androidx_test_junit
705 testImplementation ComponentsDependencies.androidx_work_testing
706 testImplementation (ComponentsDependencies.testing_robolectric) {
707 exclude group: 'org.apache.maven'
710 testImplementation ComponentsDependencies.testing_maven_ant_tasks
711 implementation project(':support-rusthttp')
713 androidTestImplementation FenixDependencies.mockk_android
714 testImplementation FenixDependencies.mockk
716 // For the initial release of Glean 19, we require consumer applications to
717 // depend on a separate library for unit tests. This will be removed in future releases.
718 testImplementation "org.mozilla.telemetry:glean-native-forUnitTests:${project.ext.glean_version}"
720 lintChecks project(":mozilla-lint-rules")
725 artifact = FenixDependencies.protobuf_compiler
728 // Generates the java Protobuf-lite code for the Protobufs in this project. See
729 // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
730 // for more information.
742 if (project.hasProperty("coverage")) {
743 tasks.withType(Test).configureEach {
744 jacoco.includeNoLocationClasses = true
745 jacoco.excludes = ['jdk.internal.*']
749 toolVersion = Versions.jacoco
752 android.applicationVariants.configureEach { variant ->
753 tasks.register("jacoco${variant.name.capitalize()}TestReport", JacocoReport) {
754 dependsOn "test${variant.name.capitalize()}UnitTest"
761 def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*',
762 '**/*Test*.*', 'android/**/*.*', '**/*$[0-9].*']
763 def kotlinDebugTree = fileTree(dir: "$project.layout.buildDirectory/tmp/kotlin-classes/${variant.name}", excludes: fileFilter)
764 def javaDebugTree = fileTree(dir: "$project.layout.buildDirectory/intermediates/classes/${variant.flavorName}/${variant.buildType.name}",
765 excludes: fileFilter)
766 def mainSrc = "$project.projectDir/src/main/java"
768 sourceDirectories.setFrom(files([mainSrc]))
769 classDirectories.setFrom(files([kotlinDebugTree, javaDebugTree]))
770 executionData.setFrom(fileTree(dir: project.layout.buildDirectory, includes: [
771 "jacoco/test${variant.name.capitalize()}UnitTest.exec",
772 'outputs/code-coverage/connected/*coverage.ec'
780 testCoverageEnabled true
786 // -------------------------------------------------------------------------------------------------
787 // Task for printing APK information for the requested variant
788 // Usage: "./gradlew printVariants
789 // -------------------------------------------------------------------------------------------------
790 tasks.register('printVariants') {
792 def variants = android.applicationVariants.collect { variant -> [
793 apks: variant.outputs.collect { output -> [
794 abi: output.getFilter(FilterConfiguration.FilterType.ABI.name()),
795 fileName: output.outputFile.name
797 build_type: variant.buildType.name,
800 // AndroidTest is a special case not included above
804 fileName: 'app-debug-androidTest.apk',
806 build_type: 'androidTest',
809 println 'variants: ' + JsonOutput.toJson(variants)
813 tasks.register('buildTranslationArray') {
814 // This isn't running as a task, instead the array is build when the gradle file is parsed.
815 // https://github.com/mozilla-mobile/fenix/issues/14175
816 def foundLocales = new StringBuilder()
817 foundLocales.append("new String[]{")
819 fileTree("src/main/res").visit { FileVisitDetails details ->
820 if (details.file.path.endsWith("${File.separator}strings.xml")) {
821 def languageCode = details.file.parent.tokenize(File.separator).last().replaceAll('values-', '').replaceAll('-r', '-')
822 languageCode = (languageCode == "values") ? "en-US" : languageCode
823 foundLocales.append("\"").append(languageCode).append("\"").append(",")
827 foundLocales.append("}")
828 def foundLocalesString = foundLocales.toString().replaceAll(',}', '}')
829 android.defaultConfig.buildConfigField "String[]", "SUPPORTED_LOCALE_ARRAY", foundLocalesString
834 // Format test output. Ported from AC #2401
835 tasks.withType(Test).configureEach {
836 systemProperty "robolectric.logging", "stdout"
837 systemProperty "logging.test-mode", "true"
839 testLogging.events = []
841 def out = services.get(StyledTextOutputFactory).create("tests")
843 beforeSuite { descriptor ->
844 if (descriptor.getClassName() != null) {
845 out.style(Style.Header).println("\nSUITE: " + descriptor.getClassName())
849 beforeTest { descriptor ->
850 out.style(Style.Description).println(" TEST: " + descriptor.getName())
853 onOutput { descriptor, event ->
854 logger.lifecycle(" " + event.message.trim())
857 afterTest { descriptor, result ->
858 switch (result.getResultType()) {
859 case ResultType.SUCCESS:
860 out.style(Style.Success).println(" SUCCESS")
863 case ResultType.FAILURE:
864 out.style(Style.Failure).println(" FAILURE")
865 logger.lifecycle("", result.getException())
868 case ResultType.SKIPPED:
869 out.style(Style.Info).println(" SKIPPED")
877 if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopsrcdir')) {
878 if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopobjdir')) {
879 ext.topobjdir = gradle."localProperties.dependencySubstitutions.geckoviewTopobjdir"
881 ext.topsrcdir = StringUtils.removeSuffix(gradle."localProperties.dependencySubstitutions.geckoviewTopsrcdir", File.separator)
882 apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
885 if (gradle.hasProperty('localProperties.autoPublish.glean.dir')) {
886 ext.gleanSrcDir = gradle."localProperties.autoPublish.glean.dir"
887 apply from: "../${gleanSrcDir}/build-scripts/substitute-local-glean.gradle"
890 android.applicationVariants.configureEach { variant ->
891 tasks.register("apkSize${variant.name.capitalize()}", ApkSizeTask) {
892 variantName = variant.name
893 apks = variant.outputs.collect { output -> output.outputFile.name }
894 dependsOn "package${variant.name.capitalize()}"
898 // Enable expiration by major version.
899 ext.gleanExpireByVersion = Config.majorVersion()