Skip to content

Commit 12f1b45

Browse files
committed
Use Collections.synchronizedMap to synchronize access
1 parent 6b60ca4 commit 12f1b45

File tree

1 file changed

+17
-23
lines changed

1 file changed

+17
-23
lines changed

lib/src/main/java/at/bitfire/cert4android/UserDecisionRegistry.kt

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import kotlinx.coroutines.CoroutineScope
66
import kotlinx.coroutines.launch
77
import kotlinx.coroutines.suspendCancellableCoroutine
88
import java.security.cert.X509Certificate
9+
import java.util.Collections
910
import kotlin.coroutines.Continuation
1011
import kotlin.coroutines.resume
1112

@@ -32,13 +33,12 @@ class UserDecisionRegistry private constructor(
3233
}
3334

3435
/**
35-
* Per-certificate map of pending decisions, which are [Continuation]s that are
36+
* Per-certificate list of pending decisions. Entries are pending decisions: [Continuation]s that are
37+
*
3638
* - resumed when the callback returns a decision and
3739
* - cancelled when the scope is cancelled.
38-
*
39-
* Every call of [check] adds an entry to the [Continuation] list.
4040
*/
41-
internal val pendingDecisions = mutableMapOf<X509Certificate, MutableList<Continuation<Boolean>>>()
41+
internal val pendingDecisions = Collections.synchronizedMap(mutableMapOf<X509Certificate, MutableList<Continuation<Boolean>>>())
4242

4343
/**
4444
* Tries to retrieve a trust decision from the user about a given certificate.
@@ -58,15 +58,14 @@ class UserDecisionRegistry private constructor(
5858
): Boolean = suspendCancellableCoroutine { cont ->
5959
cont.invokeOnCancellation {
6060
// remove from pending decisions on cancellation
61-
synchronized(pendingDecisions) {
62-
pendingDecisions[cert]?.remove(cont)
63-
}
61+
pendingDecisions[cert]?.remove(cont)
6462
}
6563

6664
synchronized(pendingDecisions) {
67-
if (pendingDecisions.containsKey(cert)) {
65+
val pendingDecisionsForCert = pendingDecisions[cert]
66+
if (pendingDecisionsForCert != null) {
6867
// There are already pending decisions for this request, just add our request
69-
pendingDecisions[cert]!! += cont
68+
pendingDecisionsForCert += cont
7069

7170
} else {
7271
// First decision for this certificate, add to map and show UI
@@ -92,21 +91,16 @@ class UserDecisionRegistry private constructor(
9291
else
9392
customCertStore.setUntrustedByUser(cert)
9493

95-
// continue work that's waiting for decisions
96-
synchronized(pendingDecisions) {
97-
pendingDecisions[cert]?.let { pendingDecisionsForCert ->
98-
// go through all Continuations that are waiting for a decision about this certificate
99-
val iter = pendingDecisionsForCert.iterator()
100-
while (iter.hasNext()) {
101-
// resume work with the now known trustworthiness
102-
iter.next().resume(trusted)
103-
104-
// remove current Continuation (that hast just been resumed) from list
105-
iter.remove()
106-
}
94+
// continue work that's waiting for a decision; remove from map so that getUserDecision can be called again
95+
pendingDecisions.remove(cert)?.let { pendingDecisionsForCert ->
96+
// go through list of all Continuations that are waiting for a decision about this certificate
97+
val iter = pendingDecisionsForCert.iterator()
98+
while (iter.hasNext()) {
99+
// resume work with the now known trustworthiness
100+
iter.next().resume(trusted)
107101

108-
// remove certificate from pendingDecisions so UI can be shown again in future
109-
pendingDecisions -= cert
102+
// remove current Continuation (that hast just been resumed) from list
103+
iter.remove()
110104
}
111105
}
112106
}

0 commit comments

Comments
 (0)