Skip to content

Commit 48210ff

Browse files
Merge branch 'release/5.234.0'
2 parents 58eb48b + d221e27 commit 48210ff

File tree

82 files changed

+1911
-455
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1911
-455
lines changed

.maestro/autofill/2_autofill_add_search_update_delete_creds.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ tags:
7272

7373
- tapOn: "Navigate up"
7474

75-
- assertVisible:
76-
text: "Save and autofill passwords"
7775
- evalScript: ${output.addLogins.counter++}
7876

7977
- scrollUntilVisible:
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
appId: com.duckduckgo.mobile.android
2+
name: "Autofill: Autofill Settings Screen"
3+
tags:
4+
- autofillNoAuthTests
5+
---
6+
# Pre-requisite: on an autofill-eligible device
7+
- retry:
8+
maxRetries: 3
9+
commands:
10+
- launchApp:
11+
clearState: true
12+
- runFlow: ../shared/skip_all_onboarding.yaml
13+
14+
- tapOn:
15+
id: "com.duckduckgo.mobile.android:id/browserMenuImageView"
16+
- assertVisible: "Settings"
17+
- tapOn: "Settings"
18+
19+
- scrollUntilVisible:
20+
element:
21+
text: "Passwords.*"
22+
- assertVisible: "Passwords.*"
23+
- tapOn: "Passwords.*"
24+
25+
- assertVisible:
26+
id: secondaryText
27+
text: "0"
28+
29+
- assertVisible:
30+
text: "Ask to Save and Autofill"
31+
32+
- assertVisible:
33+
id: syncDesktopPasswordsOption
34+
35+
- tapOn:
36+
id: passwordsListItem
37+
38+
- assertVisible:
39+
text: "No passwords saved yet"
40+
- assertNotVisible:
41+
id: searchLogins
42+
43+
- runScript: steps/2_script.js
44+
45+
- repeat:
46+
while:
47+
true: ${output.addLogins.counter < output.addLogins.domains.length}
48+
commands:
49+
- tapOn:
50+
id: addLoginManually
51+
- assertVisible:
52+
text: Add Password
53+
- assertNotVisible:
54+
id: view_menu_save
55+
56+
- scrollUntilVisible:
57+
element:
58+
id: usernameEditText
59+
- tapOn:
60+
id: usernameEditText
61+
- inputText: "user"
62+
63+
- assertVisible:
64+
id: view_menu_save
65+
66+
- scrollUntilVisible:
67+
element:
68+
id: passwordEditText
69+
- tapOn:
70+
id: passwordEditText
71+
- inputText: "123"
72+
73+
- scrollUntilVisible:
74+
element:
75+
id: domainEditText
76+
- tapOn:
77+
id: domainEditText
78+
- inputText: "${output.addLogins.domains[output.addLogins.counter]}"
79+
80+
- scrollUntilVisible:
81+
element:
82+
id: notesEditText
83+
- tapOn:
84+
id: notesEditText
85+
- inputText: "a note"
86+
87+
- tapOn:
88+
id: view_menu_save
89+
retryTapIfNoChange: false
90+
91+
- scrollUntilVisible:
92+
element:
93+
text: "Last updated.*"
94+
- assertVisible: "Last updated.*"
95+
96+
- tapOn: "Navigate up"
97+
98+
- evalScript: ${output.addLogins.counter++}
99+
100+
- scrollUntilVisible:
101+
element:
102+
text: "#"
103+
- assertVisible:
104+
text: "#"
105+
106+
- scrollUntilVisible:
107+
element:
108+
text: "a.example.com"
109+
- assertVisible:
110+
text: "a.example.com"
111+
112+
- assertNotVisible:
113+
text: "https://a.example.com"
114+
115+
- scrollUntilVisible:
116+
element:
117+
text: "fill.dev"
118+
- assertVisible:
119+
text: "fill.dev"
120+
121+
- assertNotVisible:
122+
text: "fill.dev/example"
123+
124+
- tapOn: "Navigate up"
125+
126+
- assertVisible:
127+
id: secondaryText
128+
text: "3"

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/blocklist/AppTrackerListUpdateWorker.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ import com.duckduckgo.anvil.annotations.ContributesWorker
2828
import com.duckduckgo.app.lifecycle.MainProcessLifecycleObserver
2929
import com.duckduckgo.common.utils.DispatcherProvider
3030
import com.duckduckgo.di.scopes.AppScope
31+
import com.duckduckgo.mobile.android.vpn.di.AppTpBlocklistUpdateMutex
3132
import com.duckduckgo.mobile.android.vpn.store.VpnDatabase
3233
import com.duckduckgo.mobile.android.vpn.trackers.AppTrackerMetadata
3334
import com.squareup.anvil.annotations.ContributesMultibinding
3435
import java.util.concurrent.TimeUnit
3536
import javax.inject.Inject
37+
import kotlinx.coroutines.sync.Mutex
38+
import kotlinx.coroutines.sync.withLock
3639
import kotlinx.coroutines.withContext
3740
import logcat.LogPriority
3841
import logcat.logcat
@@ -49,9 +52,15 @@ class AppTrackerListUpdateWorker(context: Context, workerParameters: WorkerParam
4952
@Inject
5053
lateinit var dispatchers: DispatcherProvider
5154

55+
@Inject
56+
@AppTpBlocklistUpdateMutex
57+
lateinit var mutex: Mutex
58+
5259
override suspend fun doWork(): Result {
5360
return withContext(dispatchers.io()) {
54-
val updateBlocklistResult = updateTrackerBlocklist()
61+
val updateBlocklistResult = mutex.withLock {
62+
updateTrackerBlocklist()
63+
}
5564

5665
val success = Result.success()
5766
if (updateBlocklistResult != success) {
@@ -73,6 +82,11 @@ class AppTrackerListUpdateWorker(context: Context, workerParameters: WorkerParam
7382
vpnDatabase.vpnAppTrackerBlockingDao().getTrackerBlocklistMetadata()?.eTag
7483
val updatedEtag = blocklist.etag.value
7584

85+
if (updatedEtag == currentEtag) {
86+
logcat { "Downloaded blocklist has same eTag, noop" }
87+
return Result.success()
88+
}
89+
7690
logcat { "Updating the app tracker blocklist, previous/new eTag: $currentEtag / $updatedEtag" }
7791

7892
vpnDatabase

app-tracking-protection/vpn-impl/src/main/java/com/duckduckgo/mobile/android/vpn/di/VpnAppModule.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import android.content.Context
2020
import android.content.res.Resources
2121
import android.net.ConnectivityManager
2222
import androidx.room.Room
23+
import com.duckduckgo.app.di.AppCoroutineScope
2324
import com.duckduckgo.common.utils.DispatcherProvider
2425
import com.duckduckgo.di.scopes.AppScope
2526
import com.duckduckgo.mobile.android.vpn.stats.AppTrackerBlockingStatsRepository
@@ -32,6 +33,9 @@ import dagger.Module
3233
import dagger.Provides
3334
import dagger.SingleInstanceIn
3435
import javax.inject.Provider
36+
import javax.inject.Qualifier
37+
import kotlinx.coroutines.CoroutineScope
38+
import kotlinx.coroutines.sync.Mutex
3539

3640
@Module
3741
@ContributesTo(AppScope::class)
@@ -47,8 +51,18 @@ object VpnAppModule {
4751
fun provideVpnDatabaseCallbackProvider(
4852
context: Context,
4953
vpnDatabase: Provider<VpnDatabase>,
54+
dispatcherProvider: DispatcherProvider,
55+
@AppCoroutineScope coroutineScope: CoroutineScope,
56+
@AppTpBlocklistUpdateMutex mutex: Mutex,
5057
): VpnDatabaseCallbackProvider {
51-
return VpnDatabaseCallbackProvider(context, vpnDatabase)
58+
return VpnDatabaseCallbackProvider(context, vpnDatabase, dispatcherProvider, coroutineScope, mutex)
59+
}
60+
61+
@Provides
62+
@SingleInstanceIn(AppScope::class)
63+
@AppTpBlocklistUpdateMutex
64+
fun providesAppTpBlocklistUpdateMutex(): Mutex {
65+
return Mutex()
5266
}
5367

5468
/**
@@ -91,3 +105,7 @@ object VpnAppModule {
91105
return RealAppTrackerBlockingStatsRepository(vpnDatabase, dispatchers)
92106
}
93107
}
108+
109+
@Retention(AnnotationRetention.BINARY)
110+
@Qualifier
111+
internal annotation class AppTpBlocklistUpdateMutex

app-tracking-protection/vpn-store/src/main/java/com/duckduckgo/mobile/android/vpn/store/VpnDatabase.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import java.time.format.DateTimeFormatter
3030

3131
@Database(
3232
exportSchema = true,
33-
version = 33,
33+
version = 34,
3434
entities = [
3535
VpnTracker::class,
3636
VpnServiceStateStats::class,
@@ -214,6 +214,12 @@ abstract class VpnDatabase : RoomDatabase() {
214214
}
215215
}
216216

217+
private val MIGRATION_33_TO_34: Migration = object : Migration(33, 34) {
218+
override fun migrate(database: SupportSQLiteDatabase) {
219+
database.execSQL("DELETE FROM `vpn_app_tracker_blocking_list_metadata`")
220+
}
221+
}
222+
217223
val ALL_MIGRATIONS: List<Migration>
218224
get() = listOf(
219225
MIGRATION_18_TO_19,
@@ -231,6 +237,7 @@ abstract class VpnDatabase : RoomDatabase() {
231237
MIGRATION_30_TO_31,
232238
MIGRATION_31_TO_32,
233239
MIGRATION_32_TO_33,
240+
MIGRATION_33_TO_34,
234241
)
235242
}
236243
}

app-tracking-protection/vpn-store/src/main/java/com/duckduckgo/mobile/android/vpn/store/VpnDatabaseCallback.kt

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,44 +17,61 @@
1717
package com.duckduckgo.mobile.android.vpn.store
1818

1919
import android.content.Context
20-
import androidx.annotation.VisibleForTesting
2120
import androidx.room.RoomDatabase
2221
import androidx.sqlite.db.SupportSQLiteDatabase
2322
import com.duckduckgo.common.utils.DispatcherProvider
2423
import com.duckduckgo.mobile.android.vpn.trackers.*
2524
import com.squareup.moshi.JsonAdapter
2625
import com.squareup.moshi.Moshi
27-
import java.util.*
2826
import javax.inject.Provider
27+
import kotlinx.coroutines.CoroutineScope
2928
import kotlinx.coroutines.ExperimentalCoroutinesApi
30-
import kotlinx.coroutines.asExecutor
29+
import kotlinx.coroutines.launch
30+
import kotlinx.coroutines.sync.Mutex
31+
import kotlinx.coroutines.sync.withLock
32+
import logcat.logcat
3133

3234
@OptIn(ExperimentalCoroutinesApi::class)
3335
internal class VpnDatabaseCallback(
3436
private val context: Context,
3537
private val vpnDatabase: Provider<VpnDatabase>,
3638
private val dispatcherProvider: DispatcherProvider,
39+
private val coroutineScope: CoroutineScope,
40+
private val mutex: Mutex,
3741
) : RoomDatabase.Callback() {
3842

3943
override fun onCreate(db: SupportSQLiteDatabase) {
4044
super.onCreate(db)
41-
ioThread {
42-
prepopulateAppTrackerBlockingList()
43-
prepopulateAppTrackerExclusionList()
44-
prepopulateAppTrackerExceptionRules()
45+
coroutineScope.launch(dispatcherProvider.io()) {
46+
mutex.withLock {
47+
if (vpnDatabase.get().vpnAppTrackerBlockingDao().getTrackerBlocklistMetadata()?.eTag == null) {
48+
logcat { "VPN-db onCreate: pre-populating db" }
49+
// only pre-populate when there's no blocklist
50+
prepopulateAppTrackerBlockingList()
51+
prepopulateAppTrackerExclusionList()
52+
prepopulateAppTrackerExceptionRules()
53+
} else {
54+
logcat { "VPN-db onCreate: SKIP pre-populating db" }
55+
}
56+
}
4557
}
4658
}
4759

4860
override fun onDestructiveMigration(db: SupportSQLiteDatabase) {
49-
ioThread {
50-
prepopulateAppTrackerBlockingList()
51-
prepopulateAppTrackerExclusionList()
52-
prepopulateAppTrackerExceptionRules()
61+
coroutineScope.launch(dispatcherProvider.io()) {
62+
mutex.withLock {
63+
if (vpnDatabase.get().vpnAppTrackerBlockingDao().getTrackerBlocklistMetadata()?.eTag == null) {
64+
logcat { "VPN-db onDestructiveMigration: pre-populating db" }
65+
// only pre-populate when there's no blocklist
66+
prepopulateAppTrackerBlockingList()
67+
prepopulateAppTrackerExclusionList()
68+
prepopulateAppTrackerExceptionRules()
69+
}
70+
}
5371
}
5472
}
5573

56-
@VisibleForTesting
57-
internal fun prepopulateAppTrackerBlockingList() {
74+
private fun prepopulateAppTrackerBlockingList() {
5875
context.resources.openRawResource(R.raw.full_app_trackers_blocklist).bufferedReader()
5976
.use { it.readText() }
6077
.also {
@@ -100,10 +117,4 @@ internal class VpnDatabaseCallback(
100117
val adapter: JsonAdapter<JsonAppTrackerExceptionRules> = moshi.adapter(JsonAppTrackerExceptionRules::class.java)
101118
return adapter.fromJson(json)?.rules.orEmpty()
102119
}
103-
104-
@OptIn(ExperimentalCoroutinesApi::class)
105-
private fun ioThread(f: () -> Unit) {
106-
// At most 1 thread will be doing IO
107-
dispatcherProvider.io().limitedParallelism(1).asExecutor().execute(f)
108-
}
109120
}

app-tracking-protection/vpn-store/src/main/java/com/duckduckgo/mobile/android/vpn/store/VpnDatabaseCallbackProvider.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,19 @@ package com.duckduckgo.mobile.android.vpn.store
1818

1919
import android.content.Context
2020
import androidx.room.RoomDatabase
21-
import com.duckduckgo.common.utils.DefaultDispatcherProvider
21+
import com.duckduckgo.common.utils.DispatcherProvider
2222
import javax.inject.Provider
23+
import kotlinx.coroutines.CoroutineScope
24+
import kotlinx.coroutines.sync.Mutex
2325

2426
class VpnDatabaseCallbackProvider constructor(
2527
private val context: Context,
2628
private val vpnDatabaseProvider: Provider<VpnDatabase>,
29+
private val dispatcherProvider: DispatcherProvider,
30+
private val coroutineScope: CoroutineScope,
31+
private val mutex: Mutex,
2732
) {
2833
fun provideCallbacks(): RoomDatabase.Callback {
29-
return VpnDatabaseCallback(context, vpnDatabaseProvider, DefaultDispatcherProvider())
34+
return VpnDatabaseCallback(context, vpnDatabaseProvider, dispatcherProvider, coroutineScope, mutex)
3035
}
3136
}

0 commit comments

Comments
 (0)