aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillPublisherChangedActivity.kt
blob: d18d61a5777a0e6eda6715404ff3fe1f16fb937e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
 * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
 * SPDX-License-Identifier: GPL-3.0-only
 */
package dev.msfjarvis.aps.ui.autofill

import android.annotation.TargetApi
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentSender
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.service.autofill.FillResponse
import android.text.format.DateUtils
import android.view.View
import android.view.autofill.AutofillManager
import androidx.appcompat.app.AppCompatActivity
import com.github.ajalt.timberkt.e
import com.github.androidpasswordstore.autofillparser.FormOrigin
import com.github.androidpasswordstore.autofillparser.computeCertificatesHash
import com.github.michaelbull.result.onFailure
import com.github.michaelbull.result.runCatching
import dev.msfjarvis.aps.R
import dev.msfjarvis.aps.databinding.ActivityOreoAutofillPublisherChangedBinding
import dev.msfjarvis.aps.util.autofill.AutofillMatcher
import dev.msfjarvis.aps.util.autofill.AutofillPublisherChangedException
import dev.msfjarvis.aps.util.extensions.viewBinding

@TargetApi(Build.VERSION_CODES.O)
class AutofillPublisherChangedActivity : AppCompatActivity() {

    companion object {

        private const val EXTRA_APP_PACKAGE =
            "dev.msfjarvis.aps.autofill.oreo.ui.EXTRA_APP_PACKAGE"
        private const val EXTRA_FILL_RESPONSE_AFTER_RESET =
            "dev.msfjarvis.aps.autofill.oreo.ui.EXTRA_FILL_RESPONSE_AFTER_RESET"
        private var publisherChangedRequestCode = 1

        fun makePublisherChangedIntentSender(
            context: Context,
            publisherChangedException: AutofillPublisherChangedException,
            fillResponseAfterReset: FillResponse?,
        ): IntentSender {
            val intent = Intent(context, AutofillPublisherChangedActivity::class.java).apply {
                putExtra(EXTRA_APP_PACKAGE, publisherChangedException.formOrigin.identifier)
                putExtra(EXTRA_FILL_RESPONSE_AFTER_RESET, fillResponseAfterReset)
            }
            return PendingIntent.getActivity(
                context, publisherChangedRequestCode++, intent, PendingIntent.FLAG_CANCEL_CURRENT
            ).intentSender
        }
    }

    private lateinit var appPackage: String
    private val binding by viewBinding(ActivityOreoAutofillPublisherChangedBinding::inflate)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        setFinishOnTouchOutside(true)

        appPackage = intent.getStringExtra(EXTRA_APP_PACKAGE) ?: run {
            e { "AutofillPublisherChangedActivity started without EXTRA_PACKAGE_NAME" }
            finish()
            return
        }
        supportActionBar?.hide()
        showPackageInfo()
        with(binding) {
            okButton.setOnClickListener { finish() }
            advancedButton.setOnClickListener {
                advancedButton.visibility = View.GONE
                warningAppAdvancedInfo.visibility = View.VISIBLE
                resetButton.visibility = View.VISIBLE
            }
            resetButton.setOnClickListener {
                AutofillMatcher.clearMatchesFor(this@AutofillPublisherChangedActivity, FormOrigin.App(appPackage))
                val fillResponse = intent.getParcelableExtra<FillResponse>(EXTRA_FILL_RESPONSE_AFTER_RESET)
                setResult(RESULT_OK, Intent().apply {
                    putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, fillResponse)
                })
                finish()
            }
        }
    }

    private fun showPackageInfo() {
        runCatching {
            with(binding) {
                val packageInfo =
                    packageManager.getPackageInfo(appPackage, PackageManager.GET_META_DATA)
                val installTime = DateUtils.getRelativeTimeSpanString(packageInfo.firstInstallTime)
                warningAppInstallDate.text =
                    getString(R.string.oreo_autofill_warning_publisher_install_time, installTime)
                val appInfo =
                    packageManager.getApplicationInfo(appPackage, PackageManager.GET_META_DATA)
                warningAppName.text = "“${packageManager.getApplicationLabel(appInfo)}”"

                val currentHash = computeCertificatesHash(this@AutofillPublisherChangedActivity, appPackage)
                warningAppAdvancedInfo.text = getString(
                    R.string.oreo_autofill_warning_publisher_advanced_info_template,
                    appPackage,
                    currentHash
                )
            }
        }.onFailure { e ->
            e(e) { "Failed to retrieve package info for $appPackage" }
            finish()
        }
    }
}