Merge "Improvements to MVP: address TODOs to move code to shared module." into main
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/IntentParser.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/IntentParser.kt
index 8986e52..98ad22c 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/IntentParser.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/IntentParser.kt
@@ -29,7 +29,7 @@
packageManager: PackageManager,
previousIntent: Intent? = null,
): Request {
- this.toRequestClose(packageManager, previousIntent)?.let { closeRequest ->
+ this.toRequestClose(previousIntent)?.let { closeRequest ->
return closeRequest
}
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/PasswordKtx.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/PasswordKtx.kt
new file mode 100644
index 0000000..3471070
--- /dev/null
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/PasswordKtx.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 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.0N
+ *
+ * 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 com.android.credentialmanager.ktx
+
+import androidx.activity.result.IntentSenderRequest
+import com.android.credentialmanager.IS_AUTO_SELECTED_KEY
+import com.android.credentialmanager.model.Password
+
+fun Password.getIntentSenderRequest(
+ isAutoSelected: Boolean = false
+): IntentSenderRequest {
+ val entryIntent = entry.frameworkExtrasIntent
+ entryIntent?.putExtra(IS_AUTO_SELECTED_KEY, isAutoSelected)
+
+ return IntentSenderRequest.Builder(
+ pendingIntent = passwordCredentialEntry.pendingIntent
+ ).setFillInIntent(entryIntent).build()
+}
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestCancelMapper.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestCancelMapper.kt
index 555a86f..99dc9ec 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestCancelMapper.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestCancelMapper.kt
@@ -31,9 +31,6 @@
Log.d(TAG, "Received UI cancel request with an invalid package name.")
null
} else {
- Request.Cancel(
- showCancellationUi = cancelUiRequest.shouldShowCancellationUi(),
- appName = appLabel
- )
+ Request.Cancel(appName = appLabel)
}
}
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestCloseMapper.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestCloseMapper.kt
index 6de3e7d..02ee77b 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestCloseMapper.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/mapper/RequestCloseMapper.kt
@@ -17,31 +17,33 @@
package com.android.credentialmanager.mapper
import android.content.Intent
-import android.content.pm.PackageManager
+import com.android.credentialmanager.ktx.cancelUiRequest
import com.android.credentialmanager.ktx.requestInfo
import com.android.credentialmanager.model.Request
fun Intent.toRequestClose(
- packageManager: PackageManager,
previousIntent: Intent? = null,
): Request.Close? {
// Close request comes as "Cancel" request from Credential Manager API
- val currentRequest = toRequestCancel(packageManager = packageManager) ?: return null
+ this.cancelUiRequest?.let { cancelUiRequest ->
- if (currentRequest.showCancellationUi) {
- // Current request is to Cancel and not to Close
- return null
- }
-
- previousIntent?.let {
- val previousToken = previousIntent.requestInfo?.token
- val currentToken = this.requestInfo?.token
-
- if (previousToken != currentToken) {
- // Current cancellation is for a different request, don't close the current flow.
+ if (cancelUiRequest.shouldShowCancellationUi()) {
+ // Current request is to Cancel and not to Close
return null
}
+
+ previousIntent?.let {
+ val previousToken = previousIntent.requestInfo?.token
+ val currentToken = this.requestInfo?.token
+
+ if (previousToken != currentToken) {
+ // Current cancellation is for a different request, don't close the current flow.
+ return null
+ }
+ }
+
+ return Request.Close
}
- return Request.Close
+ return null
}
\ No newline at end of file
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt
index 6011a1c..ed98f3e 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/model/Request.kt
@@ -37,7 +37,6 @@
* Request to close the app, displaying a message to the user.
*/
data class Cancel(
- val showCancellationUi: Boolean,
val appName: String
) : Request()
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/repository/PasswordRepository.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/repository/PasswordRepository.kt
new file mode 100644
index 0000000..1cce3ba
--- /dev/null
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/repository/PasswordRepository.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 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.0N
+ *
+ * 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 com.android.credentialmanager.repository
+
+import android.content.Intent
+import android.credentials.ui.BaseDialogResult
+import android.credentials.ui.ProviderPendingIntentResponse
+import android.credentials.ui.UserSelectionDialogResult
+import android.os.Bundle
+import android.util.Log
+import com.android.credentialmanager.TAG
+import com.android.credentialmanager.model.Password
+import com.android.credentialmanager.model.Request
+
+class PasswordRepository {
+
+ suspend fun selectPassword(
+ password: Password,
+ request: Request.Get,
+ resultCode: Int? = null,
+ resultData: Intent? = null,
+ ) {
+ Log.d(TAG, "password selected: {provider=${password.providerId}" +
+ ", key=${password.entry.key}, subkey=${password.entry.subkey}}")
+
+ val userSelectionDialogResult = UserSelectionDialogResult(
+ request.token,
+ password.providerId,
+ password.entry.key,
+ password.entry.subkey,
+ if (resultCode != null) ProviderPendingIntentResponse(resultCode, resultData) else null
+ )
+ val resultDataBundle = Bundle()
+ UserSelectionDialogResult.addToBundle(userSelectionDialogResult, resultDataBundle)
+ request.resultReceiver?.send(
+ BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION,
+ resultDataBundle
+ )
+ }
+}
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorApp.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorApp.kt
index 7c81fd0..e8e4033 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorApp.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/CredentialSelectorApp.kt
@@ -18,11 +18,13 @@
import android.app.Application
import com.android.credentialmanager.di.inject
+import com.android.credentialmanager.repository.PasswordRepository
import com.android.credentialmanager.repository.RequestRepository
class CredentialSelectorApp : Application() {
lateinit var requestRepository: RequestRepository
+ lateinit var passwordRepository: PasswordRepository
override fun onCreate() {
super.onCreate()
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/di/DI.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/di/DI.kt
index a11017b..1e8f83d 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/di/DI.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/di/DI.kt
@@ -2,12 +2,14 @@
import android.app.Application
import com.android.credentialmanager.CredentialSelectorApp
+import com.android.credentialmanager.repository.PasswordRepository
import com.android.credentialmanager.repository.RequestRepository
// TODO b/301601582 add Hilt for dependency injection
fun CredentialSelectorApp.inject() {
requestRepository = requestRepository(application = this)
+ passwordRepository = passwordRepository()
}
private fun requestRepository(
@@ -15,3 +17,5 @@
): RequestRepository = RequestRepository(
application = application,
)
+
+private fun passwordRepository(): PasswordRepository = PasswordRepository()
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
index c885ec4..c87cfd3 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
@@ -35,6 +35,7 @@
import com.android.credentialmanager.ui.components.DialogButtonsRow
import com.android.credentialmanager.ui.components.PasswordRow
import com.android.credentialmanager.ui.components.SignInHeader
+import com.android.credentialmanager.ui.model.PasswordUiModel
import com.android.credentialmanager.ui.screens.single.SingleAccountScreen
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.compose.layout.ScalingLazyColumnState
@@ -59,9 +60,8 @@
}
is SinglePasswordScreenUiState.Loaded -> {
- val model = state.passwordUiModel
SinglePasswordScreen(
- email = model.email,
+ passwordUiModel = state.passwordUiModel,
onCancelClick = viewModel::onCancelClick,
onOKClick = viewModel::onOKClick,
columnState = columnState,
@@ -98,7 +98,7 @@
@Composable
fun SinglePasswordScreen(
- email: String,
+ passwordUiModel: PasswordUiModel,
onCancelClick: () -> Unit,
onOKClick: () -> Unit,
columnState: ScalingLazyColumnState,
@@ -113,7 +113,7 @@
},
accountContent = {
PasswordRow(
- email = email,
+ email = passwordUiModel.email,
modifier = Modifier.padding(top = 10.dp),
)
},
@@ -134,7 +134,7 @@
@Composable
fun SinglePasswordScreenPreview() {
SinglePasswordScreen(
- email = "beckett_bakery@gmail.com",
+ passwordUiModel = PasswordUiModel(email = "beckett_bakery@gmail.com"),
onCancelClick = {},
onOKClick = {},
columnState = belowTimeTextPreview(),
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt
index 9b06622..3167e67 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt
@@ -17,10 +17,6 @@
package com.android.credentialmanager.ui.screens.single.password
import android.content.Intent
-import android.credentials.ui.BaseDialogResult
-import android.credentials.ui.ProviderPendingIntentResponse
-import android.credentials.ui.UserSelectionDialogResult
-import android.os.Bundle
import android.util.Log
import androidx.activity.result.IntentSenderRequest
import androidx.annotation.MainThread
@@ -30,10 +26,11 @@
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras
import com.android.credentialmanager.CredentialSelectorApp
-import com.android.credentialmanager.IS_AUTO_SELECTED_KEY
import com.android.credentialmanager.TAG
+import com.android.credentialmanager.ktx.getIntentSenderRequest
import com.android.credentialmanager.model.Password
import com.android.credentialmanager.model.Request
+import com.android.credentialmanager.repository.PasswordRepository
import com.android.credentialmanager.repository.RequestRepository
import com.android.credentialmanager.ui.model.PasswordUiModel
import kotlinx.coroutines.flow.MutableStateFlow
@@ -43,6 +40,7 @@
class SinglePasswordScreenViewModel(
private val requestRepository: RequestRepository,
+ private val passwordRepository: PasswordRepository,
) : ViewModel() {
private var initializeCalled = false
@@ -87,15 +85,8 @@
}
fun onOKClick() {
- // TODO: b/301206470 move this code to shared module
- val entryIntent = password.entry.frameworkExtrasIntent
- entryIntent?.putExtra(IS_AUTO_SELECTED_KEY, false)
- val intentSenderRequest = IntentSenderRequest.Builder(
- pendingIntent = password.passwordCredentialEntry.pendingIntent
- ).setFillInIntent(entryIntent).build()
-
_uiState.value = SinglePasswordScreenUiState.PasswordSelected(
- intentSenderRequest = intentSenderRequest
+ intentSenderRequest = password.getIntentSenderRequest()
)
}
@@ -103,25 +94,16 @@
resultCode: Int? = null,
resultData: Intent? = null,
) {
- // TODO: b/301206470 move this code to shared module
- Log.d(TAG, "credential selected: {provider=${password.providerId}" +
- ", key=${password.entry.key}, subkey=${password.entry.subkey}}")
+ viewModelScope.launch {
+ passwordRepository.selectPassword(
+ password = password,
+ request = requestGet,
+ resultCode = resultCode,
+ resultData = resultData
+ )
- val userSelectionDialogResult = UserSelectionDialogResult(
- requestGet.token,
- password.providerId,
- password.entry.key,
- password.entry.subkey,
- if (resultCode != null) ProviderPendingIntentResponse(resultCode, resultData) else null
- )
- val resultDataBundle = Bundle()
- UserSelectionDialogResult.addToBundle(userSelectionDialogResult, resultDataBundle)
- requestGet.resultReceiver?.send(
- BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION,
- resultDataBundle
- )
-
- _uiState.value = SinglePasswordScreenUiState.Completed
+ _uiState.value = SinglePasswordScreenUiState.Completed
+ }
}
companion object {
@@ -135,6 +117,7 @@
return SinglePasswordScreenViewModel(
requestRepository = (application as CredentialSelectorApp).requestRepository,
+ passwordRepository = application.passwordRepository,
) as T
}
}