build.gradle 26.8 KB
Newer Older
1
2
3
4
plugins {
    id "com.jetbrains.python.envs" version "0.0.26"
}

Jeff Boek's avatar
Jeff Boek committed
5
6
7
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
Colin Lee's avatar
Colin Lee committed
8
apply plugin: 'jacoco'
9
apply plugin: 'androidx.navigation.safeargs.kotlin'
10
apply plugin: 'com.google.android.gms.oss-licenses-plugin'
Jeff Boek's avatar
Jeff Boek committed
11

Tiger Oakes's avatar
Tiger Oakes committed
12
13

import com.android.build.OutputFile
Tiger Oakes's avatar
Tiger Oakes committed
14
import groovy.json.JsonOutput
15
16
import org.gradle.internal.logging.text.StyledTextOutput.Style
import org.gradle.internal.logging.text.StyledTextOutputFactory
17
import org.mozilla.fenix.gradle.tasks.LintUnitTestRunner
Tiger Oakes's avatar
Tiger Oakes committed
18

19
import static org.gradle.api.tasks.testing.TestResult.ResultType
20

Jeff Boek's avatar
Jeff Boek committed
21
android {
22
    compileSdkVersion Config.compileSdkVersion
Jeff Boek's avatar
Jeff Boek committed
23
    defaultConfig {
24
        applicationId "org.torproject"
25
26
        minSdkVersion Config.minSdkVersion
        targetSdkVersion Config.targetSdkVersion
27
28
        versionCode 1
        versionName Config.generateDebugVersionName()
29
        vectorDrawables.useSupportLibrary = true
Kevin Brosnan's avatar
Kevin Brosnan committed
30
31
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        testInstrumentationRunnerArguments clearPackageData: 'true'
32
33
        resValue "bool", "IS_DEBUG", "false"
        buildConfigField "boolean", "USE_RELEASE_VERSIONING", "false"
34
        buildConfigField "String", "AMO_COLLECTION", "\"83a9cccfe6e24a34bd7b155ff9ee32\""
35
        def deepLinkSchemeValue = "torbrowser-dev"
36
        buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\""
37
        manifestPlaceholders = [
38
                "deepLinkScheme": deepLinkSchemeValue
39
        ]
40
        buildConfigField "boolean", "DATA_COLLECTION_DISABLED", "true"
41
42
43
44
45
    }

    def releaseTemplate = {
        shrinkResources true
        minifyEnabled true
46
        proguardFiles 'proguard-android-optimize-3.5.0-modified.txt', 'proguard-rules.pro'
47
        matchingFallbacks = ['release'] // Use on the "release" build type in dependencies (AARs)
48
49
50
51

        if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) {
            signingConfig signingConfigs.debug
        }
52
53
54
55

        if (gradle.hasProperty("localProperties.debuggable")) {
            debuggable true
        }
Jeff Boek's avatar
Jeff Boek committed
56
    }
57

Jeff Boek's avatar
Jeff Boek committed
58
    buildTypes {
59
        debug {
60
61
            shrinkResources false
            minifyEnabled false
62
            applicationIdSuffix ".torbrowser_debug"
63
            resValue "bool", "IS_DEBUG", "true"
64
            pseudoLocalesEnabled true
65
        }
66
        nightly releaseTemplate >> {
67
            applicationIdSuffix ".torbrowser_nightly"
68
            buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
69
            def deepLinkSchemeValue = "torbrowser-nightly"
70
71
            buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\""
            manifestPlaceholders = ["deepLinkScheme": deepLinkSchemeValue]
72
        }
73
        beta releaseTemplate >> {
74
            buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
75
            applicationIdSuffix ".torbrowser_alpha"
76
            def deepLinkSchemeValue = "torbrowser-alpha"
77
            buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\""
78
            manifestPlaceholders = [
79
                    // This release type is meant to replace Firefox (Beta channel) and therefore needs to inherit
Jeff Boek's avatar
Jeff Boek committed
80
81
82
83
84
85
                    // 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
86
                    "sharedUserId": "org.torproject.torbrowser_alpha.sharedID",
87
                    "deepLinkScheme": deepLinkSchemeValue
88
            ]
89
        }
90
        release releaseTemplate >> {
91
            buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
92
            applicationIdSuffix ".torbrowser"
93
            def deepLinkSchemeValue = "torbrowser"
94
            buildConfigField "String", "DEEP_LINK_SCHEME", "\"$deepLinkSchemeValue\""
95
96
97
98
99
100
101
102
            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
103
                    "sharedUserId": "org.torproject.torbrowser.sharedID",
104
                    "deepLinkScheme": deepLinkSchemeValue
105
106
            ]
        }
