1 /*
2  * Copyright 2022 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
18 
19 import android.os.Bundle
20 import androidx.annotation.RestrictTo
21 import androidx.credentials.internal.FrameworkClassParsingException
22 
23 /**
24  * Base response class for the credential creation operation made with the
25  * [CreateCredentialRequest].
26  *
27  * @sample androidx.credentials.samples.processCreateCredentialResponse
28  * @property type the credential type determined by the credential-type-specific subclass (e.g. the
29  *   type for [CreatePasswordResponse] is [PasswordCredential.TYPE_PASSWORD_CREDENTIAL] and for
30  *   [CreatePublicKeyCredentialResponse] is [PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL])
31  * @property data the response data in the [Bundle] format
32  */
33 abstract class CreateCredentialResponse
34 internal constructor(
35     val type: String,
36     val data: Bundle,
37 ) {
38     internal companion object {
39         @JvmStatic
40         @RestrictTo(RestrictTo.Scope.LIBRARY) // used from java tests
createFromnull41         fun createFrom(type: String, data: Bundle): CreateCredentialResponse {
42             return try {
43                 when (type) {
44                     PasswordCredential.TYPE_PASSWORD_CREDENTIAL ->
45                         CreatePasswordResponse.createFrom(data)
46                     PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL ->
47                         CreatePublicKeyCredentialResponse.createFrom(data)
48                     else -> throw FrameworkClassParsingException()
49                 }
50             } catch (e: FrameworkClassParsingException) {
51                 // Parsing failed but don't crash the process. Instead just output a response
52                 // with the raw framework values.
53                 CreateCustomCredentialResponse(type, data)
54             }
55         }
56 
57         private const val EXTRA_CREATE_CREDENTIAL_RESPONSE_TYPE =
58             "androidx.credentials.provider.extra.CREATE_CREDENTIAL_RESPONSE_TYPE"
59         private const val EXTRA_CREATE_CREDENTIAL_RESPONSE_DATA =
60             "androidx.credentials.provider.extra.CREATE_CREDENTIAL_REQUEST_DATA"
61 
62         @JvmStatic
63         @RestrictTo(RestrictTo.Scope.LIBRARY)
fromBundlenull64         fun fromBundle(bundle: Bundle): CreateCredentialResponse? {
65             val type = bundle.getString(EXTRA_CREATE_CREDENTIAL_RESPONSE_TYPE) ?: return null
66             val data = bundle.getBundle(EXTRA_CREATE_CREDENTIAL_RESPONSE_DATA) ?: return null
67             return createFrom(type, data)
68         }
69 
70         @JvmStatic
71         @RestrictTo(RestrictTo.Scope.LIBRARY)
asBundlenull72         fun asBundle(response: CreateCredentialResponse): Bundle =
73             Bundle().apply {
74                 this.putString(EXTRA_CREATE_CREDENTIAL_RESPONSE_TYPE, response.type)
75                 this.putBundle(EXTRA_CREATE_CREDENTIAL_RESPONSE_DATA, response.data)
76             }
77     }
78 }
79