fenix/app/build.gradle
Petru Lingurar f7087e46e3 Fix #5067 - Refactor ShareController to use SendTabUseCases
Navigation between app fragments uses ShareTab as arguments. The newly used
SendTabUseCases uses TabData which is not Parcelable.
For minimal changes we'll keep both data classes and ShareController will know
how to map between the two.
Removed the `sessionId` property of ShareTab as it isn't needed anymore.
2019-09-03 12:01:26 -07:00

619 lines
24 KiB
Groovy

plugins {
id "com.jetbrains.python.envs" version "0.0.26"
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'jacoco'
apply from: "$project.rootDir/automation/gradle/versionCode.gradle"
apply plugin: 'androidx.navigation.safeargs.kotlin'
apply plugin: 'com.google.android.gms.oss-licenses-plugin'
import com.android.build.gradle.internal.tasks.AppPreBuildTask
import org.gradle.internal.logging.text.StyledTextOutput.Style
import org.gradle.internal.logging.text.StyledTextOutputFactory
import static org.gradle.api.tasks.testing.TestResult.ResultType
import com.android.build.OutputFile
android {
compileSdkVersion 28
defaultConfig {
applicationId "org.mozilla"
minSdkVersion Config.minSdkVersion
targetSdkVersion Config.targetSdkVersion
versionCode 1
versionName Config.generateDebugVersionName()
vectorDrawables.useSupportLibrary = true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: 'true'
manifestPlaceholders.isRaptorEnabled = "false"
resValue "bool", "IS_DEBUG", "false"
buildConfigField "boolean", "USE_RELEASE_VERSIONING", "false"
}
def releaseTemplate = {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
matchingFallbacks = ['release'] // Use on the "release" build type in dependencies (AARs)
}
buildTypes {
debug {
shrinkResources false
minifyEnabled false
applicationIdSuffix ".fenix.debug"
manifestPlaceholders.isRaptorEnabled = "true"
resValue "bool", "IS_DEBUG", "true"
pseudoLocalesEnabled true
}
forPerformanceTest releaseTemplate >> { // the ">>" concatenates the raptor-specific options with the template
manifestPlaceholders.isRaptorEnabled = "true"
applicationIdSuffix ".fenix.performancetest"
debuggable true
}
fenixNightlyLegacy releaseTemplate >> {
applicationIdSuffix ".fenix"
buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
}
fenixNightly releaseTemplate >> {
applicationIdSuffix ".fenix.nightly"
buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
}
fenixBeta releaseTemplate >> {
applicationIdSuffix ".fenix.beta"
buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
}
fenixProduction releaseTemplate >> {
applicationIdSuffix ".fenix"
buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
}
fennecProduction releaseTemplate >> {
buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
applicationIdSuffix ".firefox"
manifestPlaceholders = [
// This release type is meant to replace Firefox (Release channel) and therefore needs to inherit
// its sharedUserId for all eternity. See:
// https://searchfox.org/mozilla-central/search?q=moz_android_shared_id&case=false&regexp=false&path=
// Shipping an app update without sharedUserId can have
// fatal consequences. For example see:
// - https://issuetracker.google.com/issues/36924841
// - https://issuetracker.google.com/issues/36905922
"sharedUserId": "org.mozilla.firefox.sharedID"
]
}
}
variantFilter { // There's a "release" build type that exists by default that we don't use (it's replaced by "nightly" and "beta")
if (buildType.name == 'release') {
setIgnore true
}
// Current build variant setup:
//
// | geckoNightly | geckoBeta |
// |--------------------|---------------|-----------|
// | debug | ✅ | ✅ | Both variants for testing and development.
// | forPerformanceTest | ✅ | ✅ | Both variants unless the perf team only cares about Nightly (TBD).
// | fenixNightlyLegacy | ✅ | ✅ | Release type will be decommissioned soon.
// | fenixNightly | ✅ | ✅ | Built with both, but only the "geckoNightly" one is published to Google Play
// | fenixBeta | ❌ | ✅ | Fenix Beta ships with GV Beta
// | fenixProduction | ❌ | ✅ | Fenix Production ships with GV Beta
// | fennecProduction | ❌ | ✅ | Fenix build to replace production Firefox builds
//
def flavors = flavors*.name.toString().toLowerCase()
if (buildType.name == 'fenixBeta' && flavors.contains("geckonightly")) {
setIgnore true
}
if (buildType.name == 'fenixProduction' && flavors.contains("geckonightly")) {
setIgnore true
}
if (buildType.name == 'fennecProduction' && flavors.contains("geckonightly")) {
setIgnore true
}
}
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
unitTests.includeAndroidResources = true
}
flavorDimensions "engine"
productFlavors {
geckoNightly {
dimension "engine"
}
geckoBeta {
dimension "engine"
}
}
splits {
abi {
enable true
reset()
include "x86", "armeabi-v7a", "arm64-v8a", "x86_64"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
lintConfig file("lint.xml")
}
packagingOptions {
exclude 'META-INF/atomicfu.kotlin_module'
}
testOptions {
unitTests.returnDefaultValues = true
}
}
def baseVersionCode = generatedVersionCode
android.applicationVariants.all { variant ->
// -------------------------------------------------------------------------------------------------
// Set up kotlin-allopen plugin for writing tests
// -------------------------------------------------------------------------------------------------
boolean hasTest = gradle.startParameter.taskNames.find { it.contains("test") || it.contains("Test") } != null
if (hasTest) {
apply plugin: 'kotlin-allopen'
allOpen {
annotation("org.mozilla.fenix.test.OpenClass")
}
}
// -------------------------------------------------------------------------------------------------
// Generate version codes for builds
// -------------------------------------------------------------------------------------------------
def isDebug = variant.buildType.resValues['IS_DEBUG']?.value ?: false
def useReleaseVersioning = variant.buildType.buildConfigFields['USE_RELEASE_VERSIONING']?.value ?: false
def versionName = Config.releaseVersionName(project)
println("----------------------------------------------")
println("Variant name: " + variant.name)
println("Application ID: " + [variant.mergedFlavor.applicationId, variant.buildType.applicationIdSuffix].findAll().join())
println("Build type: " + variant.buildType.name)
println("Flavor: " + variant.flavorName)
println("Telemetry enabled: " + !isDebug)
if (useReleaseVersioning) {
// The Google Play Store does not allow multiple APKs for the same app that all have the
// same version code. Therefore we need to have different version codes for our ARM and x86
// builds.
// Our generated version code now has a length of 9 (See automation/gradle/versionCode.gradle).
// Our x86 builds need a higher version code to avoid installing ARM builds on an x86 device
// with ARM compatibility mode.
variant.outputs.each { output ->
def abi = output.getFilter(OutputFile.ABI)
def versionCodeOverride
if (variant.name.contains("Fennec")) {
versionCodeOverride = Config.generateFennecVersionCode(abi)
} else if (abi == "x86_64") {
versionCodeOverride = baseVersionCode + 3
} else if (abi == "x86") {
versionCodeOverride = baseVersionCode + 2
} else if (abi == "arm64-v8a") {
versionCodeOverride = baseVersionCode + 1
} else if (abi == "armeabi-v7a") {
versionCodeOverride = baseVersionCode
} else {
throw RuntimeException("Unknown ABI: $abi")
}
println("versionCode for $abi = $versionCodeOverride")
output.versionNameOverride = versionName
output.versionCodeOverride = versionCodeOverride
}
// If this is a release build, validate that "versionName" is set
tasks.withType(AppPreBuildTask) { prebuildTask ->
// You can't add a closure to a variant, so we need to look for an early variant-specific type
// of task (AppPreBuildTask is the first) and filter to make sure we're looking at the task for
// this variant that we're currently configuring
if (prebuildTask.variantName != variant.name) {
return
}
// Append to the task so the first thing it does is run our validation
prebuildTask.doFirst {
if (!project.hasProperty('versionName')) {
throw new RuntimeException("Release builds require the 'versionName' property to be set.\n" +
"If you're using an IDE, set your build variant to be a \"debug\" type.\n" +
"If you're using the command-line, either build a debug variant instead ('./gradlew assembleDebug')\n" +
"\tor continue building the release build and set the \"versionName\" property ('./gradlew -PversionName=<...> assembleNightly').")
// TODO when Android Studio 3.5.0 is prevalent, we can set the "debug" build type as the default
// https://issuetracker.google.com/issues/36988145#comment59
}
}
}
}
// -------------------------------------------------------------------------------------------------
// BuildConfig: Set variables for Sentry, Crash Reporting, and Telemetry
// -------------------------------------------------------------------------------------------------
buildConfigField 'String', 'SENTRY_TOKEN', 'null'
if (!isDebug) {
buildConfigField 'boolean', 'CRASH_REPORTING', 'true'
// Reading sentry token from local file (if it exists). In a release task on taskcluster it will be available.
try {
def token = new File("${rootDir}/.sentry_token").text.trim()
buildConfigField 'String', 'SENTRY_TOKEN', '"' + token + '"'
} catch (FileNotFoundException ignored) {}
} else {
buildConfigField 'boolean', 'CRASH_REPORTING', 'false'
}
if (!isDebug) {
buildConfigField 'boolean', 'TELEMETRY', 'true'
} else {
buildConfigField 'boolean', 'TELEMETRY', 'false'
}
def buildDate = Config.generateBuildDate()
buildConfigField 'String', 'BUILD_DATE', '"' + buildDate + '"'
def variantName = variant.getName()
// -------------------------------------------------------------------------------------------------
// Adjust: Read token from local file if it exists (Only release builds)
// -------------------------------------------------------------------------------------------------
print("Adjust token: ")
if (!isDebug) {
try {
def token = new File("${rootDir}/.adjust_token").text.trim()
buildConfigField 'String', 'ADJUST_TOKEN', '"' + token + '"'
println "(Added from .adjust_token file)"
} catch (FileNotFoundException ignored) {
buildConfigField 'String', 'ADJUST_TOKEN', 'null'
println("X_X")
}
} else {
buildConfigField 'String', 'ADJUST_TOKEN', 'null'
println("--")
}
// -------------------------------------------------------------------------------------------------
// Leanplum: Read token from local file if it exists
// -------------------------------------------------------------------------------------------------
print("Leanplum token: ")
try {
def parts = new File("${rootDir}/.leanplum_token").text.trim().split(":")
def id = parts[0]
def key = parts[1]
buildConfigField 'String', 'LEANPLUM_ID', '"' + id + '"'
buildConfigField 'String', 'LEANPLUM_TOKEN', '"' + key + '"'
println "(Added from .leanplum_token file)"
} catch (FileNotFoundException ignored) {
buildConfigField 'String', 'LEANPLUM_ID', 'null'
buildConfigField 'String', 'LEANPLUM_TOKEN', 'null'
println("X_X")
}
}
androidExtensions {
experimental = true
}
dependencies {
implementation project(':architecture')
geckoNightlyImplementation Deps.mozilla_browser_engine_gecko_nightly
geckoBetaImplementation Deps.mozilla_browser_engine_gecko_beta
implementation Deps.kotlin_stdlib
implementation Deps.kotlin_coroutines
implementation Deps.androidx_appcompat
implementation Deps.androidx_constraintlayout
implementation Deps.androidx_coordinatorlayout
implementation Deps.rxAndroid
implementation Deps.rxKotlin
implementation Deps.rxBindings
implementation Deps.autodispose
implementation Deps.autodispose_android
implementation Deps.autodispose_android_aac
implementation Deps.anko_commons
implementation Deps.anko_sdk
implementation Deps.anko_constraintlayout
implementation Deps.sentry
implementation Deps.leanplum
implementation Deps.osslicenses_library
implementation Deps.mozilla_concept_engine
implementation Deps.mozilla_concept_push
implementation Deps.mozilla_concept_storage
implementation Deps.mozilla_concept_sync
implementation Deps.mozilla_concept_toolbar
implementation Deps.mozilla_browser_awesomebar
implementation Deps.mozilla_feature_downloads
implementation Deps.mozilla_browser_domains
implementation Deps.mozilla_browser_icons
implementation Deps.mozilla_browser_menu
implementation Deps.mozilla_browser_search
implementation Deps.mozilla_browser_session
implementation Deps.mozilla_browser_storage_sync
implementation Deps.mozilla_browser_toolbar
implementation Deps.mozilla_feature_accounts
implementation Deps.mozilla_feature_app_links
implementation Deps.mozilla_feature_awesomebar
implementation Deps.mozilla_feature_contextmenu
implementation Deps.mozilla_feature_customtabs
implementation Deps.mozilla_feature_downloads
implementation Deps.mozilla_feature_intent
implementation Deps.mozilla_feature_media
implementation Deps.mozilla_feature_prompts
implementation Deps.mozilla_feature_push
implementation Deps.mozilla_feature_pwa
implementation Deps.mozilla_feature_qr
implementation Deps.mozilla_feature_search
implementation Deps.mozilla_feature_session
implementation Deps.mozilla_feature_toolbar
implementation Deps.mozilla_feature_tabs
implementation Deps.mozilla_feature_findinpage
implementation Deps.mozilla_feature_site_permissions
implementation Deps.mozilla_feature_readerview
implementation Deps.mozilla_feature_tab_collections
implementation Deps.mozilla_feature_sendtab
implementation Deps.mozilla_service_firefox_accounts
implementation Deps.mozilla_service_fretboard
implementation Deps.mozilla_service_glean
implementation Deps.mozilla_service_experiments
implementation Deps.mozilla_support_ktx
implementation Deps.mozilla_support_rustlog
implementation Deps.mozilla_support_utils
implementation Deps.mozilla_ui_colors
implementation Deps.mozilla_ui_icons
implementation Deps.mozilla_ui_publicsuffixlist
implementation Deps.mozilla_lib_crash
implementation Deps.mozilla_lib_push_firebase
debugImplementation Deps.leakcanary
releaseImplementation Deps.leakcanary_noop
implementation Deps.mozilla_lib_fetch_httpurlconnection
implementation Deps.androidx_legacy
implementation Deps.androidx_paging
implementation Deps.androidx_preference
implementation Deps.androidx_fragment
implementation Deps.androidx_navigation_fragment
implementation Deps.androidx_navigation_ui
implementation Deps.androidx_recyclerview
implementation Deps.androidx_lifecycle_runtime
implementation Deps.androidx_lifecycle_viewmodel
implementation Deps.androidx_core
implementation Deps.androidx_core_ktx
implementation Deps.androidx_transition
implementation Deps.androidx_work_ktx
implementation Deps.google_material
implementation Deps.autodispose
implementation Deps.adjust
implementation Deps.installreferrer // Required by Adjust
implementation Deps.google_ads_id // Required for the Google Advertising ID
androidTestImplementation Deps.uiautomator
// Removed pending AndroidX fixes
// androidTestImplementation "tools.fastlane:screengrab:1.2.0"
// androidTestImplementation "br.com.concretesolutions:kappuccino:1.2.1"
androidTestImplementation Deps.espresso_core, {
exclude group: 'com.android.support', module: 'support-annotations'
}
androidTestImplementation(Deps.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'
}
androidTestImplementation Deps.androidx_test_core
androidTestImplementation Deps.espresso_idling_resources
androidTestImplementation Deps.tools_test_runner
androidTestImplementation Deps.tools_test_rules
androidTestUtil Deps.orchestrator
androidTestImplementation Deps.espresso_core, {
exclude group: 'com.android.support', module: 'support-annotations'
}
androidTestImplementation Deps.mockwebserver
testImplementation Deps.mozilla_support_test
testImplementation Deps.androidx_junit
testImplementation (Deps.robolectric) {
exclude group: 'org.apache.maven'
}
testImplementation 'org.apache.maven:maven-ant-tasks:2.1.3'
// For production builds, the native code for all `org.mozilla.appservices`
// dependencies gets compiled together into a single "megazord" build, and
// different megazords are published for different subsets of features. Ref
// https://mozilla.github.io/application-services/docs/applications/consuming-megazord-libraries.html
// We want to use the one that's specifically designed for Fenix.
implementation Deps.fenix_megazord
testImplementation Deps.fenix_megazord_forUnitTests
implementation Deps.mozilla_support_rusthttp
modules {
module('org.mozilla.appservices:full-megazord') {
replacedBy('org.mozilla.appservices:fenix-megazord', 'prefer the fenix megazord, to reduce final application size')
}
module('org.mozilla.appservices:fenix-megazord') {
replacedBy('org.mozilla.appservices:fenix-megazord-forUnitTests', 'prefer the forUnitTests variant if present')
}
}
testImplementation Deps.mockito_core
androidTestImplementation Deps.mockito_android
testImplementation Deps.mockk
testImplementation Deps.assertk
debugImplementation Deps.flipper
debugImplementation Deps.soLoader
releaseImplementation Deps.flipper_noop
}
if (project.hasProperty("raptor")) {
android.defaultConfig.manifestPlaceholders.isRaptorEnabled = "true"
}
if (project.hasProperty("coverage")) {
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
}
android.applicationVariants.all { variant ->
task "jacoco${variant.name.capitalize()}TestReport"(type: JacocoReport, dependsOn: "test${variant.name.capitalize()}UnitTest") {
reports {
xml.enabled = true
html.enabled = true
}
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*',
'**/*Test*.*', 'android/**/*.*', '**/*$[0-9].*']
def kotlinDebugTree = fileTree(dir: "$project.buildDir/tmp/kotlin-classes/${variant.name}", excludes: fileFilter)
def javaDebugTree = fileTree(dir: "$project.buildDir/intermediates/classes/${variant.flavorName}/${variant.buildType.name}",
excludes: fileFilter)
def mainSrc = "$project.projectDir/src/main/java"
sourceDirectories = files([mainSrc])
classDirectories = files([kotlinDebugTree, javaDebugTree])
executionData = fileTree(dir: project.buildDir, includes: [
"jacoco/test${variant.name.capitalize()}UnitTest.exec", 'outputs/code-coverage/connected/*coverage.ec'
])
}
}
android {
buildTypes {
debug {
testCoverageEnabled true
}
}
}
}
// -------------------------------------------------------------------------------------------------
// Task for printing APK information for the requested variant
// Usage: "./gradlew printVariant -PvariantBuildType=nightly -PvariantEngine=geckoNightly"
// -------------------------------------------------------------------------------------------------
task printVariant {
doLast {
def rawVariant = android.applicationVariants.find {
it.buildType.name == variantBuildType &&
it.productFlavors.find { it.dimension == 'engine' }.name == variantEngine
}
println 'variant: ' + groovy.json.JsonOutput.toJson([
name: rawVariant.name,
apks: rawVariant.variantData.outputScope.apkDatas.collect { [
abi: it.filters.find { it.filterType == 'ABI' }.identifier,
fileName: it.outputFileName,
]}
])
}
}
def glean_android_components_tag = (
Versions.mozilla_android_components.endsWith('-SNAPSHOT') ?
'master' :
'v' + Versions.mozilla_android_components
)
apply from: 'https://github.com/mozilla-mobile/android-components/raw/' + glean_android_components_tag + '/components/service/glean/scripts/sdk_generator.gradle'
// For production builds, the native code for all `org.mozilla.appservices` dependencies gets compiled together
// into a single "megazord" build, and different megazords are published for different subsets of features.
// Ref https://mozilla.github.io/application-services/docs/applications/consuming-megazord-libraries.html
// Substitute all appservices dependencies with an appropriate megazord.
afterEvaluate {
// Format test output. Ported from AC #2401
tasks.matching {it instanceof Test}.all {
systemProperty "robolectric.logging", "stdout"
systemProperty "logging.test-mode", "true"
testLogging.events = []
def out = services.get(StyledTextOutputFactory).create("tests")
beforeSuite { descriptor ->
if (descriptor.getClassName() != null) {
out.style(Style.Header).println("\nSUITE: " + descriptor.getClassName())
}
}
beforeTest { descriptor ->
out.style(Style.Description).println(" TEST: " + descriptor.getName())
}
onOutput { descriptor, event ->
logger.lifecycle(" " + event.message.trim())
}
afterTest { descriptor, result ->
switch (result.getResultType()) {
case ResultType.SUCCESS:
out.style(Style.Success).println(" SUCCESS")
break
case ResultType.FAILURE:
out.style(Style.Failure).println(" FAILURE")
logger.lifecycle("", result.getException())
break
case ResultType.SKIPPED:
out.style(Style.Info).println(" SKIPPED")
break
}
logger.lifecycle("")
}
}
}
if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopsrcdir')) {
if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopobjdir')) {
ext.topobjdir = gradle."localProperties.dependencySubstitutions.geckoviewTopobjdir"
}
ext.topsrcdir = gradle."localProperties.dependencySubstitutions.geckoviewTopsrcdir"
apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
}