1package com.peachpasswords.autofill23import android.app.PendingIntent4import android.content.Context5import android.content.Intent6import android.content.IntentSender7import android.os.Build8910111213141516object AutofillIntents {17 const val EXTRA_IDENTITY_ID = "peach.autofill.identityId"18 const val EXTRA_PASSWORD_ID = "peach.autofill.passwordId"19 const val EXTRA_OTP_ID = "peach.autofill.otpId"20 const val EXTRA_OTP_DIGIT_BOX_IDS = "peach.autofill.otpDigitBoxIds"21 const val EXTRA_ORIGIN = "peach.autofill.origin"22 const val EXTRA_IS_WEB_ORIGIN = "peach.autofill.isWebOrigin"23 24 const val EXTRA_CALLER_PACKAGE = "peach.autofill.callerPackage"2526 const val EXTRA_CARD_NUMBER_ID = "peach.autofill.cardNumberId"27 const val EXTRA_CARD_EXP_MONTH_ID = "peach.autofill.cardExpMonthId"28 const val EXTRA_CARD_EXP_YEAR_ID = "peach.autofill.cardExpYearId"29 const val EXTRA_CARD_EXP_DATE_ID = "peach.autofill.cardExpDateId"30 const val EXTRA_CARD_CVC_ID = "peach.autofill.cardCvcId"31 const val EXTRA_CARD_NAME_ID = "peach.autofill.cardNameId"3233 34 const val EXTRA_TYPED_USERNAME = "peach.autofill.typedUsername"35 36 const val EXTRA_TYPED_EMAIL = "peach.autofill.typedEmail"3738 39404142434445 const val EXTRA_OPEN_NEW_ENTRY = "peach.autofill.openNewEntry"46 const val EXTRA_NEW_ENTRY_URL = "peach.autofill.newEntryUrl"47 const val EXTRA_NEW_ENTRY_USERNAME = "peach.autofill.newEntryUsername"48 const val EXTRA_NEW_ENTRY_EMAIL = "peach.autofill.newEntryEmail"49 505152535455 const val EXTRA_NEW_ENTRY_TOKEN = "peach.autofill.newEntryToken"5657 private const val REQ_CHIP = 0xC0DE58 private const val REQ_PICKER = 0xBEEF59 private const val REQ_PICKER_CHIP = 0xBEE060 private const val REQ_NEW_ENTRY_CHIP = 0xBEE16162 @Volatile private var pendingNewEntryToken: String? = null6364 65 fun issueNewEntryToken(): String {66 val token = java.util.UUID.randomUUID().toString()67 pendingNewEntryToken = token68 return token69 }7071 72737475 fun consumeNewEntryToken(token: String?): Boolean {76 val expected = pendingNewEntryToken ?: return false77 if (token != expected) return false78 pendingNewEntryToken = null79 return true80 }8182 83 fun noopChipIntent(context: Context): PendingIntent {84 val intent = Intent(context, AutofillEntryPickerActivity::class.java)85 return PendingIntent.getActivity(context, REQ_CHIP, intent, immutableFlags())86 }8788 899091929394 fun pickerChipPendingIntent(context: Context, parsed: ParsedStructure): PendingIntent {95 val intent = Intent(context, AutofillEntryPickerActivity::class.java).apply {96 putExtra(EXTRA_IDENTITY_ID, parsed.identityId)97 putExtra(EXTRA_PASSWORD_ID, parsed.passwordId)98 putExtra(EXTRA_OTP_ID, parsed.otpId)99 putParcelableArrayListExtra(EXTRA_OTP_DIGIT_BOX_IDS, ArrayList(parsed.otpDigitBoxIds))100 putExtra(EXTRA_ORIGIN, parsed.origin)101 putExtra(EXTRA_IS_WEB_ORIGIN, parsed.webDomain != null)102 putExtra(EXTRA_CALLER_PACKAGE, parsed.packageName)103 putExtra(EXTRA_CARD_NUMBER_ID, parsed.cardNumberId)104 putExtra(EXTRA_CARD_EXP_MONTH_ID, parsed.cardExpMonthId)105 putExtra(EXTRA_CARD_EXP_YEAR_ID, parsed.cardExpYearId)106 putExtra(EXTRA_CARD_EXP_DATE_ID, parsed.cardExpDateId)107 putExtra(EXTRA_CARD_CVC_ID, parsed.cardCvcId)108 putExtra(EXTRA_CARD_NAME_ID, parsed.cardNameId)109 parsed.usernameValue?.trim()?.takeIf { it.isNotBlank() }?.let {110 putExtra(EXTRA_TYPED_USERNAME, it)111 }112 parsed.emailValue?.trim()?.takeIf { it.isNotBlank() }?.let {113 putExtra(EXTRA_TYPED_EMAIL, it)114 }115 }116 return PendingIntent.getActivity(context, REQ_PICKER_CHIP, intent, immutableFlags())117 }118119 120121122123124125126 fun newEntryChipPendingIntent(127 context: Context,128 parsed: ParsedStructure,129 origin: String?,130 ): PendingIntent {131 val intent = Intent(context, com.peachpasswords.MainActivity::class.java).apply {132 addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)133 putExtra(EXTRA_OPEN_NEW_ENTRY, true)134 putExtra(EXTRA_NEW_ENTRY_TOKEN, issueNewEntryToken())135 origin?.takeIf { it.isNotBlank() }?.let { putExtra(EXTRA_NEW_ENTRY_URL, it) }136 parsed.usernameValue?.trim()?.takeIf { it.isNotBlank() }?.let {137 putExtra(EXTRA_NEW_ENTRY_USERNAME, it)138 }139 parsed.emailValue?.trim()?.takeIf { it.isNotBlank() }?.let {140 putExtra(EXTRA_NEW_ENTRY_EMAIL, it)141 }142 }143 return PendingIntent.getActivity(context, REQ_NEW_ENTRY_CHIP, intent, immutableFlags())144 }145146 147 fun pickerIntentSender(context: Context, parsed: ParsedStructure): IntentSender {148 val intent = Intent(context, AutofillEntryPickerActivity::class.java).apply {149 putExtra(EXTRA_IDENTITY_ID, parsed.identityId)150 putExtra(EXTRA_PASSWORD_ID, parsed.passwordId)151 putExtra(EXTRA_OTP_ID, parsed.otpId)152 putParcelableArrayListExtra(EXTRA_OTP_DIGIT_BOX_IDS, ArrayList(parsed.otpDigitBoxIds))153 putExtra(EXTRA_ORIGIN, parsed.origin)154 putExtra(EXTRA_IS_WEB_ORIGIN, parsed.webDomain != null)155 156 157 putExtra(EXTRA_CALLER_PACKAGE, parsed.packageName)158 putExtra(EXTRA_CARD_NUMBER_ID, parsed.cardNumberId)159 putExtra(EXTRA_CARD_EXP_MONTH_ID, parsed.cardExpMonthId)160 putExtra(EXTRA_CARD_EXP_YEAR_ID, parsed.cardExpYearId)161 putExtra(EXTRA_CARD_EXP_DATE_ID, parsed.cardExpDateId)162 putExtra(EXTRA_CARD_CVC_ID, parsed.cardCvcId)163 putExtra(EXTRA_CARD_NAME_ID, parsed.cardNameId)164 165 166 167 168 parsed.usernameValue?.trim()?.takeIf { it.isNotBlank() }?.let {169 putExtra(EXTRA_TYPED_USERNAME, it)170 }171 parsed.emailValue?.trim()?.takeIf { it.isNotBlank() }?.let {172 putExtra(EXTRA_TYPED_EMAIL, it)173 }174 }175 176 177 178 return PendingIntent.getActivity(context, REQ_PICKER, intent, immutableFlags()).intentSender179 }180181 private fun immutableFlags(): Int =182 PendingIntent.FLAG_UPDATE_CURRENT or183 if (Build.VERSION.SDK_INT >= 23) PendingIntent.FLAG_IMMUTABLE else 0184185}