]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/dialogs/SslCertificateErrorDialog.kt
First wrong button text in View Headers in night theme. https://redmine.stoutner...
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / dialogs / SslCertificateErrorDialog.kt
index 1090bedd2285244a368ada1b331059fa4f6c8eb5..60df833f14ec07e088bffdd7321fb664fd3aa560 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2016-2023 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
  *
 
 package com.stoutner.privacybrowser.dialogs
 
-import android.app.Activity
 import android.app.Dialog
 import android.content.DialogInterface
 import android.net.Uri
 import android.net.http.SslError
-import android.os.AsyncTask
 import android.os.Bundle
 import android.text.SpannableStringBuilder
 import android.text.Spanned
 import android.text.style.ForegroundColorSpan
 import android.view.WindowManager
+import android.webkit.SslErrorHandler
 import android.widget.TextView
 
 import androidx.appcompat.app.AlertDialog
@@ -38,11 +37,9 @@ import androidx.preference.PreferenceManager
 
 import com.stoutner.privacybrowser.R
 import com.stoutner.privacybrowser.activities.MainWebViewActivity
+import com.stoutner.privacybrowser.coroutines.GetHostIpAddressesCoroutine
 import com.stoutner.privacybrowser.views.NestedScrollWebView
 
-import java.lang.ref.WeakReference
-import java.net.InetAddress
-import java.net.UnknownHostException
 import java.text.DateFormat
 
 // Define the class constants.
@@ -60,8 +57,6 @@ private const val WEBVIEW_FRAGMENT_ID = "webview_fragment_id"
 
 class SslCertificateErrorDialog : DialogFragment() {
     companion object {
-        // `@JvmStatic` will no longer be required once all the code has transitioned to Kotlin.
-        @JvmStatic
         fun displayDialog(sslError: SslError, webViewFragmentId: Long): SslCertificateErrorDialog {
             // Get the various components of the SSL error message.
             val primaryErrorInt = sslError.primaryError
@@ -103,292 +98,241 @@ class SslCertificateErrorDialog : DialogFragment() {
         }
     }
 
-    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
-        // Get the variables from the bundle.
-        val primaryErrorInt = requireArguments().getInt(PRIMARY_ERROR_INT)
-        val urlWithErrors = requireArguments().getString(URL_WITH_ERRORS)
-        val issuedToCName = requireArguments().getString(ISSUED_TO_CNAME)
-        val issuedToOName = requireArguments().getString(ISSUED_TO_ONAME)
-        val issuedToUName = requireArguments().getString(ISSUED_TO_UNAME)
-        val issuedByCName = requireArguments().getString(ISSUED_BY_CNAME)
-        val issuedByOName = requireArguments().getString(ISSUED_BY_ONAME)
-        val issuedByUName = requireArguments().getString(ISSUED_BY_UNAME)
-        val startDate = requireArguments().getString(START_DATE)
-        val endDate = requireArguments().getString(END_DATE)
-        val webViewFragmentId = requireArguments().getLong(WEBVIEW_FRAGMENT_ID)
-
-        // Get the current position of this WebView fragment.
-        val webViewPosition = MainWebViewActivity.webViewPagerAdapter.getPositionForId(webViewFragmentId)
-
-        // Get the WebView tab fragment.
-        val webViewTabFragment = MainWebViewActivity.webViewPagerAdapter.getPageFragment(webViewPosition)
-
-        // Get the fragment view.
-        val fragmentView = webViewTabFragment.requireView()
-
-        // Get a handle for the current WebView.
-        val nestedScrollWebView: NestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview)
-
-        // Get a handle for the SSL error handler.
-        val sslErrorHandler = nestedScrollWebView.sslErrorHandler
-
-        // Use an alert dialog builder to create the alert dialog.
-        val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog)
-
-        // Set the icon.
-        dialogBuilder.setIcon(R.drawable.ssl_certificate)
-
-        // Set the title.
-        dialogBuilder.setTitle(R.string.ssl_certificate_error)
-
-        // Set the view.
-        dialogBuilder.setView(R.layout.ssl_certificate_error)
-
-        // Set the cancel button listener.
-        dialogBuilder.setNegativeButton(R.string.cancel) { _: DialogInterface?, _: Int ->
-            // Check to make sure the SSL error handler is not null.  This might happen if multiple dialogs are displayed at once.
-            if (sslErrorHandler != null) {
-                // Cancel the request.
-                sslErrorHandler.cancel()
-
-                // Reset the SSL error handler.
-                nestedScrollWebView.resetSslErrorHandler()
-            }
-        }
-
-        // Set the proceed button listener.
-        dialogBuilder.setPositiveButton(R.string.proceed) { _: DialogInterface?, _: Int ->
-            // Check to make sure the SSL error handler is not null.  This might happen if multiple dialogs are displayed at once.
-            if (sslErrorHandler != null) {
-                // Proceed to the website.
-                sslErrorHandler.proceed()
-
-                // Reset the SSL error handler.
-                nestedScrollWebView.resetSslErrorHandler()
-            }
-        }
-
-        // Create an alert dialog from the builder.
-        val alertDialog = dialogBuilder.create()
-
-        // Get a handle for the shared preferences.
-        val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
+    // Define the class variables.
+    private var sslErrorHandler: SslErrorHandler? = null
 
