8000 Move the Android 12 download fix to remote config (#1857) · xpcom-bsd/Android-1@d78d3b8 · GitHub
[go: up one dir, main page]

Skip to content

Commit d78d3b8

Browse files
authored
Move the Android 12 download fix to remote config (duckduckgo#1857)
Task/Issue URL: https://app.asana.com/0/414730916066338/1201828857868229/f ### Description Enable download fix for Android 12 devices and move it to remote config ### Steps to test this PR _Test downloads on Android 12_ - [x] Fresh install from this branch - [x] Enable appTP - [x] Try do download a file from https://www.thinkbroadband.com/download (IPv4 best) - [x] Verify the download does not start and it will only if AppTP is disabled - [x] In `PrivacyConfigService` class, replace the `@GET` to be `https://jsonblob.com/api/jsonBlob/961379783971979264` it should have the fix `disabled` - [x] re-build and launch - [x] Try do download a file from https://www.thinkbroadband.com/download (IPv4 best) - [x] Verify the download does not start and it will only if AppTP is disabled - [x] In `PrivacyConfigService` class, replace the `@GET` to be `https://jsonblob.com/api/jsonBlob/965954020414078976` it should have the fix `enabled` - [x] re-build and launch - [x] Try do download a file from https://www.thinkbroadband.com/download (IPv4 best) - [x] Verify the download does start and succeed _Test downloads on API < Android 12_ - [x] repeat the tests above - [x] verify in all cases the download succeeds regardless of whether the configuration is enabled or disabled
1 parent 2d8288c commit d78d3b8

File tree

10 files changed

+160
-40
lines changed

10 files changed

+160
-40
lines changed

vpn-api/src/main/java/com/duckduckgo/mobile/android/vpn/feature/AppTpSetting.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ enum class AppTpSetting(override val value: String, override val defaultValue: B
2222
PrivateDnsSupport("privateDnsSupport"),
2323
NetworkSwitchHandling("networkSwitchSupport"),
2424
SetActiveNetworkDns("setActiveNetworkDns"),
25+
VpnDdgBrowserTraffic("vpnDdgBrowserTraffic"),
2526
AlwaysSetDNS("alwaysSetDNS"),
2627
}
2728

vpn-internal/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ dependencies {
3232
anvil project(path: ':anvil-compiler')
3333
implementation project(path: ':anvil-annotations')
3434

35+
implementation project(path: ':vpn')
3536
implementation project(path: ':vpn-store')
3637
implementation project(path: ':vpn-api')
3738
implementation project(path: ':di')

vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/transparency/TransparencyTrackerDetectorInterceptor.kt

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,18 @@
1616

1717
package com.duckduckgo.vpn.internal.feature.transparency
1818

19-
import android.os.Build
20-
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
2119
import com.duckduckgo.di.scopes.AppScope
22-
import com.duckduckgo.mobile.android.vpn.apps.VpnExclusionList
2320
import com.duckduckgo.mobile.android.vpn.processor.tcp.tracker.RequestTrackerType
2421
import com.duckduckgo.mobile.android.vpn.processor.tcp.tracker.VpnTrackerDetectorInterceptor
2522
import com.squareup.anvil.annotations.ContributesMultibinding
23+
import dagger.SingleInstanceIn
2624
import timber.log.Timber
2725
import java.util.concurrent.atomic.AtomicBoolean
2826
import javax.inject.Inject
29-
import dagger.SingleInstanceIn
3027

3128
@ContributesMultibinding(AppScope::class)
3229
@SingleInstanceIn(AppScope::class)
33-
class TransparencyTrackerDetectorInterceptor @Inject constructor(private val appBuildConfig: AppBuildConfig) : VpnTrackerDetectorInterceptor {
30+
class TransparencyTrackerDetectorInterceptor @Inject constructor() : VpnTrackerDetectorInterceptor {
3431

3532
private val enable = AtomicBoolean(false)
3633

@@ -41,10 +38,6 @@ class TransparencyTrackerDetectorInterceptor @Inject constructor(private val app
4138
packageId: String
4239
): RequestTrackerType? {
4340
return when {
44-
transparencyModeBugFixForAndroid12(packageId) -> {
45-
Timber.v("Transparency mode for Android 12 and DDG: Not Tracker returned for $packageId / $hostname")
46-
RequestTrackerType.NotTracker(hostname)
47-
}
4841
enable.get() -> {
4942
Timber.v("Transparency mode: Not Tracker returned for $packageId / $hostname")
5043
RequestTrackerType.NotTracker(hostname)
@@ -55,10 +48,4 @@ class TransparencyTrackerDetectorInterceptor @Inject constructor(private val app
5548
}
5649
}
5750
}
58-
59-
// https://issuetracker.google.com/issues/217570500
60-
// https://app.asana.com/0/1174433894299346/1201657419006650
61-
private fun transparencyModeBugFixForAndroid12(packageId: String): Boolean {
62-
return appBuildConfig.sdkInt >= Build.VERSION_CODES.S && VpnExclusionList.isDdgApp(packageId)
63-
}
6451
}

vpn-internal/src/test/java/com/duckduckgo/vpn/internal/feature/transparency/TransparencyTrackerDetectorInterceptorTest.kt

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,20 @@
1616

1717
package com.duckduckgo.vpn.internal.feature.transparency
1818

19-
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
2019
import com.duckduckgo.mobile.android.vpn.processor.tcp.tracker.RequestTrackerType
2120
import org.junit.Assert.*
2221
import org.junit.Before
2322
import org.junit.Test
2423
import org.mockito.MockitoAnnotations
25-
import org.mockito.kotlin.mock
26-
import org.mockito.kotlin.whenever
2724

2825
class TransparencyTrackerDetectorInterceptorTest {
2926

30-
private val mockAppBuildConfig: AppBuildConfig = mock()
31-
3227
private lateinit var testee: TransparencyTrackerDetectorInterceptor
3328

3429
@Before
3530
fun before() {
3631
MockitoAnnotations.openMocks(this)
37-
testee = TransparencyTrackerDetectorInterceptor(mockAppBuildConfig)
32+
testee = TransparencyTrackerDetectorInterceptor()
3833
}
3934

4035
@Test
@@ -51,26 +46,9 @@ class TransparencyTrackerDetectorInterceptorTest {
5146
assertNull(trackerType)
5247
}
5348

54-
@Test
55-
fun returnNotTrackersNullWhenDDGAppAndAndroid12() {
56-
whenever(mockAppBuildConfig.sdkInt).thenReturn(31)
57-
58-
val trackerType = testee.interceptTrackerRequest(HOSTNAME, DDG_PACKAGE_ID)
59-
assertEquals(trackerType, RequestTrackerType.NotTracker(HOSTNAME))
60-
}
61-
62-
@Test
63-
fun returnNullWhenDDGAppAndAndroid11() {
64-
whenever(mockAppBuildConfig.sdkInt).thenReturn(30)
65-
66-
val trackerType = testee.interceptTrackerRequest(HOSTNAME, DDG_PACKAGE_ID)
67-
assertNull(trackerType)
68-
}
69-
7049
companion object {
7150
private const val HOSTNAME = "hostname"
7251
private const val SOME_PACKAGE_ID = "some.package.name"
73-
private const val DDG_PACKAGE_ID = "com.duckduckgo.mobile"
7452
}
7553

7654
}

vpn/src/main/java/com/duckduckgo/mobile/android/vpn/apps/TrackingProtectionAppsRepository.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ import android.content.pm.PackageManager
2121
import android.os.Build
2222
import com.duckduckgo.app.global.DispatcherProvider
2323
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
24-
import com.duckduckgo.appbuildconfig.api.BuildFlavor.INTERNAL
2524
import com.duckduckgo.di.scopes.AppScope
25+
import com.duckduckgo.mobile.android.vpn.feature.AppTpFeatureConfig
26+
import com.duckduckgo.mobile.android.vpn.feature.AppTpSetting
2627
import com.duckduckgo.mobile.android.vpn.trackers.AppTrackerExcludedPackage
2728
import com.duckduckgo.mobile.android.vpn.trackers.AppTrackerManualExcludedApp
2829
import com.duckduckgo.mobile.android.vpn.trackers.AppTrackerRepository
@@ -59,6 +60,7 @@ class RealTrackingProtectionAppsRepository @Inject constructor(
5960
private val packageManager: PackageManager,
6061
private val appTrackerRepository: AppTrackerRepository,
6162
private val appBuildConfig: AppBuildConfig,
63+
private val appTpFeatureConfig: AppTpFeatureConfig,
6264
private val dispatcherProvider: DispatcherProvider
6365
) : TrackingProtectionAppsRepository {
6466

@@ -135,7 +137,9 @@ class RealTrackingProtectionAppsRepository @Inject constructor(
135137
// https://issuetracker.google.com/issues/217570500
136138
// https://app.asana.com/0/1174433894299346/1201657419006650
137139
private fun transparencyModeBugFixForAndroid12(appInfo: ApplicationInfo): Boolean {
138-
return appBuildConfig.sdkInt >= Build.VERSION_CODES.S && VpnExclusionList.isDdgApp(appInfo.packageName) && appBuildConfig.flavor == INTERNAL
140+
return appBuildConfig.sdkInt >= Build.VERSION_CODES.S &&
141+
VpnExclusionList.isDdgApp(appInfo.packageName) &&
142+
appTpFeatureConfig.isEnabled(AppTpSetting.VpnDdgBrowserTraffic)
139143
}
140144

141145
private fun isManuallyExcluded(
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2021 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.mobile.android.vpn.bug
18+
19+
import com.duckduckgo.di.scopes.AppScope
20+
import com.duckduckgo.mobile.android.vpn.apps.VpnExclusionList
21+
import com.duckduckgo.mobile.android.vpn.processor.tcp.tracker.RequestTrackerType
22+
import com.duckduckgo.mobile.android.vpn.processor.tcp.tracker.VpnTrackerDetectorInterceptor
23+
import com.squareup.anvil.annotations.ContributesMultibinding
24+
import dagger.SingleInstanceIn
25+
import timber.log.Timber
26+
import javax.inject.Inject
27+
28+
@ContributesMultibinding(AppScope::class)
29+
@SingleInstanceIn(AppScope::class)
30+
class BrowserTrafficTransparencyInterceptor @Inject constructor() : VpnTrackerDetectorInterceptor {
31+
32+
override fun interceptTrackerRequest(
33+
hostname: String,
34+
packageId: String
35+
): RequestTrackerType? {
36+
return when {
37+
// we should never really block anything in our app, even if/when we pass its traffic through the VPN
38+
VpnExclusionList.isDdgApp(packageId) -> {
39+
Timber.v("Transparency mode for DDG app: Not Tracker returned for $packageId / $hostname")
40+
RequestTrackerType.NotTracker(hostname)
41+
}
42+
else -> {
43+
Timber.v("Not intercepting for $packageId / $hostname")
44+
null
45+
}
46+
}
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2022 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.mobile.android.vpn.feature.settings
18+
19+
import com.duckduckgo.di.scopes.AppScope
20+
import com.duckduckgo.mobile.android.vpn.feature.*
21+
import com.squareup.anvil.annotations.ContributesMultibinding
22+
import com.squareup.moshi.Moshi
23+
import timber.log.Timber
24+
import javax.inject.Inject
25+
26+
@ContributesMultibinding(
27+
scope = AppScope::class,
28+
boundType = AppTpSettingPlugin::class
29+
)
30+
class VpnDdgBrowserTrafficSettingPlugin @Inject constructor(
31+
private val appTpFeatureConfig: AppTpFeatureConfig,
32+
) : AppTpSettingPlugin {
33+
private val jsonAdapter = Moshi.Builder().build().adapter(JsonConfigModel::class.java)
34+
35+
override fun store(name: SettingName, jsonString: String): Boolean {
36+
@Suppress("NAME_SHADOWING")
37+
val name = appTpSettingValueOf(name.value)
38+
if (name == settingName) {
39+
Timber.d("Received configuration: $jsonString")
40+
jsonAdapter.fromJson(jsonString)?.let { config ->
41+
appTpFeatureConfig.edit { setEnabled(settingName, config.state == "enabled") }
42+
}
43+
return true
44+
}
45+
46+
return false
47+
}
48+
49+
override val settingName: SettingName = AppTpSetting.VpnDdgBrowserTraffic
50+
51+
private data class JsonConfigModel(val state: String?)
52+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (c) 2022 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.mobile.android.vpn.bug
18+
19+
import com.duckduckgo.mobile.android.vpn.processor.tcp.tracker.RequestTrackerType
20+
import org.junit.Assert
21+
import org.junit.Before
22+
import org.junit.Test
23+
24+
private const val HOSTNAME = "hostname"
25+
private const val DDG_PACKAGE_ID = "com.duckduckgo.mobile"
26+
private const val OTHER_PACKAGE_ID = "other.package.id"
27+
28+
class BrowserTrafficTransparencyInterceptorTest {
29+
private lateinit var browserTrafficTransparencyInterceptor: BrowserTrafficTransparencyInterceptor
30+
31+
@Before
32+
fun before() {
33+
browserTrafficTransparencyInterceptor = BrowserTrafficTransparencyInterceptor()
34+
}
35+
36+
@Test
37+
fun whenInterceptingDdgPackageIdThenReturnNotTracker() {
38+
val trackerType = browserTrafficTransparencyInterceptor.interceptTrackerRequest(HOSTNAME, DDG_PACKAGE_ID)
39+
Assert.assertEquals(trackerType, RequestTrackerType.NotTracker(HOSTNAME))
40+
}
41+
42+
@Test
43+
fun whenInterceptingNotDdgPackageIdThenReturnNull() {
44+
val trackerType = browserTrafficTransparencyInterceptor.interceptTrackerRequest(HOSTNAME, OTHER_PACKAGE_ID)
45+
Assert.assertNull(trackerType)
46+
}
47+
}

vpn/src/test/java/com/duckduckgo/mobile/android/vpn/feature/AppTpSettingTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class AppTpSettingTest {
3232
AppTpSetting.NetworkSwitchHandling -> assertFalse(setting.defaultValue)
3333
AppTpSetting.SetActiveNetworkDns -> assertFalse(setting.defaultValue)
3434
AppTpSetting.AlwaysSetDNS -> assertFalse(setting.defaultValue)
35+
AppTpSetting.VpnDdgBrowserTraffic -> assertFalse(setting.defaultValue)
36+
else -> throw java.lang.IllegalStateException("Missing AppTpSetting default checks")
3537
}
3638
}
3739
}

0 commit comments

Comments
 (0)
0