Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a0a0995 authored by Qinmei Du's avatar Qinmei Du
Browse files

Update the structure of createOptionInfo as EntryInfo, change the

structure of ProviderInfo

Test: deployed locally

Bug: 253157211
Change-Id: I68de6868cd263d4b1da858e2bce9622e970abe0b
parent 89b3a6b4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
        android:viewportWidth="46"
        android:viewportHeight="46"
        android:width="46dp"
        android:height="46dp">
    <path
        android:pathData="M45.4247 22.9953C45.4247 35.0229 35.4133 44.7953 23.0359 44.7953C10.6585 44.7953 0.646973 35.0229 0.646973 22.9953C0.646973 10.9677 10.6585 1.19531 23.0359 1.19531C35.4133 1.19531 45.4247 10.9677 45.4247 22.9953Z"
        android:strokeColor="#202124"
        android:strokeAlpha="0.13"
        android:strokeWidth="1" />
</vector>
 No newline at end of file
+5 −0
Original line number Diff line number Diff line
@@ -22,4 +22,9 @@
  <string name="choose_create_option_description">You can use saved <xliff:g id="type">%1$s</xliff:g> on any device. It will be saved to <xliff:g id="providerInfoDisplayName">%2$s</xliff:g> for <xliff:g id="createInfoDisplayName">%3$s</xliff:g></string>
  <string name="more_options_title_multiple_options"><xliff:g id="providerInfoDisplayName">%1$s</xliff:g> for <xliff:g id="createInfoTitle">%2$s</xliff:g></string>
  <string name="more_options_title_one_option"><xliff:g id="providerInfoDisplayName">%1$s</xliff:g></string>
  <string name="more_options_usage_data"><xliff:g id="passwordsNumber">%1$s</xliff:g> passwords and <xliff:g id="passkeyssNumber">%2$s</xliff:g> passkeys saved</string>
  <string name="passkeys">passkeys</string>
  <string name="passwords">passwords</string>
  <string name="sign_ins">sign-ins</string>
  <string name="createOptionInfo_icon_description">CreateOptionInfo credentialType icon</string>
</resources>
 No newline at end of file
+53 −31
Original line number Diff line number Diff line
@@ -33,8 +33,10 @@ import android.graphics.drawable.Icon
import android.os.Binder
import android.os.Bundle
import android.os.ResultReceiver
import com.android.credentialmanager.createflow.ActiveEntry
import com.android.credentialmanager.createflow.CreatePasskeyUiState
import com.android.credentialmanager.createflow.CreateScreenState
import com.android.credentialmanager.createflow.ProviderInfo
import com.android.credentialmanager.createflow.RequestDisplayInfo
import com.android.credentialmanager.getflow.GetCredentialUiState
import com.android.credentialmanager.getflow.GetScreenState
@@ -119,6 +121,10 @@ class CredentialManagerRepo(
    val providerList = CreateFlowUtils.toProviderList(
      // Handle runtime cast error
      providerList as List<CreateCredentialProviderData>, context)
    var hasDefault = false
    var defaultProvider: ProviderInfo = providerList.first()
    providerList.forEach{providerInfo ->
      if (providerInfo.isDefault) {hasDefault = true; defaultProvider = providerInfo} }
    // TODO: covert from real requestInfo
    val requestDisplayInfo = RequestDisplayInfo(
      "Elisa Beckett",
@@ -127,8 +133,12 @@ class CredentialManagerRepo(
      "tribank")
    return CreatePasskeyUiState(
      providers = providerList,
      currentScreenState = CreateScreenState.PASSKEY_INTRO,
      if (hasDefault)
      {CreateScreenState.CREATION_OPTION_SELECTION} else {CreateScreenState.PASSKEY_INTRO},
      requestDisplayInfo,
      if (hasDefault) {
        ActiveEntry(defaultProvider, defaultProvider.createOptions.first())
      } else null
    )
  }

@@ -150,38 +160,39 @@ class CredentialManagerRepo(
  // TODO: below are prototype functionalities. To be removed for productionization.
  private fun testCreateCredentialProviderList(): List<CreateCredentialProviderData> {
    return listOf(
      CreateCredentialProviderData.Builder("com.google/com.google.CredentialManagerService")
      CreateCredentialProviderData
        .Builder("com.google/com.google.CredentialManagerService")
        .setSaveEntries(
          listOf<Entry>(
            newEntry("key1", "subkey-1", "elisa.beckett@gmail.com",
              "Elisa Backett", "20 passwords and 7 passkeys saved"),
              20, 7, 27, 10000),
            newEntry("key1", "subkey-2", "elisa.work@google.com",
              "Elisa Backett Work", "20 passwords and 7 passkeys saved"),
              20, 7, 27, 11000),
          )
        )
        .setActionChips(
          listOf<Entry>(
            newEntry("key2", "subkey-1", "Go to Settings", "",
                     "20 passwords and 7 passkeys saved"),
            newEntry("key2", "subkey-2", "Switch Account", "",
                     "20 passwords and 7 passkeys saved"),
            newEntry("key2", "subkey-1", "Go to Settings",
              20, 7, 27, 20000),
            newEntry("key2", "subkey-2", "Switch Account",
              20, 7, 27, 21000),
          ),
        )
        .setIsDefaultProvider(true)
        .setIsDefaultProvider(false)
        .build(),
      CreateCredentialProviderData.Builder("com.dashlane/com.dashlane.CredentialManagerService")
      CreateCredentialProviderData
        .Builder("com.dashlane/com.dashlane.CredentialManagerService")
        .setSaveEntries(
          listOf<Entry>(
            newEntry("key1", "subkey-3", "elisa.beckett@dashlane.com",
              "Elisa Backett", "20 passwords and 7 passkeys saved"),
              20, 7, 27, 30000),
            newEntry("key1", "subkey-4", "elisa.work@dashlane.com",
              "Elisa Backett Work", "20 passwords and 7 passkeys saved"),
              20, 7, 27, 31000),
          )
        ).setActionChips(
          listOf<Entry>(
            newEntry("key2", "subkey-3", "Manage Accounts",
              "Manage your accounts in the dashlane app",
                     "20 passwords and 7 passkeys saved"),
              20, 7, 27, 32000),
          ),
        ).build(),
    )
