@@ -20,6 +20,7 @@ import com.google.firebase.annotations.DeferredApi
2020import com.google.firebase.appcheck.interop.InteropAppCheckTokenProvider
2121import com.google.firebase.auth.internal.InternalAuthProvider
2222import com.google.firebase.dataconnect.DataConnectException
23+ import com.google.firebase.dataconnect.core.DataConnectCredentialsTokenManager.GetTokenResult
2324import com.google.firebase.dataconnect.core.Globals.toScrubbedAccessToken
2425import com.google.firebase.dataconnect.core.LoggerGlobals.debug
2526import com.google.firebase.dataconnect.core.LoggerGlobals.warn
@@ -52,7 +53,7 @@ import kotlinx.coroutines.flow.update
5253import kotlinx.coroutines.launch
5354
5455/* * Base class that shares logic for managing the Auth token and AppCheck token. */
55- internal sealed class DataConnectCredentialsTokenManager <T : Any >(
56+ internal sealed class DataConnectCredentialsTokenManager <T : Any , R : GetTokenResult >(
5657 private val deferredProvider : com.google.firebase.inject.Deferred <T >,
5758 parentCoroutineScope : CoroutineScope ,
5859 private val blockingDispatcher : CoroutineDispatcher ,
@@ -75,13 +76,13 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
7576 }
7677 )
7778
78- private sealed interface State <out T > {
79+ private sealed interface State <out T , out R : GetTokenResult > {
7980
8081 /* *
8182 * State indicating that the object has just been created and [initialize] has not yet been
8283 * called.
8384 */
84- object New : State<Nothing>
85+ object New : State<Nothing, Nothing >
8586
8687 /* *
8788 * State indicating that [initialize] has been invoked but the token provider is not (yet?)
@@ -93,33 +94,33 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
9394 }
9495
9596 /* * State indicating that [close] has been invoked. */
96- object Closed : State<Nothing>
97+ object Closed : State<Nothing, Nothing >
9798
98- sealed interface StateWithForceTokenRefresh <out T > : State <T > {
99+ sealed interface StateWithForceTokenRefresh <out T > : State <T , Nothing > {
99100 /* * The value to specify for `forceRefresh` on the next invocation of [getToken]. */
100101 val forceTokenRefresh: Boolean
101102 }
102103
103- sealed interface StateWithProvider <out T > : State <T > {
104+ sealed interface StateWithProvider <out T , out R : GetTokenResult > : State <T , R > {
104105 /* * The token provider, [InternalAuthProvider] or [InteropAppCheckTokenProvider] */
105106 val provider: T
106107 }
107108
108109 /* * State indicating that there is no outstanding "get token" request. */
109110 data class Idle <T >(override val provider : T , override val forceTokenRefresh : Boolean ) :
110- StateWithProvider <T >, StateWithForceTokenRefresh <T >
111+ StateWithProvider <T , Nothing >, StateWithForceTokenRefresh <T >
111112
112113 /* * State indicating that there _is_ an outstanding "get token" request. */
113- data class Active <out T >(
114+ data class Active <out T , out R : GetTokenResult >(
114115 override val provider : T ,
115116
116117 /* * The job that is performing the "get token" request. */
117- val job : Deferred <SequencedReference <Result <GetTokenResult >>>
118- ) : StateWithProvider<T>
118+ val job : Deferred <SequencedReference <Result <R >>>
119+ ) : StateWithProvider<T, R >
119120 }
120121
121122 /* * The current state of this object. */
122- private val state = MutableStateFlow <State <T >>(State .New )
123+ private val state = MutableStateFlow <State <T , R >>(State .New )
123124
124125 /* *
125126 * Adds the token listener to the given provider.
@@ -139,7 +140,7 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
139140 * Starts an asynchronous task to get a new access token from the given provider, forcing a token
140141 * refresh if and only if `forceRefresh` is true.
141142 */
142- protected abstract suspend fun getToken (provider : T , forceRefresh : Boolean ): GetTokenResult
143+ protected abstract suspend fun getToken (provider : T , forceRefresh : Boolean ): R
143144
144145 /* *
145146 * Initializes this object.
@@ -274,7 +275,7 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
274275 invocationId : String ,
275276 provider : T ,
276277 forceRefresh : Boolean
277- ): State .Active <T > {
278+ ): State .Active <T , R > {
278279 val coroutineName =
279280 CoroutineName (
280281 " $instanceId 535gmcvv5a $invocationId getToken(" +
@@ -296,14 +297,14 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
296297 * @throws DataConnectException if [close] has been called or is called while the operation is in
297298 * progress.
298299 */
299- suspend fun getToken (requestId : String ): String ? {
300+ suspend fun getToken (requestId : String ): R ? {
300301 val invocationId = " gat" + Random .nextAlphanumericString(length = 8 )
301302 logger.debug { " $invocationId getToken(requestId=$requestId )" }
302303 while (true ) {
303304 val attemptSequenceNumber = nextSequenceNumber()
304305 val oldState = state.value
305306
306- val newState: State .Active <T > =
307+ val newState: State .Active <T , R > =
307308 when (oldState) {
308309 is State .New ->
309310 throw IllegalStateException (" initialize() must be called before getToken()" )
@@ -381,11 +382,12 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
381382 }
382383 }
383384
384- val accessToken = sequencedResult!! .ref.getOrThrow().token
385+ val tokenResult : R = sequencedResult!! .ref.getOrThrow()
385386 logger.debug {
386- " $invocationId getToken() returns retrieved token: ${accessToken?.toScrubbedAccessToken()} "
387+ " $invocationId getToken() returns retrieved token: " +
388+ tokenResult.token?.toScrubbedAccessToken()
387389 }
388- return accessToken
390+ return tokenResult
389391 }
390392 }
391393
@@ -440,16 +442,17 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
440442 * strong reference to the [DataConnectCredentialsTokenManager] instance indefinitely, in the case
441443 * that the callback never occurs.
442444 */
443- private class DeferredProviderHandlerImpl <T : Any >(
444- private val weakCredentialsTokenManagerRef : WeakReference <DataConnectCredentialsTokenManager <T >>
445+ private class DeferredProviderHandlerImpl <T : Any , R : GetTokenResult >(
446+ private val weakCredentialsTokenManagerRef :
447+ WeakReference <DataConnectCredentialsTokenManager <T , R >>
445448 ) : DeferredHandler<T> {
446449 override fun handle (provider : Provider <T >) {
447450 weakCredentialsTokenManagerRef.get()?.onProviderAvailable(provider.get())
448451 }
449452 }
450453
451454 private class CredentialsTokenManagerClosedException (
452- tokenProvider : DataConnectCredentialsTokenManager <* >
455+ tokenProvider : DataConnectCredentialsTokenManager <* , * >
453456 ) :
454457 DataConnectException (
455458 " DataConnectCredentialsTokenManager ${tokenProvider.instanceId} was closed (code cqrbq4zfvy)"
@@ -458,7 +461,9 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
458461 private class GetTokenCancelledException (cause : Throwable ) :
459462 DataConnectException (" getToken() was cancelled, likely by close() (code rqdd4jam9d)" , cause)
460463
461- protected data class GetTokenResult (val token : String? )
464+ interface GetTokenResult {
465+ val token: String?
466+ }
462467
463468 private companion object {
464469
0 commit comments