diff --git a/common/src/abn/java/ch/admin/bag/covidcertificate/common/debug/DebugFragment.kt b/common/src/abn/java/ch/admin/bag/covidcertificate/common/debug/DebugFragment.kt new file mode 100644 index 00000000..84e98dad --- /dev/null +++ b/common/src/abn/java/ch/admin/bag/covidcertificate/common/debug/DebugFragment.kt @@ -0,0 +1,25 @@ +package ch.admin.bag.covidcertificate.common.debug +/* + * Copyright (c) 2021 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +import android.content.Context +import androidx.fragment.app.Fragment + +open class DebugFragment : Fragment() { + + companion object { + fun newInstance(): DebugFragment = DebugFragment() + + const val EXISTS = false + + fun initDebug(context: Context) {} + } + +} \ No newline at end of file diff --git a/common/src/dev/java/ch/admin/bag/covidcertificate/common/debug/DebugFragment.kt b/common/src/dev/java/ch/admin/bag/covidcertificate/common/debug/DebugFragment.kt new file mode 100644 index 00000000..35fae3c0 --- /dev/null +++ b/common/src/dev/java/ch/admin/bag/covidcertificate/common/debug/DebugFragment.kt @@ -0,0 +1,67 @@ +package ch.admin.bag.covidcertificate.common.debug +/* + * Copyright (c) 2021 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import ch.admin.bag.covidcertificate.common.databinding.FragmentDebugBinding +import ch.admin.bag.covidcertificate.sdk.android.net.CertificatePinning + +open class DebugFragment : Fragment() { + + companion object { + fun newInstance(): DebugFragment = DebugFragment() + + const val EXISTS = true + + fun initDebug(context: Context) { + CertificatePinning.enabled = DebugSecureStorage.getInstance(context).isCertPinningEnabled + } + } + + private var _binding: FragmentDebugBinding? = null + protected val binding get() = _binding!! + + private lateinit var debugSecureStorage: DebugSecureStorage + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + debugSecureStorage = DebugSecureStorage.getInstance(requireContext()) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + _binding = FragmentDebugBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + binding.toolbar.setNavigationOnClickListener { + parentFragmentManager.popBackStack() + } + + binding.buttonToggleCertificatePinning.apply { + isChecked = debugSecureStorage.isCertPinningEnabled + + setOnCheckedChangeListener { _, isChecked -> + debugSecureStorage.isCertPinningEnabled = isChecked + CertificatePinning.enabled = isChecked + } + } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} \ No newline at end of file diff --git a/common/src/dev/java/ch/admin/bag/covidcertificate/common/debug/DebugSecureStorage.kt b/common/src/dev/java/ch/admin/bag/covidcertificate/common/debug/DebugSecureStorage.kt new file mode 100644 index 00000000..6f2fca42 --- /dev/null +++ b/common/src/dev/java/ch/admin/bag/covidcertificate/common/debug/DebugSecureStorage.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +package ch.admin.bag.covidcertificate.common.debug + +import android.content.Context +import ch.admin.bag.covidcertificate.sdk.android.net.CertificatePinning +import ch.admin.bag.covidcertificate.sdk.android.utils.EncryptedSharedPreferencesUtil +import ch.admin.bag.covidcertificate.sdk.android.utils.SingletonHolder + +class DebugSecureStorage private constructor(context: Context) { + + companion object : SingletonHolder(::DebugSecureStorage) { + private const val PREFERENCES = "DebugSecureStorage" + private const val KEY_CERT_PINNING_ENABLED = "KEY_CERT_PINNING_ENABLED" + } + + private val prefs = EncryptedSharedPreferencesUtil.initializeSharedPreferences(context, PREFERENCES) + + var isCertPinningEnabled: Boolean + get() = prefs.getBoolean(KEY_CERT_PINNING_ENABLED, CertificatePinning.enabled) + set(value) = prefs.edit().putBoolean(KEY_CERT_PINNING_ENABLED, value).apply() + +} \ No newline at end of file diff --git a/wallet/src/main/res/layout/fragment_debug.xml b/common/src/main/res/layout/fragment_debug.xml similarity index 86% rename from wallet/src/main/res/layout/fragment_debug.xml rename to common/src/main/res/layout/fragment_debug.xml index a7d86fb7..f258f62c 100644 --- a/wallet/src/main/res/layout/fragment_debug.xml +++ b/common/src/main/res/layout/fragment_debug.xml @@ -32,6 +32,13 @@ app:titleTextAppearance="@style/CovidCertificate.ToolbarTitle" app:titleTextColor="@color/grey" /> + + + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +import android.content.Context +import androidx.fragment.app.Fragment + +open class DebugFragment : Fragment() { + + companion object { + fun newInstance(): DebugFragment = DebugFragment() + + const val EXISTS = false + + fun initDebug(context: Context) {} + } + +} \ No newline at end of file diff --git a/verifier/src/main/java/ch/admin/bag/covidcertificate/verifier/HomeFragment.kt b/verifier/src/main/java/ch/admin/bag/covidcertificate/verifier/HomeFragment.kt index 66824196..f9ae86f6 100644 --- a/verifier/src/main/java/ch/admin/bag/covidcertificate/verifier/HomeFragment.kt +++ b/verifier/src/main/java/ch/admin/bag/covidcertificate/verifier/HomeFragment.kt @@ -20,16 +20,17 @@ import androidx.fragment.app.activityViewModels import ch.admin.bag.covidcertificate.common.config.ConfigViewModel import ch.admin.bag.covidcertificate.common.config.InfoBoxModel import ch.admin.bag.covidcertificate.common.data.ConfigSecureStorage +import ch.admin.bag.covidcertificate.common.debug.DebugFragment import ch.admin.bag.covidcertificate.common.dialog.InfoDialogFragment import ch.admin.bag.covidcertificate.common.html.BuildInfo import ch.admin.bag.covidcertificate.common.html.ImprintFragment -import ch.admin.bag.covidcertificate.common.util.AssetUtil import ch.admin.bag.covidcertificate.verifier.databinding.FragmentHomeBinding import ch.admin.bag.covidcertificate.verifier.faq.VerifierFaqFragment import ch.admin.bag.covidcertificate.verifier.pager.HomescreenPageAdapter import ch.admin.bag.covidcertificate.verifier.pager.HomescreenPagerFragment import ch.admin.bag.covidcertificate.verifier.qr.VerifierQrScanFragment import com.google.android.material.tabs.TabLayoutMediator +import java.util.concurrent.atomic.AtomicLong class HomeFragment : Fragment() { @@ -74,6 +75,10 @@ class HomeFragment : Fragment() { //Some implementation }.attach() + if (DebugFragment.EXISTS) { + setupDebugFragment() + } + binding.homescreenHeader.headerImpressum.setOnClickListener { val buildInfo = BuildInfo( getString(R.string.verifier_app_title), @@ -103,6 +108,24 @@ class HomeFragment : Fragment() { _binding = null } + private fun setupDebugFragment() { + val lastClick = AtomicLong(0) + val debugButtonClickListener = View.OnClickListener { + val now = System.currentTimeMillis() + if (lastClick.get() > now - 1000L) { + lastClick.set(0) + parentFragmentManager.beginTransaction() + .setCustomAnimations(R.anim.slide_enter, R.anim.slide_exit, R.anim.slide_pop_enter, R.anim.slide_pop_exit) + .replace(R.id.fragment_container, DebugFragment.newInstance()) + .addToBackStack(DebugFragment::class.java.canonicalName) + .commit() + } else { + lastClick.set(now) + } + } + binding.homescreenHeader.schwiizerchruez.setOnClickListener(debugButtonClickListener) + } + private fun setupInfoBox() { configViewModel.configLiveData.observe(viewLifecycleOwner) { config -> val notificationButton = binding.homescreenHeader.headerNotification diff --git a/verifier/src/main/java/ch/admin/bag/covidcertificate/verifier/MainApplication.kt b/verifier/src/main/java/ch/admin/bag/covidcertificate/verifier/MainApplication.kt index 4c3286a8..881c45d2 100644 --- a/verifier/src/main/java/ch/admin/bag/covidcertificate/verifier/MainApplication.kt +++ b/verifier/src/main/java/ch/admin/bag/covidcertificate/verifier/MainApplication.kt @@ -3,6 +3,7 @@ package ch.admin.bag.covidcertificate.verifier import android.app.Application import android.os.Build import ch.admin.bag.covidcertificate.common.data.ConfigSecureStorage +import ch.admin.bag.covidcertificate.common.debug.DebugFragment import ch.admin.bag.covidcertificate.common.util.EnvironmentUtil import ch.admin.bag.covidcertificate.sdk.android.CovidCertificateSdk import ch.admin.bag.covidcertificate.sdk.android.data.Config @@ -13,6 +14,11 @@ class MainApplication : Application() { override fun onCreate() { super.onCreate() + + if (DebugFragment.EXISTS) { + DebugFragment.initDebug(this) + } + // If this is a fresh install, don't show the certificate light updateboarding val isFreshInstall = ConfigSecureStorage.getInstance(this).getConfig() == null if (isFreshInstall) { diff --git a/wallet/src/abn/java/ch/admin/bag/covidcertificate/wallet/debug/WalletDebugFragment.kt b/wallet/src/abn/java/ch/admin/bag/covidcertificate/wallet/debug/WalletDebugFragment.kt new file mode 100644 index 00000000..85ef02a1 --- /dev/null +++ b/wallet/src/abn/java/ch/admin/bag/covidcertificate/wallet/debug/WalletDebugFragment.kt @@ -0,0 +1,18 @@ +package ch.admin.bag.covidcertificate.wallet.debug +/* + * Copyright (c) 2021 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +import ch.admin.bag.covidcertificate.common.debug.DebugFragment + +class WalletDebugFragment : DebugFragment() { + companion object { + fun newInstance(): DebugFragment = DebugFragment() + } +} \ No newline at end of file diff --git a/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificateItem.kt b/wallet/src/dev/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificateItem.kt similarity index 100% rename from wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificateItem.kt rename to wallet/src/dev/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificateItem.kt diff --git a/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificatesListAdapter.kt b/wallet/src/dev/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificatesListAdapter.kt similarity index 100% rename from wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificatesListAdapter.kt rename to wallet/src/dev/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificatesListAdapter.kt diff --git a/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificatesListViewHolder.kt b/wallet/src/dev/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificatesListViewHolder.kt similarity index 100% rename from wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificatesListViewHolder.kt rename to wallet/src/dev/java/ch/admin/bag/covidcertificate/wallet/debug/DebugCertificatesListViewHolder.kt diff --git a/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/debug/DebugFragment.kt b/wallet/src/dev/java/ch/admin/bag/covidcertificate/wallet/debug/WalletDebugFragment.kt similarity index 61% rename from wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/debug/DebugFragment.kt rename to wallet/src/dev/java/ch/admin/bag/covidcertificate/wallet/debug/WalletDebugFragment.kt index ac631536..d21fc397 100644 --- a/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/debug/DebugFragment.kt +++ b/wallet/src/dev/java/ch/admin/bag/covidcertificate/wallet/debug/WalletDebugFragment.kt @@ -11,50 +11,25 @@ package ch.admin.bag.covidcertificate.wallet.debug import android.content.Intent import android.os.Bundle -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels -import ch.admin.bag.covidcertificate.wallet.BuildConfig +import ch.admin.bag.covidcertificate.common.debug.DebugFragment import ch.admin.bag.covidcertificate.wallet.CertificatesViewModel -import ch.admin.bag.covidcertificate.wallet.databinding.FragmentDebugBinding -class DebugFragment : Fragment() { +class WalletDebugFragment : DebugFragment() { companion object { fun newInstance(): DebugFragment = DebugFragment() - - const val EXISTS = BuildConfig.FLAVOR == "abn" || BuildConfig.FLAVOR == "dev" } private val certificatesViewModel by activityViewModels() - private var _binding: FragmentDebugBinding? = null - private val binding get() = _binding!! - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - _binding = FragmentDebugBinding.inflate(inflater, container, false) - return binding.root - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - // Have additional self-control to not be shown in PROD - if (!EXISTS) { - parentFragmentManager.popBackStack() - } + super.onViewCreated(view, savedInstanceState) - binding.toolbar.setNavigationOnClickListener { - parentFragmentManager.popBackStack() - } setupRecyclerView() } - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } - private fun setupRecyclerView() { val recyclerView = binding.certificatesRecyclerView diff --git a/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/MainApplication.kt b/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/MainApplication.kt index 27df2ead..2befa860 100644 --- a/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/MainApplication.kt +++ b/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/MainApplication.kt @@ -6,11 +6,12 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.ProcessLifecycleOwner +import ch.admin.bag.covidcertificate.common.debug.DebugFragment import ch.admin.bag.covidcertificate.common.net.ConfigRepository import ch.admin.bag.covidcertificate.common.util.EnvironmentUtil +import ch.admin.bag.covidcertificate.sdk.android.CovidCertificateSdk import ch.admin.bag.covidcertificate.sdk.android.data.Config import ch.admin.bag.covidcertificate.sdk.android.net.interceptor.UserAgentInterceptor -import ch.admin.bag.covidcertificate.sdk.android.CovidCertificateSdk import ch.admin.bag.covidcertificate.wallet.data.CertificateStorage import ch.admin.bag.covidcertificate.wallet.data.WalletDataItem import ch.admin.bag.covidcertificate.wallet.data.WalletDataSecureStorage @@ -22,6 +23,11 @@ class MainApplication : Application() { override fun onCreate() { super.onCreate() + + if (DebugFragment.EXISTS) { + DebugFragment.initDebug(this) + } + Config.appToken = BuildConfig.SDK_APP_TOKEN Config.userAgent = UserAgentInterceptor.UserAgentGenerator { "${this.packageName};${BuildConfig.VERSION_NAME};${BuildConfig.BUILD_TIME};Android;${Build.VERSION.SDK_INT}" } diff --git a/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/homescreen/HomeFragment.kt b/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/homescreen/HomeFragment.kt index 96e6427f..0610bfa0 100644 --- a/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/homescreen/HomeFragment.kt +++ b/wallet/src/main/java/ch/admin/bag/covidcertificate/wallet/homescreen/HomeFragment.kt @@ -30,10 +30,10 @@ import androidx.viewpager2.widget.ViewPager2 import ch.admin.bag.covidcertificate.common.config.ConfigViewModel import ch.admin.bag.covidcertificate.common.config.InfoBoxModel import ch.admin.bag.covidcertificate.common.data.ConfigSecureStorage +import ch.admin.bag.covidcertificate.common.debug.DebugFragment import ch.admin.bag.covidcertificate.common.dialog.InfoDialogFragment import ch.admin.bag.covidcertificate.common.html.BuildInfo import ch.admin.bag.covidcertificate.common.html.ImprintFragment -import ch.admin.bag.covidcertificate.common.util.AssetUtil import ch.admin.bag.covidcertificate.common.util.HorizontalMarginItemDecoration import ch.admin.bag.covidcertificate.common.views.hideAnimated import ch.admin.bag.covidcertificate.common.views.rotate @@ -46,7 +46,7 @@ import ch.admin.bag.covidcertificate.wallet.DeeplinkViewModel import ch.admin.bag.covidcertificate.wallet.R import ch.admin.bag.covidcertificate.wallet.add.CertificateAddFragment import ch.admin.bag.covidcertificate.wallet.databinding.FragmentHomeBinding -import ch.admin.bag.covidcertificate.wallet.debug.DebugFragment +import ch.admin.bag.covidcertificate.wallet.debug.WalletDebugFragment import ch.admin.bag.covidcertificate.wallet.detail.CertificateDetailFragment import ch.admin.bag.covidcertificate.wallet.faq.WalletFaqFragment import ch.admin.bag.covidcertificate.wallet.homescreen.pager.CertificatesPagerAdapter @@ -161,10 +161,8 @@ class HomeFragment : Fragment() { lastClick.set(0) parentFragmentManager.beginTransaction() .setCustomAnimations(R.anim.slide_enter, R.anim.slide_exit, R.anim.slide_pop_enter, R.anim.slide_pop_exit) - .replace( - R.id.fragment_container, DebugFragment.newInstance() - ) - .addToBackStack(DebugFragment::class.java.canonicalName) + .replace(R.id.fragment_container, WalletDebugFragment.newInstance()) + .addToBackStack(WalletDebugFragment::class.java.canonicalName) .commit() } else { lastClick.set(now) diff --git a/wallet/src/prod/java/ch/admin/bag/covidcertificate/wallet/debug/WalletDebugFragment.kt b/wallet/src/prod/java/ch/admin/bag/covidcertificate/wallet/debug/WalletDebugFragment.kt new file mode 100644 index 00000000..1da5fa8d --- /dev/null +++ b/wallet/src/prod/java/ch/admin/bag/covidcertificate/wallet/debug/WalletDebugFragment.kt @@ -0,0 +1,19 @@ +package ch.admin.bag.covidcertificate.wallet.debug +/* + * Copyright (c) 2021 Ubique Innovation AG + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + + +import ch.admin.bag.covidcertificate.common.debug.DebugFragment + +class WalletDebugFragment : DebugFragment() { + companion object { + fun newInstance(): DebugFragment = DebugFragment() + } +} \ No newline at end of file