@@ -193,31 +204,30 @@ class CredentialManagerRepo(
        .setCredentialEntries(
          listOf<Entry>(
            newEntry("key1", "subkey-1", "elisa.beckett@gmail.com",
              "Elisa Backett", "20 passwords and 7 passkeys saved"),
              20, 7, 27, 10000),
            newEntry("key1", "subkey-2", "elisa.work@google.com",
              "Elisa Backett Work", "20 passwords and 7 passkeys saved"),
              20, 7, 27, 11000),
          )
        ).setActionChips(
          listOf<Entry>(
            newEntry("key2", "subkey-1", "Go to Settings", "",
              "20 passwords and 7 passkeys saved"),
            newEntry("key2", "subkey-2", "Switch Account", "",
              "20 passwords and 7 passkeys saved"),
            newEntry("key2", "subkey-1", "Go to Settings",
              20, 7, 27, 20000),
            newEntry("key2", "subkey-2", "Switch Account",
              20, 7, 27, 21000),
          ),
        ).build(),
      GetCredentialProviderData.Builder("com.dashlane/com.dashlane.CredentialManagerService")
        .setCredentialEntries(
          listOf<Entry>(
            newEntry("key1", "subkey-3", "elisa.beckett@dashlane.com",
              "Elisa Backett", "20 passwords and 7 passkeys saved"),
              20, 7, 27, 30000),
            newEntry("key1", "subkey-4", "elisa.work@dashlane.com",
              "Elisa Backett Work", "20 passwords and 7 passkeys saved"),
              20, 7, 27, 31000),
          )
        ).setActionChips(
          listOf<Entry>(
            newEntry("key2", "subkey-3", "Manage Accounts",
              "Manage your accounts in the dashlane app",
              "20 passwords and 7 passkeys saved"),
              20, 7, 27, 40000),
          ),
        ).build(),
    )