-        // Get the screenshot preference.
-        val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
-
-        // Disable screenshots if not allowed.
-        if (!allowScreenshots) {
-            // Disable screenshots.
-            alertDialog.window!!.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
-        }
-
-        // Get a URI for the URL with errors.
-        val uriWithErrors = Uri.parse(urlWithErrors)
-
-        // Get the IP addresses for the URI.
-        GetIpAddresses(requireActivity(), alertDialog).execute(uriWithErrors.host)
-
-        // The alert dialog must be shown before the contents can be modified.
-        alertDialog.show()
-
-        // Get handles for the views.
-        val primaryErrorTextView = alertDialog.findViewById<TextView>(R.id.primary_error)!!
-        val urlTextView = alertDialog.findViewById<TextView>(R.id.url)!!
-        val issuedToCNameTextView = alertDialog.findViewById<TextView>(R.id.issued_to_cname)!!
-        val issuedToONameTextView = alertDialog.findViewById<TextView>(R.id.issued_to_oname)!!
-        val issuedToUNameTextView = alertDialog.findViewById<TextView>(R.id.issued_to_uname)!!
-        val issuedByTextView = alertDialog.findViewById<TextView>(R.id.issued_by_textview)!!
-        val issuedByCNameTextView = alertDialog.findViewById<TextView>(R.id.issued_by_cname)!!
-        val issuedByONameTextView = alertDialog.findViewById<TextView>(R.id.issued_by_oname)!!
-        val issuedByUNameTextView = alertDialog.findViewById<TextView>(R.id.issued_by_uname)!!
-        val validDatesTextView = alertDialog.findViewById<TextView>(R.id.valid_dates_textview)!!
-        val startDateTextView = alertDialog.findViewById<TextView>(R.id.start_date)!!
-        val endDateTextView = alertDialog.findViewById<TextView>(R.id.end_date)!!
-
-        // Setup the common strings.
-        val urlLabel = getString(R.string.url_label) + "  "
-        val cNameLabel = getString(R.string.common_name) + "  "
-        val oNameLabel = getString(R.string.organization) + "  "
-        val uNameLabel = getString(R.string.organizational_unit) + "  "
-        val startDateLabel = getString(R.string.start_date) + "  "
-        val endDateLabel = getString(R.string.end_date) + "  "
-
-        // Create a spannable string builder for each text view that needs multiple colors of text.
-        val urlStringBuilder = SpannableStringBuilder(urlLabel + urlWithErrors)
-        val issuedToCNameStringBuilder = SpannableStringBuilder(cNameLabel + issuedToCName)
-        val issuedToONameStringBuilder = SpannableStringBuilder(oNameLabel + issuedToOName)
-        val issuedToUNameStringBuilder = SpannableStringBuilder(uNameLabel + issuedToUName)
-        val issuedByCNameStringBuilder = SpannableStringBuilder(cNameLabel + issuedByCName)
-        val issuedByONameStringBuilder = SpannableStringBuilder(oNameLabel + issuedByOName)
-        val issuedByUNameStringBuilder = SpannableStringBuilder(uNameLabel + issuedByUName)
-        val startDateStringBuilder = SpannableStringBuilder(startDateLabel + startDate)
-        val endDateStringBuilder = SpannableStringBuilder(endDateLabel + endDate)
-
-        // Define the color spans.
-        val blueColorSpan = ForegroundColorSpan(requireContext().getColor(R.color.alt_blue_text))
-        val redColorSpan = ForegroundColorSpan(requireContext().getColor(R.color.red_text))
-
-        // Setup the spans to display the certificate information in blue.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
-        urlStringBuilder.setSpan(blueColorSpan, urlLabel.length, urlStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-        issuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length, issuedToCNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-        issuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length, issuedToONameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-        issuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length, issuedToUNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-        issuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length, issuedByCNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-        issuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length, issuedByONameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-        issuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length, issuedByUNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-        startDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length, startDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-        endDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length, endDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-
-        // Define the primary error string.
-        var primaryErrorString = ""
-
-        // Highlight the primary error in red and store it in the primary error string.
-        when (primaryErrorInt) {
-            SslError.SSL_IDMISMATCH -> {
-                // Change the URL span colors to red.
-                urlStringBuilder.setSpan(redColorSpan, urlLabel.length, urlStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-                issuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length, issuedToCNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.cn_mismatch)
+    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+        try {
+            // Get the variables from the bundle.
+            val primaryErrorInt = requireArguments().getInt(PRIMARY_ERROR_INT)
+            val urlWithErrors = requireArguments().getString(URL_WITH_ERRORS)
+            val issuedToCName = requireArguments().getString(ISSUED_TO_CNAME)
+            val issuedToOName = requireArguments().getString(ISSUED_TO_ONAME)
+            val issuedToUName = requireArguments().getString(ISSUED_TO_UNAME)
+            val issuedByCName = requireArguments().getString(ISSUED_BY_CNAME)
+            val issuedByOName = requireArguments().getString(ISSUED_BY_ONAME)
+            val issuedByUName = requireArguments().getString(ISSUED_BY_UNAME)
+            val startDate = requireArguments().getString(START_DATE)
+            val endDate = requireArguments().getString(END_DATE)
+            val webViewFragmentId = requireArguments().getLong(WEBVIEW_FRAGMENT_ID)
+
+            // Get the current position of this WebView fragment.
+            val webViewPosition = MainWebViewActivity.webViewStateAdapter!!.getPositionForId(webViewFragmentId)
+
+            // Get the WebView tab fragment.
+            val webViewTabFragment = MainWebViewActivity.webViewStateAdapter!!.getPageFragment(webViewPosition)
+
+            // Get the fragment view.
+            val fragmentView = webViewTabFragment.requireView()
+
+            // Get a handle for the current WebView.
+            val nestedScrollWebView: NestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview)
+
+            // Get a handle for the SSL error handler.
+            sslErrorHandler = nestedScrollWebView.sslErrorHandler
+
+            // Use an alert dialog builder to create the alert dialog.
+            val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog)
+
+            // Set the icon.
+            dialogBuilder.setIcon(R.drawable.ssl_certificate)
+
+            // Set the title.
+            dialogBuilder.setTitle(R.string.ssl_certificate_error)
+
+            // Set the view.
+            dialogBuilder.setView(R.layout.ssl_certificate_error)
+
+            // Set the cancel button listener.
+            dialogBuilder.setNegativeButton(R.string.cancel) { _: DialogInterface?, _: Int ->
+                // Check to make sure the SSL error handler is not null.  This might happen if multiple dialogs are displayed at once.
+                if (sslErrorHandler != null) {
+                    // Cancel the request.
+                    sslErrorHandler!!.cancel()
+
+                    // Reset the SSL error handler.
+                    nestedScrollWebView.resetSslErrorHandler()
+                }
             }
 
-            SslError.SSL_UNTRUSTED -> {
-                // Change the issued by text view text to red.
-                issuedByTextView.setTextColor(requireContext().getColor(R.color.red_text))
-
-                // Change the issued by span color to red.
-                issuedByCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length, issuedByCNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-                issuedByONameStringBuilder.setSpan(redColorSpan, oNameLabel.length, issuedByONameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-                issuedByUNameStringBuilder.setSpan(redColorSpan, uNameLabel.length, issuedByUNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            // Set the proceed button listener.
+            dialogBuilder.setPositiveButton(R.string.proceed) { _: DialogInterface?, _: Int ->
+                // Check to make sure the SSL error handler is not null.  This might happen if multiple dialogs are displayed at once.
+                if (sslErrorHandler != null) {
+                    // Proceed to the website.
+                    sslErrorHandler!!.proceed()
 
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.untrusted)
+                    // Reset the SSL error handler.
+                    nestedScrollWebView.resetSslErrorHandler()
+                }
             }
 
-            SslError.SSL_DATE_INVALID -> {
-                // Change the valid dates text view text to red.
-                validDatesTextView.setTextColor(requireContext().getColor(R.color.red_text))
-
-                // Change the date span colors to red.
-                startDateStringBuilder.setSpan(redColorSpan, startDateLabel.length, startDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-                endDateStringBuilder.setSpan(redColorSpan, endDateLabel.length, endDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            // Create an alert dialog from the builder.
+            val alertDialog = dialogBuilder.create()
 
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.invalid_date)
-            }
+            // Get a handle for the shared preferences.
+            val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
 
-            SslError.SSL_NOTYETVALID -> {
-                // Change the start date span color to red.
-                startDateStringBuilder.setSpan(redColorSpan, startDateLabel.length, startDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            // Get the screenshot preference.
+            val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
 
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.future_certificate)
+            // Disable screenshots if not allowed.
+            if (!allowScreenshots) {
+                // Disable screenshots.
+                alertDialog.window!!.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
             }
 
-            SslError.SSL_EXPIRED -> {
-                // Change the end date span color to red.
-                endDateStringBuilder.setSpan(redColorSpan, endDateLabel.length, endDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            // Get a URI for the URL with errors.
+            val uriWithErrors = Uri.parse(urlWithErrors)
 
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.expired_certificate)
-            }
+            // The alert dialog must be shown before the contents can be modified.
+            alertDialog.show()
 
-            SslError.SSL_INVALID ->
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.invalid_certificate)
-        }
+            // Get handles for the views.
+            val primaryErrorTextView = alertDialog.findViewById<TextView>(R.id.primary_error)!!
+            val urlTextView = alertDialog.findViewById<TextView>(R.id.url)!!
+            val ipAddressesTextView = alertDialog.findViewById<TextView>(R.id.ip_addresses)!!
+            val issuedToCNameTextView = alertDialog.findViewById<TextView>(R.id.issued_to_cname)!!
+            val issuedToONameTextView = alertDialog.findViewById<TextView>(R.id.issued_to_oname)!!
+            val issuedToUNameTextView = alertDialog.findViewById<TextView>(R.id.issued_to_uname)!!
+            val issuedByTextView = alertDialog.findViewById<TextView>(R.id.issued_by_textview)!!
+            val issuedByCNameTextView = alertDialog.findViewById<TextView>(R.id.issued_by_cname)!!
+            val issuedByONameTextView = alertDialog.findViewById<TextView>(R.id.issued_by_oname)!!
+            val issuedByUNameTextView = alertDialog.findViewById<TextView>(R.id.issued_by_uname)!!
+            val validDatesTextView = alertDialog.findViewById<TextView>(R.id.valid_dates_textview)!!
+            val startDateTextView = alertDialog.findViewById<TextView>(R.id.start_date)!!
+            val endDateTextView = alertDialog.findViewById<TextView>(R.id.end_date)!!
+
+            // Define the color spans.
+            val blueColorSpan = ForegroundColorSpan(requireContext().getColor(R.color.alt_blue_text))
+            val redColorSpan = ForegroundColorSpan(requireContext().getColor(R.color.red_text))
+
+            // Get the IP Addresses for the URI.
+            GetHostIpAddressesCoroutine.getAddresses(uriWithErrors.host!!, getString(R.string.ip_addresses), blueColorSpan, ipAddressesTextView)
+
+            // Setup the common strings.
+            val urlLabel = getString(R.string.url_label)
+            val cNameLabel = getString(R.string.common_name)
+            val oNameLabel = getString(R.string.organization)
+            val uNameLabel = getString(R.string.organizational_unit)
+            val startDateLabel = getString(R.string.start_date)
+            val endDateLabel = getString(R.string.end_date)
+
+            // Create a spannable string builder for each text view that needs multiple colors of text.
+            val urlStringBuilder = SpannableStringBuilder(urlLabel + urlWithErrors)
+            val issuedToCNameStringBuilder = SpannableStringBuilder(cNameLabel + issuedToCName)
+            val issuedToONameStringBuilder = SpannableStringBuilder(oNameLabel + issuedToOName)
+            val issuedToUNameStringBuilder = SpannableStringBuilder(uNameLabel + issuedToUName)
+            val issuedByCNameStringBuilder = SpannableStringBuilder(cNameLabel + issuedByCName)
+            val issuedByONameStringBuilder = SpannableStringBuilder(oNameLabel + issuedByOName)
+            val issuedByUNameStringBuilder = SpannableStringBuilder(uNameLabel + issuedByUName)
+            val startDateStringBuilder = SpannableStringBuilder(startDateLabel + startDate)
+            val endDateStringBuilder = SpannableStringBuilder(endDateLabel + endDate)
+
+            // Setup the spans to display the certificate information in blue.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
+            urlStringBuilder.setSpan(blueColorSpan, urlLabel.length, urlStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            issuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length, issuedToCNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            issuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length, issuedToONameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            issuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length, issuedToUNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            issuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length, issuedByCNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            issuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length, issuedByONameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            issuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length, issuedByUNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            startDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length, startDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+            endDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length, endDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+
+            // Define the primary error string.
+            var primaryErrorString = ""
+
+            // Highlight the primary error in red and store it in the primary error string.
+            when (primaryErrorInt) {
+                SslError.SSL_IDMISMATCH -> {
+                    // Change the URL span colors to red.
+                    urlStringBuilder.setSpan(redColorSpan, urlLabel.length, urlStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+                    issuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length, issuedToCNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.cn_mismatch)
+                }
 
-        // Display the strings.
-        primaryErrorTextView.text = primaryErrorString
-        urlTextView.text = urlStringBuilder
-        issuedToCNameTextView.text = issuedToCNameStringBuilder
-        issuedToONameTextView.text = issuedToONameStringBuilder
-        issuedToUNameTextView.text = issuedToUNameStringBuilder
-        issuedByCNameTextView.text = issuedByCNameStringBuilder
-        issuedByONameTextView.text = issuedByONameStringBuilder
-        issuedByUNameTextView.text = issuedByUNameStringBuilder
-        startDateTextView.text = startDateStringBuilder
-        endDateTextView.text = endDateStringBuilder
-
-        // Return the alert dialog.
-        return alertDialog
-    }
+                SslError.SSL_UNTRUSTED -> {
+                    // Change the issued by text view text to red.
+                    issuedByTextView.setTextColor(requireContext().getColor(R.color.red_text))
 
-    // This must run asynchronously because it involves a network request.  `String` declares the parameters.  `Void` does not declare progress units.  `SpannableStringBuilder` contains the results.
-    private class GetIpAddresses constructor(activity: Activity, alertDialog: AlertDialog) : AsyncTask<String, Void?, SpannableStringBuilder>() {
-        // Define the weak references.
-        private val activityWeakReference: WeakReference<Activity> = WeakReference(activity)
-        private val alertDialogWeakReference: WeakReference<AlertDialog> = WeakReference(alertDialog)
-
-        @Deprecated("Deprecated in Java")
-        override fun doInBackground(vararg domainName: String): SpannableStringBuilder {
-            // Get handles for the activity and the alert dialog.
-            val activity = activityWeakReference.get()
-            val alertDialog = alertDialogWeakReference.get()
-
-            // Abort if the activity or the dialog is gone.
-            if (activity == null || activity.isFinishing || alertDialog == null) {
-                return SpannableStringBuilder()
-            }
+                    // Change the issued by span color to red.
+                    issuedByCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length, issuedByCNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+                    issuedByONameStringBuilder.setSpan(redColorSpan, oNameLabel.length, issuedByONameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+                    issuedByUNameStringBuilder.setSpan(redColorSpan, uNameLabel.length, issuedByUNameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
 
-            // Initialize an IP address string builder.
-            val ipAddresses = StringBuilder()
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.untrusted)
+                }
 
-            // Get an array with the IP addresses for the host.
-            try {
-                // Get an array with all the IP addresses for the domain.
-                val inetAddressesArray = InetAddress.getAllByName(domainName[0])
+                SslError.SSL_DATE_INVALID -> {
+                    // Change the valid dates text view text to red.
+                    validDatesTextView.setTextColor(requireContext().getColor(R.color.red_text))
 
-                // Add each IP address to the string builder.
-                for (inetAddress in inetAddressesArray) {
-                    // Check to see if this is not the first IP address.
-                    if (ipAddresses.isNotEmpty()) {
-                        // Add a line break to the string builder first.
-                        ipAddresses.append("\n")
-                    }
+                    // Change the date span colors to red.
+                    startDateStringBuilder.setSpan(redColorSpan, startDateLabel.length, startDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+                    endDateStringBuilder.setSpan(redColorSpan, endDateLabel.length, endDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
 
-                    // Add the IP Address to the string builder.
-                    ipAddresses.append(inetAddress.hostAddress)
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.invalid_date)
                 }
-            } catch (exception: UnknownHostException) {
-                // Do nothing.
-            }
 
-            // Set the label.
-            val ipAddressesLabel = activity.getString(R.string.ip_addresses) + "  "
+                SslError.SSL_NOTYETVALID -> {
+                    // Change the start date span color to red.
+                    startDateStringBuilder.setSpan(redColorSpan, startDateLabel.length, startDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
 
-            // Create a spannable string builder.
-            val ipAddressesStringBuilder = SpannableStringBuilder(ipAddressesLabel + ipAddresses)
-
-            // Create a blue color span according to the theme.
-            val blueColorSpan = ForegroundColorSpan(activity.getColor(R.color.alt_blue_text))
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.future_certificate)
+                }
 
-            // Set the string builder to display the certificate information in blue.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
-            ipAddressesStringBuilder.setSpan(blueColorSpan, ipAddressesLabel.length, ipAddressesStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+                SslError.SSL_EXPIRED -> {
+                    // Change the end date span color to red.
+                    endDateStringBuilder.setSpan(redColorSpan, endDateLabel.length, endDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
 
-            // Return the formatted string.
-            return ipAddressesStringBuilder
-        }
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.expired_certificate)
+                }
 
-        // `onPostExecute()` operates on the UI thread.
-        @Deprecated("Deprecated in Java")
-        override fun onPostExecute(ipAddresses: SpannableStringBuilder) {
-            // Get handles for the activity and the alert dialog.
-            val activity = activityWeakReference.get()
-            val alertDialog = alertDialogWeakReference.get()
+                SslError.SSL_INVALID ->
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.invalid_certificate)
+            }
 
-            // Abort if the activity or the alert dialog is gone.
-            if (activity == null || activity.isFinishing || alertDialog == null) {
-                return
+            // Display the strings.
+            primaryErrorTextView.text = primaryErrorString
+            urlTextView.text = urlStringBuilder
+            issuedToCNameTextView.text = issuedToCNameStringBuilder
+            issuedToONameTextView.text = issuedToONameStringBuilder
+            issuedToUNameTextView.text = issuedToUNameStringBuilder
+            issuedByCNameTextView.text = issuedByCNameStringBuilder
+            issuedByONameTextView.text = issuedByONameStringBuilder
+            issuedByUNameTextView.text = issuedByUNameStringBuilder
+            startDateTextView.text = startDateStringBuilder
+            endDateTextView.text = endDateStringBuilder
+
+            // Return the alert dialog.
+            return alertDialog
+        } catch (exception: Exception) {  // The app was restarted while the dialog was displayed.
+            // Dismiss this new instance of the dialog as soon as it is displayed.
+            dismiss()
+
+            // Use an alert dialog builder to create an empty alert dialog.
+            val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog)
+
+            // Return the empty alert dialog.
+            return dialogBuilder.create()
             }
+    }
 
-            // Get a handle for the IP addresses text view.
-            val ipAddressesTextView = alertDialog.findViewById<TextView>(R.id.ip_addresses)!!
+    override fun onSaveInstanceState(outState: Bundle) {
+        // Run the default commands.
+        super.onSaveInstanceState(outState)
 
-            // Populate the IP addresses text view.
-            ipAddressesTextView.text = ipAddresses
-        }
+        // Cancel the request if the SSL error handler is not null.  This resets the WebView so it is not waiting on a response to the error handler if it is restarted in the background.
+        // Otherwise, after restart, the dialog is no longer displayed, but the error handler is still pending and there is no way to cause the dialog to redisplay for that URL in that tab.
+        if (sslErrorHandler != null)
+            sslErrorHandler!!.cancel()
     }
 }