| /* |
| * Copyright 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package androidx.credentials |
| |
| import android.os.Bundle |
| import androidx.annotation.RequiresApi |
| import androidx.annotation.RestrictTo |
| import androidx.credentials.internal.FrameworkClassParsingException |
| |
| /** |
| * A request to save the user password credential with their password provider. |
| * |
| * @param id the user id associated with the password |
| * @param password the password |
| * @param origin the origin of a different application if the request is being made on behalf of |
| * that application (Note: for API level >=34, setting a non-null value for this parameter will |
| * throw a SecurityException if android.permission.CREDENTIAL_MANAGER_SET_ORIGIN is not present) |
| * @param preferImmediatelyAvailableCredentials true if you prefer the operation to return |
| * immediately when there is no available credential creation offering instead of falling back to |
| * discovering remote options, and false (default) otherwise |
| * @property id the user id associated with the password |
| * @property password the password |
| */ |
| class CreatePasswordRequest |
| private constructor( |
| val id: String, |
| val password: String, |
| isAutoSelectAllowed: Boolean, |
| displayInfo: DisplayInfo, |
| origin: String? = null, |
| preferImmediatelyAvailableCredentials: Boolean, |
| credentialData: Bundle = toCredentialDataBundle(id, password), |
| candidateQueryData: Bundle = toCandidateDataBundle(), |
| ) : |
| CreateCredentialRequest( |
| type = PasswordCredential.TYPE_PASSWORD_CREDENTIAL, |
| credentialData = credentialData, |
| candidateQueryData = candidateQueryData, |
| isSystemProviderRequired = false, |
| isAutoSelectAllowed, |
| displayInfo, |
| origin, |
| preferImmediatelyAvailableCredentials, |
| ) { |
| |
| /** |
| * Constructs a [CreatePasswordRequest] to save the user password credential with their password |
| * provider. |
| * |
| * @param id the user id associated with the password |
| * @param password the password |
| * @param origin the origin of a different application if the request is being made on behalf of |
| * that application (Note: for API level >=34, setting a non-null value for this parameter |
| * will throw a SecurityException if android.permission.CREDENTIAL_MANAGER_SET_ORIGIN is not |
| * present) |
| * @param preferImmediatelyAvailableCredentials true if you prefer the operation to return |
| * immediately when there is no available password saving option instead of falling back to |
| * discovering remote options, and false (default) otherwise |
| * @param isAutoSelectAllowed whether a create option will be automatically chosen if it is the |
| * only one available to the user (note that there is a chance that the credential provider |
| * does not support auto-select even if you turn this bit on); not recommended to be true for |
| * password request type to ensure that the user will always get a confirmation dialog even if |
| * the password saving provider does not offer any UI |
| * @throws NullPointerException If [id] is null |
| * @throws NullPointerException If [password] is null |
| * @throws IllegalArgumentException If [password] is empty |
| * @throws SecurityException if [origin] is set but |
| * android.permission.CREDENTIAL_MANAGER_SET_ORIGIN is not present |
| */ |
| @JvmOverloads |
| constructor( |
| id: String, |
| password: String, |
| origin: String? = null, |
| preferImmediatelyAvailableCredentials: Boolean = false, |
| isAutoSelectAllowed: Boolean = false, |
| ) : this( |
| id = id, |
| password = password, |
| isAutoSelectAllowed = isAutoSelectAllowed, |
| displayInfo = DisplayInfo(id, null), |
| origin = origin, |
| preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials |
| ) |
| |
| /** |
| * Constructs a [CreatePasswordRequest] to save the user password credential with their password |
| * provider. |
| * |
| * @param id the user id associated with the password |
| * @param password the password |
| * @param origin the origin of a different application if the request is being made on behalf of |
| * that application (Note: for API level >=34, setting a non-null value for this parameter |
| * will throw a SecurityException if android.permission.CREDENTIAL_MANAGER_SET_ORIGIN is not |
| * present) |
| * @param preferDefaultProvider the preferred default provider component name to prioritize in |
| * the selection UI flows (Note: your app must have the permission |
| * android.permission.CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS to specify this, or it would |
| * not take effect; also this bit may not take effect for Android API level 33 and below, |
| * depending on the pre-34 provider(s) you have chosen) |
| * @param preferImmediatelyAvailableCredentials true if you prefer the operation to return |
| * immediately when there is no available passkey registration offering instead of falling |
| * back to discovering remote options, and false (preferably) otherwise |
| * @param isAutoSelectAllowed whether a create option will be automatically chosen if it is the |
| * only one available to the user (note that there is a chance that the credential provider |
| * does not support auto-select even if you turn this bit on); not recommended to be true for |
| * password request type to ensure that the user will always get a confirmation dialog even if |
| * the password saving provider does not offer any UI |
| * @throws NullPointerException If [id] is null |
| * @throws NullPointerException If [password] is null |
| * @throws IllegalArgumentException If [password] is empty |
| * @throws SecurityException if [origin] is set but |
| * android.permission.CREDENTIAL_MANAGER_SET_ORIGIN is not present |
| */ |
| constructor( |
| id: String, |
| password: String, |
| origin: String?, |
| preferDefaultProvider: String?, |
| preferImmediatelyAvailableCredentials: Boolean, |
| isAutoSelectAllowed: Boolean |
| ) : this( |
| id = id, |
| password = password, |
| isAutoSelectAllowed = isAutoSelectAllowed, |
| displayInfo = |
| DisplayInfo( |
| userId = id, |
| userDisplayName = null, |
| preferDefaultProvider = preferDefaultProvider, |
| ), |
| origin = origin, |
| preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials, |
| ) |
| |
| init { |
| require(password.isNotEmpty()) { "password should not be empty" } |
| } |
| |
| internal companion object { |
| @RestrictTo(RestrictTo.Scope.LIBRARY) // used from java tests |
| const val BUNDLE_KEY_ID = "androidx.credentials.BUNDLE_KEY_ID" |
| @RestrictTo(RestrictTo.Scope.LIBRARY) // used from java tests |
| const val BUNDLE_KEY_PASSWORD = "androidx.credentials.BUNDLE_KEY_PASSWORD" |
| |
| @JvmStatic |
| internal fun toCredentialDataBundle(id: String, password: String): Bundle { |
| val bundle = Bundle() |
| bundle.putString(BUNDLE_KEY_ID, id) |
| bundle.putString(BUNDLE_KEY_PASSWORD, password) |
| return bundle |
| } |
| |
| // No credential data should be sent during the query phase. |
| @JvmStatic |
| internal fun toCandidateDataBundle(): Bundle { |
| return Bundle() |
| } |
| |
| @JvmStatic |
| @RequiresApi(23) |
| internal fun createFrom( |
| data: Bundle, |
| origin: String?, |
| candidateQueryData: Bundle, |
| ): CreatePasswordRequest { |
| try { |
| val id = data.getString(BUNDLE_KEY_ID)!! |
| val password = data.getString(BUNDLE_KEY_PASSWORD)!! |
| val displayInfo = |
| try { |
| DisplayInfo.createFrom(data) |
| } catch (e: IllegalArgumentException) { |
| DisplayInfo(id, null) |
| } |
| val preferImmediatelyAvailableCredentials = |
| data.getBoolean(BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS, false) |
| val isAutoSelectAllowed = data.getBoolean(BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED, false) |
| return CreatePasswordRequest( |
| id = id, |
| password = password, |
| displayInfo = displayInfo, |
| origin = origin, |
| preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials, |
| credentialData = data, |
| candidateQueryData = candidateQueryData, |
| isAutoSelectAllowed = isAutoSelectAllowed, |
| ) |
| } catch (e: Exception) { |
| throw FrameworkClassParsingException() |
| } |
| } |
| } |
| } |