@@ -226,20 +236,32 @@ class CredentialManagerRepo(
  private fun newEntry(
    key: String,
    subkey: String,
    title: String,
    subtitle: String,
    usageData: String
    providerDisplayName: String,
    passwordCount: Int,
    passkeyCount: Int,
    totalCredentialCount: Int,
    lastUsedTimeMillis: Long,
  ): Entry {
    val slice = Slice.Builder(
      Entry.CREDENTIAL_MANAGER_ENTRY_URI, SliceSpec(Entry.VERSION, 1)
    )
      .addText(title, null, listOf(Entry.HINT_TITLE))
      .addText(subtitle, null, listOf(Entry.HINT_SUBTITLE))
      .addText(
        providerDisplayName, null, listOf(Entry.HINT_USER_PROVIDER_ACCOUNT_NAME))
      .addIcon(
        Icon.createWithResource(context, R.drawable.ic_passkey),
        null,
        listOf(Entry.HINT_ICON))
      .addText(usageData, Slice.SUBTYPE_MESSAGE, listOf(Entry.HINT_SUBTITLE))
        listOf(Entry.HINT_CREDENTIAL_TYPE_ICON))
      .addIcon(
        Icon.createWithResource(context, R.drawable.ic_profile),
        null,
        listOf(Entry.HINT_PROFILE_ICON))
      .addInt(
        passwordCount, null, listOf(Entry.HINT_PASSWORD_COUNT))
      .addInt(
        passkeyCount, null, listOf(Entry.HINT_PASSKEY_COUNT))
      .addInt(
        totalCredentialCount, null, listOf(Entry.HINT_TOTAL_CREDENTIAL_COUNT))
      .addLong(lastUsedTimeMillis, null, listOf(Entry.HINT_LAST_USED_TIME_MILLIS))
      .build()
    return Entry(
      key,
+10 −9
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.credentials.ui.CreateCredentialProviderData
import com.android.credentialmanager.createflow.CreateOptionInfo
import com.android.credentialmanager.getflow.CredentialOptionInfo
import com.android.credentialmanager.getflow.ProviderInfo
import com.android.credentialmanager.jetpack.provider.SaveEntryUi

/** Utility functions for converting CredentialManager data structures to or from UI formats. */
class GetFlowUtils {
@@ -59,8 +60,6 @@ class GetFlowUtils {
          // TODO: remove fallbacks
          icon = credentialEntryUi.icon?.loadDrawable(context)
            ?: context.getDrawable(R.drawable.ic_passkey)!!,
          title = credentialEntryUi.userName.toString(),
          subtitle = credentialEntryUi.displayName?.toString() ?: "Unknown display name",
          entryKey = it.key,
          entrySubkey = it.subkey,
          usageData = credentialEntryUi.usageData?.toString() ?: "Unknown usageData",
@@ -82,9 +81,7 @@ class CreateFlowUtils {
          // TODO: replace to extract from the service data structure when available
          icon = context.getDrawable(R.drawable.ic_passkey)!!,
          name = it.providerFlattenedComponentName,
          // TODO: get the service display name and icon from the component name.
          displayName = it.providerFlattenedComponentName,
          credentialTypeIcon = context.getDrawable(R.drawable.ic_passkey)!!,
          createOptions = toCreationOptionInfoList(it.saveEntries, context),
          isDefault = it.isDefaultProvider,
        )
@@ -100,13 +97,17 @@ class CreateFlowUtils {

        return@map CreateOptionInfo(
          // TODO: remove fallbacks
          icon = saveEntryUi.icon?.loadDrawable(context)
            ?: context.getDrawable(R.drawable.ic_passkey)!!,
          title = saveEntryUi.title.toString(),
          subtitle = saveEntryUi.subTitle?.toString() ?: "Unknown subtitle",
          entryKey = it.key,
          entrySubkey = it.subkey,
          usageData = saveEntryUi.usageData?.toString() ?: "Unknown usageData",
          userProviderDisplayName = saveEntryUi.userProviderAccountName as String,
          credentialTypeIcon = saveEntryUi.credentialTypeIcon?.loadDrawable(context)
            ?: context.getDrawable(R.drawable.ic_passkey)!!,
          profileIcon = saveEntryUi.profileIcon?.loadDrawable(context)
            ?: context.getDrawable(R.drawable.ic_profile)!!,
          passwordCount = saveEntryUi.passwordCount ?: 0,
          passkeyCount = saveEntryUi.passkeyCount ?: 0,
          totalCredentialCount = saveEntryUi.totalCredentialCount ?: 0,
          lastUsedTimeMillis = saveEntryUi.lastUsedTimeMillis ?: 0,
        )
      }
    }
+0 −59
Original line number Diff line number Diff line
/*
 * Copyright (C) 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 com.android.credentialmanager

import android.app.slice.Slice
import android.credentials.ui.Entry
import android.graphics.drawable.Icon

/**
 * UI representation for a save entry used during the create credential flow.
 *
 * TODO: move to jetpack.
 */
class SaveEntryUi(
  val title: CharSequence,
  val subTitle: CharSequence?,
  val icon: Icon?,
  val usageData: CharSequence?,
  // TODO: add
) {
  companion object {
    fun fromSlice(slice: Slice): SaveEntryUi {
      val items = slice.items

      var title: String? = null
      var subTitle: String? = null
      var icon: Icon? = null
      var usageData: String? = null

      items.forEach {
        if (it.hasHint(Entry.HINT_ICON)) {
          icon = it.icon
        } else if (it.hasHint(Entry.HINT_SUBTITLE) && it.subType == null) {
          subTitle = it.text.toString()
        } else if (it.hasHint(Entry.HINT_TITLE)) {
          title = it.text.toString()
        } else if (it.hasHint(Entry.HINT_SUBTITLE) && it.subType == Slice.SUBTYPE_MESSAGE) {
          usageData = it.text.toString()
        }
      }
      // TODO: fail NPE more elegantly.
      return SaveEntryUi(title!!, subTitle, icon, usageData)
    }
  }
}
Loading