diff options
Diffstat (limited to 'app/src/main')
7 files changed, 105 insertions, 2 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2098abc9..40bcb481 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -139,6 +139,11 @@ android:name=".autofill.oreo.ui.AutofillSaveActivity" android:theme="@style/NoBackgroundTheme" /> <activity + android:name=".autofill.oreo.ui.AutofillSmsActivity" + android:configChanges="orientation" + android:theme="@style/DialogLikeTheme" + android:windowSoftInputMode="adjustNothing" /> + <activity android:name=".autofill.oreo.ui.AutofillPublisherChangedActivity" android:configChanges="orientation|keyboardHidden" android:theme="@style/DialogLikeTheme" diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/AutofillHelper.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/AutofillHelper.kt index 838b7a05..e9b2c630 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/AutofillHelper.kt +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/AutofillHelper.kt @@ -87,7 +87,7 @@ val AssistStructure.ViewNode.webOrigin: String? "$scheme://$domain" } -data class Credentials(val username: String?, val password: String, val otp: String?) { +data class Credentials(val username: String?, val password: String?, val otp: String?) { companion object { fun fromStoreEntry( context: Context, @@ -141,6 +141,13 @@ fun makeGenerateAndFillRemoteView(context: Context, formOrigin: FormOrigin): Rem return makeRemoteView(context, title, summary, iconRes) } +fun makeFillOtpFromSmsRemoteView(context: Context, formOrigin: FormOrigin): RemoteViews { + val title = formOrigin.getPrettyIdentifier(context, untrusted = true) + val summary = context.getString(R.string.oreo_autofill_fill_otp_from_sms) + val iconRes = R.drawable.ic_autofill_sms + return makeRemoteView(context, title, summary, iconRes) +} + fun makePlaceholderRemoteView(context: Context): RemoteViews { return makeRemoteView(context, "PLACEHOLDER", "PLACEHOLDER", R.mipmap.ic_launcher) } diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/AutofillScenario.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/AutofillScenario.kt index 8e209a60..ee8e3602 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/AutofillScenario.kt +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/AutofillScenario.kt @@ -14,7 +14,7 @@ import androidx.annotation.RequiresApi import com.github.ajalt.timberkt.e enum class AutofillAction { - Match, Search, Generate + Match, Search, Generate, FillOtpFromSms } /** @@ -112,8 +112,13 @@ sealed class AutofillScenario<out T : Any> { AutofillAction.Match -> passwordFieldsToFillOnMatch + listOfNotNull(otp) AutofillAction.Search -> passwordFieldsToFillOnSearch + listOfNotNull(otp) AutofillAction.Generate -> passwordFieldsToFillOnGenerate + AutofillAction.FillOtpFromSms -> listOfNotNull(otp) } return when { + action == AutofillAction.FillOtpFromSms -> { + // When filling from an SMS, we cannot get any data other than the OTP itself. + credentialFieldsToFill + } credentialFieldsToFill.isNotEmpty() -> { // If the current action would fill into any password field, we also fill into the // username field if possible. diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/Form.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/Form.kt index 210fefab..e4ae1f75 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/Form.kt +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/Form.kt @@ -25,6 +25,7 @@ import com.zeapo.pwdstore.autofill.oreo.ui.AutofillDecryptActivity import com.zeapo.pwdstore.autofill.oreo.ui.AutofillFilterView import com.zeapo.pwdstore.autofill.oreo.ui.AutofillPublisherChangedActivity import com.zeapo.pwdstore.autofill.oreo.ui.AutofillSaveActivity +import com.zeapo.pwdstore.autofill.oreo.ui.AutofillSmsActivity import java.io.File /** @@ -285,6 +286,14 @@ class FillableForm private constructor( return makePlaceholderDataset(remoteView, intentSender, AutofillAction.Generate) } + private fun makeFillOtpFromSmsDataset(context: Context): Dataset? { + if (scenario.fieldsToFillOn(AutofillAction.FillOtpFromSms).isEmpty()) return null + if (!AutofillSmsActivity.shouldOfferFillFromSms(context)) return null + val remoteView = makeFillOtpFromSmsRemoteView(context, formOrigin) + val intentSender = AutofillSmsActivity.makeFillOtpFromSmsIntentSender(context) + return makePlaceholderDataset(remoteView, intentSender, AutofillAction.FillOtpFromSms) + } + private fun makePublisherChangedDataset( context: Context, publisherChangedException: AutofillPublisherChangedException @@ -341,6 +350,10 @@ class FillableForm private constructor( hasDataset = true addDataset(it) } + makeFillOtpFromSmsDataset(context)?.let { + hasDataset = true + addDataset(it) + } if (!hasDataset) return null makeSaveInfo()?.let { setSaveInfo(it) } setClientState(clientState) diff --git a/app/src/main/res/drawable/ic_autofill_sms.xml b/app/src/main/res/drawable/ic_autofill_sms.xml new file mode 100644 index 00000000..e58c33c4 --- /dev/null +++ b/app/src/main/res/drawable/ic_autofill_sms.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorControlNormal" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM9,11L7,11L7,9h2v2zM13,11h-2L11,9h2v2zM17,11h-2L15,9h2v2z" /> +</vector> diff --git a/app/src/main/res/layout/activity_oreo_autofill_sms.xml b/app/src/main/res/layout/activity_oreo_autofill_sms.xml new file mode 100644 index 00000000..608727d0 --- /dev/null +++ b/app/src/main/res/layout/activity_oreo_autofill_sms.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. + ~ SPDX-License-Identifier: GPL-3.0-only + --> + +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingHorizontal="10dp" + tools:context="com.zeapo.pwdstore.autofill.oreo.ui.AutofillFilterView"> + + <ImageView + android:id="@+id/cover" + android:layout_width="0dp" + android:layout_height="50dp" + android:contentDescription="@string/app_name" + android:src="@drawable/ic_launcher_foreground" + app:layout_constraintBottom_toTopOf="@id/text" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + android:layout_margin="10dp" + app:layout_constraintVertical_bias="0.0" /> + + <TextView + android:id="@+id/text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/oreo_autofill_waiting_for_sms" + android:layout_margin="10dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/cover" /> + + <ProgressBar + android:id="@+id/progress" + style="@style/Widget.MaterialComponents.ProgressIndicator.Circular.Indeterminate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="10dp" + app:layout_constraintBottom_toTopOf="@id/cancelButton" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/text" /> + + <Button + android:id="@+id/cancelButton" + style="@style/Widget.MaterialComponents.Button.TextButton" + android:layout_margin="10dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/dialog_cancel" + android:textColor="?attr/colorSecondary" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/progress" /> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3023d995..6d06a7a4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -253,6 +253,8 @@ <string name="oreo_autofill_save_app_not_supported">This app is currently not supported</string> <string name="oreo_autofill_save_passwords_dont_match">Passwords don\'t match</string> <string name="oreo_autofill_generate_password">Generate password…</string> + <string name="oreo_autofill_fill_otp_from_sms">Extract code from SMS…</string> + <string name="oreo_autofill_waiting_for_sms">Waiting for SMS…</string> <string name="oreo_autofill_max_matches_reached">Maximum number of matches (%1$d) reached; clear matches before adding new ones.</string> <string name="oreo_autofill_warning_publisher_header">This app\'s publisher has changed since you first associated a Password Store entry with it:</string> <string name="oreo_autofill_warning_publisher_footer"><b>The currently installed app may be trying to steal your credentials by pretending to be a trusted app.</b>\n\nTry to uninstall and reinstall the app from a trusted source, such as the Play Store, Amazon Appstore, F-Droid, or your phone manufacturer\'s store.</string> |