1 /*
<lambda>null2  * Copyright 2024 The Android Open Source Project
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 androidx.credentials.registry.provider
18 
19 import android.content.Context
20 import android.os.CancellationSignal
21 import androidx.credentials.CredentialManagerCallback
22 import java.util.concurrent.Executor
23 import kotlin.coroutines.resume
24 import kotlin.coroutines.resumeWithException
25 import kotlinx.coroutines.suspendCancellableCoroutine
26 
27 /**
28  * APIs for managing credential registries that are registered with the Credential Manager.
29  *
30  * Use the APIs by constructing a [RegistryManager] with the [create] factory method.
31  */
32 public abstract class RegistryManager internal constructor() {
33     public companion object {
34         /**
35          * Creates a [RegistryManager] based on the given [context].
36          *
37          * @param context the context with which the RegistryManager should be associated
38          */
39         @JvmStatic
40         public fun create(context: Context): RegistryManager = RegistryManagerImpl(context)
41 
42         /**
43          * The intent action name that the Credential Manager used to find and invoke your activity
44          * when the user selects a credential that belongs to your application. Your activity will
45          * be launched and you should use the
46          * [androidx.credentials.provider.PendingIntentHandler.retrieveProviderGetCredentialRequest]
47          * API to retrieve information about the user selection (you can do this through
48          * [androidx.credentials.registry.provider.selectedEntryId]), the verifier request, and
49          * other caller app information contained in
50          * [androidx.credentials.provider.ProviderGetCredentialRequest].
51          *
52          * Next, perform the necessary steps (e.g. consent collection, credential lookup) to
53          * generate a response for the given request. Pass the result back using one of the
54          * [androidx.credentials.provider.PendingIntentHandler.setGetCredentialResponse] and
55          * [androidx.credentials.provider.PendingIntentHandler.setGetCredentialException] APIs.
56          */
57         public const val ACTION_GET_CREDENTIAL: String =
58             "androidx.credentials.registry.provider.action.GET_CREDENTIAL"
59     }
60 
61     /**
62      * Registers credentials with the Credential Manager.
63      *
64      * The registries will then be used by the Credential Manager when handling an app calling
65      * request (see [androidx.credentials.CredentialManager]). The Credential Manager will determine
66      * if the registry contains some credential(s) qualified as a candidate to fulfill the given
67      * request, and if so it will surface a user selector UI to collect the user decision for
68      * whether to proceed with the operation.
69      *
70      * @param request the request containing the credential data to register
71      */
72     public suspend fun registerCredentials(
73         request: RegisterCredentialsRequest
74     ): RegisterCredentialsResponse = suspendCancellableCoroutine { continuation ->
75         // Any Android API that supports cancellation should be configured to propagate
76         // coroutine cancellation as follows:
77         val canceller = CancellationSignal()
78         continuation.invokeOnCancellation { canceller.cancel() }
79 
80         val callback =
81             object :
82                 CredentialManagerCallback<
83                     RegisterCredentialsResponse,
84                     RegisterCredentialsException
85                 > {
86                 override fun onResult(result: RegisterCredentialsResponse) {
87                     if (continuation.isActive) {
88                         continuation.resume(result)
89                     }
90                 }
91 
92                 override fun onError(e: RegisterCredentialsException) {
93                     if (continuation.isActive) {
94                         continuation.resumeWithException(e)
95                     }
96                 }
97             }
98 
99         registerCredentialsAsync(
100             request,
101             canceller,
102             // Use a direct executor to avoid extra dispatch. Resuming the continuation will
103             // handle getting to the right thread or pool via the ContinuationInterceptor.
104             Runnable::run,
105             callback
106         )
107     }
108 
109     /**
110      * Registers credentials with the Credential Manager.
111      *
112      * This API uses callbacks instead of Kotlin coroutines.
113      *
114      * The registries will then be used by the Credential Manager when handling an app calling
115      * request (see [androidx.credentials.CredentialManager]). The Credential Manager will determine
116      * if the registry contains some credential(s) qualified as a candidate to fulfill the given
117      * request, and if so it will surface a user selector UI to collect the user decision for
118      * whether to proceed with the operation.
119      *
120      * @param request the request containing the credential data to register
121      * @param cancellationSignal an optional signal that allows for cancelling this call
122      * @param executor the callback will take place on this executor
123      * @param callback the callback invoked when the request succeeds or fails
124      */
125     public abstract fun registerCredentialsAsync(
126         request: RegisterCredentialsRequest,
127         cancellationSignal: CancellationSignal?,
128         executor: Executor,
129         callback:
130             CredentialManagerCallback<RegisterCredentialsResponse, RegisterCredentialsException>
131     )
132 
133     // TODO: b/355652174 add clear registry APIs.
134 }
135