107
108
    }

109
110
111
112
113
114
    aaptOptions {
        // All JavaScript code used internally by GeckoView is packaged in a
        // file called omni.ja. If this file is compressed in the APK,
        // GeckoView must uncompress it before it can do anything else which
        // causes a significant delay on startup.
        noCompress 'ja'
115
116
117
118

        // manifest.template.json is converted to manifest.json at build time.
        // No need to package the template in the APK.
        ignoreAssetsPattern "manifest.template.json"
119
120
    }

Kevin Brosnan's avatar
Kevin Brosnan committed
121
122
    testOptions {
        execution 'ANDROIDX_TEST_ORCHESTRATOR'
123
        unitTests.includeAndroidResources = true
124
        animationsDisabled = true
Kevin Brosnan's avatar
Kevin Brosnan committed
125
126
    }

127
    flavorDimensions "engine"
128

Isabel Rios's avatar
Isabel Rios committed
129
130
    sourceSets {
        androidTest {
Jeff Boek's avatar
Jeff Boek committed
131
            resources.srcDirs += ['src/androidTest/resources']
Isabel Rios's avatar
Isabel Rios committed
132
        }
133
134
        debug {
            java.srcDirs = ['src/geckoNightly/java']
135
        }
136
137
        nightly {
            java.srcDirs = ['src/geckoNightly/java']
138
        }
139
140
        beta {
            java.srcDirs = ['src/migration/java', 'src/geckoBeta/java']
141
142
            manifest.srcFile "src/migration/AndroidManifest.xml"
        }
143
144
145
        release {
            java.srcDirs = ['src/migration/java', 'src/geckoRelease/java']
            manifest.srcFile "src/migration/AndroidManifest.xml"
146
        }
147
148
149
150
151
152
153
154
155
    }

    splits {
        abi {
            enable true

            reset()

            include "x86", "armeabi-v7a", "arm64-v8a", "x86_64"
156
        }
157
158
    }

159
160
161
162
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
163
164
165
166

    lintOptions {
        lintConfig file("lint.xml")
    }
167
168
169
170

    packagingOptions {
        exclude 'META-INF/atomicfu.kotlin_module'
    }
171
172
173
174

    testOptions {
        unitTests.returnDefaultValues = true
    }
175
176
}

177
android.applicationVariants.all { variant ->
178
179
180
181
182

// -------------------------------------------------------------------------------------------------
// Set up kotlin-allopen plugin for writing tests
// -------------------------------------------------------------------------------------------------

183
    boolean hasTest = gradle.startParameter.taskNames.find { it.contains("test") || it.contains("Test") } != null
184
185
186
    if (hasTest) {
        apply plugin: 'kotlin-allopen'
        allOpen {
187
            annotation("org.mozilla.fenix.utils.OpenClass")
188
189
190
        }
    }

191
192
193
194
// -------------------------------------------------------------------------------------------------
// Generate version codes for builds
// -------------------------------------------------------------------------------------------------

195
    def isDebug = variant.buildType.resValues['IS_DEBUG']?.value ?: false
196
197
    def isDataCollectionDisabled = variant.buildType.buildConfigFields['DATA_COLLECTION_DISABLED']?.value ?: true
    def isDebugOrDCD = isDebug || isDataCollectionDisabled
198
    def useReleaseVersioning = variant.buildType.buildConfigFields['USE_RELEASE_VERSIONING']?.value ?: false
199
200
    def versionName = Config.releaseVersionName(project)

201
202
203
204
205
    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)
206
    println("Telemetry enabled: " + !isDebugOrDCD)
207

208
    if (useReleaseVersioning) {
209
210
211
212
        // 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.

213
214
        variant.outputs.each { output ->
            def abi = output.getFilter(OutputFile.ABI)
215
216
217
            // We use the same version code generator, that we inherited from Fennec, across all channels - even on
            // channels that never shipped a Fennec build.
            def versionCodeOverride = Config.generateFennecVersionCode(abi)
218
219

            println("versionCode for $abi = $versionCodeOverride")
220
221
222

            output.versionNameOverride = versionName
            output.versionCodeOverride = versionCodeOverride
223
        }
224
225
    }

