@@ -6,6 +6,7 @@ import kotlinx.coroutines.CoroutineScope
66import kotlinx.coroutines.launch
77import kotlinx.coroutines.suspendCancellableCoroutine
88import java.security.cert.X509Certificate
9+ import java.util.Collections
910import kotlin.coroutines.Continuation
1011import 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