aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillPublisherChangedActivity.kt
blob: e37ebf5e7d410368f6170503a42017805dd0057f (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
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * Copyright © 2014-2021 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.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.asLog
import dev.msfjarvis.aps.util.extensions.viewBinding
import logcat.LogPriority.ERROR
import logcat.logcat

@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 {
          logcat(ERROR) { "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 ->
        logcat(ERROR) { e.asLog("Failed to retrieve package info for $appPackage") }
        finish()
      }
  }
}