226
227
228
229
// -------------------------------------------------------------------------------------------------
// BuildConfig: Set variables for Sentry, Crash Reporting, and Telemetry
// -------------------------------------------------------------------------------------------------

230
    buildConfigField 'String', 'SENTRY_TOKEN', 'null'
231
    if (!isDebugOrDCD) {
232
        buildConfigField 'boolean', 'CRASH_REPORTING', 'true'
233
234
235
236
237
        // 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) {}
238
239
240
241
    } else {
        buildConfigField 'boolean', 'CRASH_REPORTING', 'false'
    }

242
    if (!isDebugOrDCD) {
243
244
245
246
247
248
        buildConfigField 'boolean', 'TELEMETRY', 'true'
    } else {
        buildConfigField 'boolean', 'TELEMETRY', 'false'
    }

    def buildDate = Config.generateBuildDate()
249
250
251
252
253
254
255
    // Setting buildDate with every build changes the generated BuildConfig, which slows down the
    // build. Only do this for non-debug builds, to speed-up builds produced during local development.
    if (isDebug) {
        buildConfigField 'String', 'BUILD_DATE', '"debug build"'
    } else {
        buildConfigField 'String', 'BUILD_DATE', '"' + buildDate + '"'
    }
Jeff Boek's avatar
Jeff Boek committed
256

257
// -------------------------------------------------------------------------------------------------
Jeff Boek's avatar
Jeff Boek committed
258
// Adjust: Read token from local file if it exists (Only release builds)
259
260
261
262
// -------------------------------------------------------------------------------------------------

    print("Adjust token: ")

263
    if (!isDebugOrDCD) {
264
265
266
267
268
269
270
271
272
273
274
275
        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("--")
    }
Jeff Boek's avatar
Jeff Boek committed
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

// -------------------------------------------------------------------------------------------------
// 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")
    }
295

296
297
298
299
300
301
302
303
304
305
306
307
308
309
// -------------------------------------------------------------------------------------------------
// MLS: Read token from local file if it exists
// -------------------------------------------------------------------------------------------------

    print("MLS token: ")

    try {
        def token = new File("${rootDir}/.mls_token").text.trim()
        buildConfigField 'String', 'MLS_TOKEN', '"' + token + '"'
        println "(Added from .mls_token file)"
    } catch (FileNotFoundException ignored) {
        buildConfigField 'String', 'MLS_TOKEN', '""'
        println("X_X")
    }
Jeff Boek's avatar
Jeff Boek committed
310
311
}

312
313
314
315
androidExtensions {
    experimental = true
}

316
317
318
319
320
// Generate Kotlin code and markdown docs for the Fenix Glean metrics.
ext.gleanGenerateMarkdownDocs = true
ext.gleanDocsDirectory = "$rootDir/docs"
apply plugin: "org.mozilla.telemetry.glean-gradle-plugin"

Jeff Boek's avatar
Jeff Boek committed
321
dependencies {
322
323
324
325
326
    debugImplementation Deps.mozilla_browser_engine_gecko_nightly

    nightlyImplementation Deps.mozilla_browser_engine_gecko_nightly
    betaImplementation Deps.mozilla_browser_engine_gecko_beta
    releaseImplementation Deps.mozilla_browser_engine_gecko_release
327

328
    implementation Deps.kotlin_stdlib
329
    implementation Deps.kotlin_coroutines
330
    implementation Deps.kotlin_coroutines_android
331
    testImplementation Deps.kotlin_coroutines_test
332
333
    implementation Deps.androidx_appcompat
    implementation Deps.androidx_constraintlayout
Emily Kager's avatar
Emily Kager committed
334
    implementation Deps.androidx_coordinatorlayout
335

336
    implementation Deps.sentry
Jeff Boek's avatar
Jeff Boek committed
337

338
339
340
    implementation Deps.leanplum_core
    implementation Deps.leanplum_fcm

341
    implementation Deps.mozilla_concept_engine
Tiger Oakes's avatar
Tiger Oakes committed
342
    implementation Deps.mozilla_concept_menu
343
    implementation Deps.mozilla_concept_push
344
    implementation Deps.mozilla_concept_storage
345
    implementation Deps.mozilla_concept_sync
346
    implementation Deps.mozilla_concept_toolbar
347
    implementation Deps.mozilla_concept_tabstray
348

Jeff Boek's avatar
Jeff Boek committed
349
    implementation Deps.mozilla_browser_awesomebar
350
    implementation Deps.mozilla_feature_downloads
351
    implementation Deps.mozilla_browser_domains
352
    implementation Deps.mozilla_browser_icons
353
    implementation Deps.mozilla_browser_menu
354
    implementation Deps.mozilla_browser_menu2
355
    implementation Deps.mozilla_browser_search
356
    implementation Deps.mozilla_browser_session
357
    implementation Deps.mozilla_browser_state
358
    implementation Deps.mozilla_browser_storage_sync
359
360
    implementation Deps.mozilla_browser_tabstray
    implementation Deps.mozilla_browser_thumbnails
Jeff Boek's avatar
Jeff Boek committed
361
362
    implementation Deps.mozilla_browser_toolbar

Gabriel Luong's avatar
Gabriel Luong committed
363
364
365
    implementation Deps.mozilla_support_extensions
    implementation Deps.mozilla_feature_addons

366
    implementation Deps.mozilla_feature_accounts
367
    implementation Deps.mozilla_feature_app_links
368
    implementation Deps.mozilla_feature_awesomebar
369
    implementation Deps.mozilla_feature_contextmenu
370
    implementation Deps.mozilla_feature_customtabs
371
    implementation Deps.mozilla_feature_downloads
372
    implementation Deps.mozilla_feature_intent
373
    implementation Deps.mozilla_feature_media
374
    implementation Deps.mozilla_feature_prompts
375
    implementation Deps.mozilla_feature_push
376
    implementation Deps.mozilla_feature_privatemode
377
    implementation Deps.mozilla_feature_pwa
Colin Lee's avatar
Colin Lee committed
378
    implementation Deps.mozilla_feature_qr
379
    implementation Deps.mozilla_feature_search
380
    implementation Deps.mozilla_feature_session
381
    implementation Deps.mozilla_feature_syncedtabs
382
    implementation Deps.mozilla_feature_toolbar
383
    implementation Deps.mozilla_feature_tabs
384
    implementation Deps.mozilla_feature_findinpage
385
    implementation Deps.mozilla_feature_logins
386
    implementation Deps.mozilla_feature_site_permissions
387
    implementation Deps.mozilla_feature_readerview
388
    implementation Deps.mozilla_feature_tab_collections
ekager's avatar
ekager committed
389
    implementation Deps.mozilla_feature_recentlyclosed
390
    implementation Deps.mozilla_feature_top_sites
Mihai Branescu's avatar
Mihai Branescu committed
391
    implementation Deps.mozilla_feature_share
392
    implementation Deps.mozilla_feature_accounts_push
393
    implementation Deps.mozilla_feature_webcompat
394
    implementation Deps.mozilla_feature_webnotifications
395
    implementation Deps.mozilla_feature_webcompat_reporter
396

Tiger Oakes's avatar
Tiger Oakes committed
397
    implementation Deps.mozilla_service_digitalassetlinks
398
    implementation Deps.mozilla_service_experiments
ekager's avatar
ekager committed
399
    implementation Deps.mozilla_service_sync_logins
400
    implementation Deps.mozilla_service_firefox_accounts
401
    implementation Deps.mozilla_service_glean
402
403
    implementation Deps.mozilla_service_location

404
    implementation Deps.mozilla_support_base
405
    implementation Deps.mozilla_support_images
406
    implementation Deps.mozilla_support_ktx
407
    implementation Deps.mozilla_support_rustlog
408
    implementation Deps.mozilla_support_utils
409
    implementation Deps.mozilla_support_locale
410

411
    implementation Deps.mozilla_support_migration
412

413
414
    implementation Deps.mozilla_ui_colors
    implementation Deps.mozilla_ui_icons
415
    implementation Deps.mozilla_lib_publicsuffixlist
416
    implementation Deps.mozilla_ui_widgets
417

418
    implementation Deps.mozilla_lib_crash
419
    implementation Deps.mozilla_lib_push_firebase
420
    implementation Deps.mozilla_lib_dataprotect
421
    debugImplementation Deps.leakcanary
422

423
    implementation Deps.androidx_legacy
424
    implementation Deps.androidx_biometric
425
    implementation Deps.androidx_paging
426
    implementation Deps.androidx_preference
427
    implementation Deps.androidx_fragment
ekager's avatar
ekager committed
428
429
    implementation Deps.androidx_navigation_fragment
    implementation Deps.androidx_navigation_ui
ekager's avatar
ekager committed
430
    implementation Deps.androidx_recyclerview
Tiger Oakes's avatar
Tiger Oakes committed
431
    implementation Deps.androidx_lifecycle_livedata
432
433
    implementation Deps.androidx_lifecycle_runtime
    implementation Deps.androidx_lifecycle_viewmodel
434
    implementation Deps.androidx_core
435
    implementation Deps.androidx_core_ktx
436
    implementation Deps.androidx_transition
437
    implementation Deps.androidx_work_ktx
438
    implementation Deps.google_material
Colin Lee's avatar
Colin Lee committed
439

440
441
    implementation Deps.lottie

442
443
444
    implementation Deps.adjust
    implementation Deps.installreferrer // Required by Adjust

445
446
    implementation Deps.google_ads_id // Required for the Google Advertising ID

447
448
    implementation Deps.google_play_store // Required for in-app reviews

Kevin Brosnan's avatar
Kevin Brosnan committed
449
    androidTestImplementation Deps.uiautomator
450
// Removed pending AndroidX fixes
451
    androidTestImplementation "tools.fastlane:screengrab:2.0.0"
452
//    androidTestImplementation "br.com.concretesolutions:kappuccino:1.2.1"
453

Kevin Brosnan's avatar
Kevin Brosnan committed
454
455
456
457
458
459
460
461
462
463
464
465
466
    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'
    }

467
    androidTestImplementation Deps.androidx_test_core
Kevin Brosnan's avatar
Kevin Brosnan committed
468
    androidTestImplementation Deps.espresso_idling_resources
469
    androidTestImplementation Deps.espresso_intents
470

471
    androidTestImplementation Deps.tools_test_runner
Kevin Brosnan's avatar
Kevin Brosnan committed
472
473
474
475
476
    androidTestImplementation Deps.tools_test_rules
    androidTestUtil Deps.orchestrator
    androidTestImplementation Deps.espresso_core, {
        exclude group: 'com.android.support', module: 'support-annotations'
    }
477

478
479
    androidTestImplementation Deps.androidx_junit
    androidTestImplementation Deps.androidx_work_testing
480
    androidTestImplementation Deps.mockwebserver
Denys M's avatar
Denys M committed
481
482
    testImplementation Deps.mozilla_support_test
    testImplementation Deps.androidx_junit
483
    testImplementation Deps.androidx_work_testing
484
485
486
487
488
    testImplementation (Deps.robolectric) {
        exclude group: 'org.apache.maven'
    }

    testImplementation 'org.apache.maven:maven-ant-tasks:2.1.3'
489
    implementation Deps.mozilla_support_rusthttp
490
491

    testImplementation Deps.mockk
492
493
494

    // For the initial release of Glean 19, we require consumer applications to
    // depend on a separate library for unit tests. This will be removed in future releases.
495
    testImplementation "org.mozilla.telemetry:glean-forUnitTests:${project.ext.glean_version}"
496
497

    lintChecks project(":mozilla-lint-rules")
Jeff Boek's avatar
Jeff Boek committed
498
}
499

Colin Lee's avatar
Colin Lee committed
500
if (project.hasProperty("coverage")) {
Tiger Oakes's avatar
Tiger Oakes committed
501
    tasks.withType(Test).configureEach {
Colin Lee's avatar
Colin Lee committed
502
503
504
505
        jacoco.includeNoLocationClasses = true
    }

    android.applicationVariants.all { variant ->
506
507
508
        tasks.register("jacoco${variant.name.capitalize()}TestReport", JacocoReport) {
            dependsOn "test${variant.name.capitalize()}UnitTest"

Colin Lee's avatar
Colin Lee committed
509
510
511
512
513
514
515
516
517
518
519
520
            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"

521
522
523
524
525
526
            sourceDirectories.setFrom(files([mainSrc]))
            classDirectories.setFrom(files([kotlinDebugTree, javaDebugTree]))
            executionData.setFrom(fileTree(dir: project.buildDir, includes: [
                "jacoco/test${variant.name.capitalize()}UnitTest.exec",
                'outputs/code-coverage/connected/*coverage.ec'
            ]))
Colin Lee's avatar
Colin Lee committed
527
528
529
530
531
532
533
534
535
536
537
538
        }
    }

    android {
        buildTypes {
            debug {
                testCoverageEnabled true
            }
        }
    }
}

539
// -------------------------------------------------------------------------------------------------
540
// Task for printing APK information for the requested variant
541
// Usage: "./gradlew printVariants
542
// -------------------------------------------------------------------------------------------------
Tiger Oakes's avatar
Tiger Oakes committed
543
tasks.register('printVariants') {
544
    doLast {
545
        def variants = android.applicationVariants.collect {[
Jeff Boek's avatar
Jeff Boek committed
546
547
548
549
550
551
                apks: it.variantData.outputScope.apkDatas.collect {[
                        abi: it.filters.find { it.filterType == 'ABI' }.identifier,
                        fileName: it.outputFileName,
                ]},
                build_type: it.buildType.name,
                name: it.name,
552
        ]}
Johan Lorenzo's avatar
Johan Lorenzo committed
553
554
555
556
        // AndroidTest is a special case not included above
        variants.add([
            apks: [[
                abi: 'noarch',
557
                fileName: 'app-debug-androidTest.apk',
Johan Lorenzo's avatar
Johan Lorenzo committed
558
559
560
561
            ]],
            build_type: 'androidTest',
            name: 'androidTest',
        ])
Tiger Oakes's avatar
Tiger Oakes committed
562
        println 'variants: ' + JsonOutput.toJson(variants)
563
564
565
    }
}

566
task buildTranslationArray {
Tiger Oakes's avatar
Tiger Oakes committed
567
568
    // This isn't running as a task, instead the array is build when the gradle file is parsed.
    // https://github.com/mozilla-mobile/fenix/issues/14175
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
    def foundLocales = new StringBuilder()
    foundLocales.append("new String[]{")

    fileTree("src/main/res").visit { FileVisitDetails details ->
        if(details.file.path.endsWith("/strings.xml")){
            def languageCode = details.file.parent.tokenize('/').last().replaceAll('values-','').replaceAll('-r','-')
            languageCode = (languageCode == "values") ? "en-US" : languageCode
            foundLocales.append("\"").append(languageCode).append("\"").append(",")
        }
    }

    foundLocales.append("}")
    def foundLocalesString = foundLocales.toString().replaceAll(',}','}')
    android.defaultConfig.buildConfigField "String[]", "SUPPORTED_LOCALE_ARRAY", foundLocalesString
}

Tiger Oakes's avatar
Tiger Oakes committed
585
tasks.register('lintUnitTestRunner', LintUnitTestRunner)
586

587
afterEvaluate {
588
589

    // Format test output. Ported from AC #2401
Tiger Oakes's avatar
Tiger Oakes committed
590
    tasks.withType(Test).configureEach {
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
        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("")
        }
    }
630
}
631
632
633
634
635
636
637
638

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"
}
639
640
641
642
643

if (gradle.hasProperty('localProperties.autoPublish.android-components.dir')) {
    ext.acSrcDir = gradle."localProperties.autoPublish.android-components.dir"
    apply from: "../${acSrcDir}/substitute-local-ac.gradle"
}
644
645
646
647
648

if (gradle.hasProperty('localProperties.autoPublish.application-services.dir')) {
    ext.appServicesSrcDir = gradle."localProperties.autoPublish.application-services.dir"
    apply from: "../${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle"
}
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677

// Define a reusable task for updating the versions of our built-in web extensions. We automate this
// to make sure we never forget to update the version, either in local development or for releases.
// In both cases, we want to make sure the latest version of all extensions (including their latest
// changes) are installed on first start-up.
// We're using the A-C version here as we want to uplift all built-in extensions to A-C (Once that's
// done we can also remove the task below):
// https://github.com/mozilla-mobile/android-components/issues/7249
ext.updateExtensionVersion = { task, extDir ->
    configure(task) {
        from extDir
        include 'manifest.template.json'
        rename { 'manifest.json' }
        into extDir

        def values = ['version': AndroidComponents.VERSION + "." + new Date().format('MMddHHmmss')]
        inputs.properties(values)
        expand(values)
    }
}

tasks.register("updateAdsExtensionVersion", Copy) { task ->
    updateExtensionVersion(task, 'src/main/assets/extensions/ads')
}

tasks.register("updateCookiesExtensionVersion", Copy) { task ->
    updateExtensionVersion(task, 'src/main/assets/extensions/cookies')
}

Tiger Oakes's avatar
Tiger Oakes committed
678
679
preBuild.dependsOn "updateAdsExtensionVersion"
preBuild.dependsOn "updateCookiesExtensionVersion"