]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/commitdiff
Fix a crash when restiarting while the SSL Error Dialog is displayed. https://redmin...
authorSoren Stoutner <soren@stoutner.com>
Sat, 17 Jun 2023 20:21:17 +0000 (13:21 -0700)
committerSoren Stoutner <soren@stoutner.com>
Sat, 17 Jun 2023 20:21:17 +0000 (13:21 -0700)
app/src/main/java/com/stoutner/privacybrowser/dialogs/SslCertificateErrorDialog.kt
app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt
app/src/main/res/values-de/strings.xml
app/src/main/res/values-es/strings.xml
app/src/main/res/values-ru/strings.xml

index aa0ae90856ef798a1eb75f9a0c411f6eacff2ca4..63acae3f8282f7687e850adae568c25698d56db8 100644 (file)
@@ -28,6 +28,7 @@ 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
@@ -97,217 +98,241 @@ class SslCertificateErrorDialog : DialogFragment() {
         }
     }
 
+    // Declare the class variables.
+    private var sslErrorHandler: SslErrorHandler? = null
+
     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.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.
-        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()
+        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()
+                }
             }
-        }
 
-        // 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()
+            // 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()
+                    // Reset the SSL error handler.
+                    nestedScrollWebView.resetSslErrorHandler()
+                }
             }
-        }
 
-        // Create an alert dialog from the builder.
-        val alertDialog = dialogBuilder.create()
+            // Create an alert dialog from the builder.
+            val alertDialog = dialogBuilder.create()
 
-        // Get a handle for the shared preferences.
-        val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
+            // Get a handle for the shared preferences.
+            val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
 
-        // 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 the screenshot preference.
+            val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
 
-        // Get a URI for the URL with errors.
-        val uriWithErrors = Uri.parse(urlWithErrors)
-
-        // 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 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)
+            // Disable screenshots if not allowed.
+            if (!allowScreenshots) {
+                // Disable screenshots.
+                alertDialog.window!!.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
             }
 
-            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)
-
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.untrusted)
+            // Get a URI for the URL with errors.
+            val uriWithErrors = Uri.parse(urlWithErrors)
+
+            // 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 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)
+                }
+
+                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)
+
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.untrusted)
+                }
+
+                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)
+
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.invalid_date)
+                }
+
+                SslError.SSL_NOTYETVALID -> {
+                    // Change the start date span color to red.
+                    startDateStringBuilder.setSpan(redColorSpan, startDateLabel.length, startDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.future_certificate)
+                }
+
+                SslError.SSL_EXPIRED -> {
+                    // Change the end date span color to red.
+                    endDateStringBuilder.setSpan(redColorSpan, endDateLabel.length, endDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.expired_certificate)
+                }
+
+                SslError.SSL_INVALID ->
+                    // Store the primary error string.
+                    primaryErrorString = getString(R.string.invalid_certificate)
             }
 
-            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)
-
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.invalid_date)
-            }
-
-            SslError.SSL_NOTYETVALID -> {
-                // Change the start date span color to red.
-                startDateStringBuilder.setSpan(redColorSpan, startDateLabel.length, startDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.future_certificate)
-            }
-
-            SslError.SSL_EXPIRED -> {
-                // Change the end date span color to red.
-                endDateStringBuilder.setSpan(redColorSpan, endDateLabel.length, endDateStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.expired_certificate)
+            // 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()
             }
+    }
 
-            SslError.SSL_INVALID ->
-                // Store the primary error string.
-                primaryErrorString = getString(R.string.invalid_certificate)
-        }
+    override fun onSaveInstanceState(outState: Bundle) {
+        // Run the default commands.
+        super.onSaveInstanceState(outState)
 
-        // 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
+        // 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()
     }
 }
index ee1d62fe22803485d0877bbd17a3ae888d1f3bf5..518bc20e66ab00b1e8e48426de66f33deef9589d 100644 (file)
@@ -55,35 +55,35 @@ const val ULTRAPRIVACY = 6
 const val THIRD_PARTY_REQUESTS = 7
 
 // Define the private class constants.
-private const val DOMAIN_SETTINGS_APPLIED = "domain_settings_applied"
-private const val DOMAIN_SETTINGS_DATABASE_ID = "domain_settings_database_id"
-private const val CURRENT_DOMAIN_NAME = "current_domain_name"
-private const val CURRENT_URl = "current_url"
-private const val ACCEPT_COOKIES = "accept_cookies"
-private const val EASYLIST_ENABLED = "easylist_enabled"
-private const val EASYPRIVACY_ENABLED = "easyprivacy_enabled"
-private const val FANBOYS_ANNOYANCE_LIST_ENABLED = "fanboys_annoyance_list_enabled"
-private const val FANBOYS_SOCIAL_BLOCKING_LIST_ENABLED = "fanboys_social_blocking_list_enabled"
-private const val ULTRALIST_ENABLED = "ultralist_enabled"
-private const val ULTRAPRIVACY_ENABLED = "ultraprivacy_enabled"
-private const val BLOCK_ALL_THIRD_PARTY_REQUESTS = "block_all_third_party_requests"
-private const val HAS_PINNED_SSL_CERTIFICATE = "has_pinned_ssl_certificate"
-private const val PINNED_SSL_ISSUED_TO_CNAME = "pinned_ssl_issued_to_cname"
-private const val PINNED_SSL_ISSUED_TO_ONAME = "pinned_ssl_issued_to_oname"
-private const val PINNED_SSL_ISSUED_TO_UNAME = "pinned_ssl_issued_to_uname"
-private const val PINNED_SSL_ISSUED_BY_CNAME = "pinned_ssl_issued_by_cname"
-private const val PINNED_SSL_ISSUED_BY_ONAME = "pinned_ssl_issued_by_oname"
-private const val PINNED_SSL_ISSUED_BY_UNAME = "pinned_ssl_issued_by_uname"
-private const val PINNED_SSL_START_DATE = "pinned_ssl_start_date"
-private const val PINNED_SSL_END_DATE = "pinned_ssl_end_date"
-private const val PINNED_IP_ADDRESSES = "pinned_ip_addresses"
-private const val IGNORE_PINNED_DOMAIN_INFORMATION = "ignore_pinned_domain_information"
-private const val SWIPE_TO_REFRESH = "swipe_to_refresh"
-private const val JAVASCRIPT_ENABLED = "javascript_enabled"
-private const val DOM_STORAGE_ENABLED = "dom_storage_enabled"
-private const val USER_AGENT = "user_agent"
-private const val WIDE_VIEWPORT = "wide_viewport"
-private const val FONT_SIZE = "font_size"
+private const val ACCEPT_COOKIES = "A"
+private const val BLOCK_ALL_THIRD_PARTY_REQUESTS = "B"
+private const val CURRENT_DOMAIN_NAME = "C"
+private const val CURRENT_URl = "D"
+private const val DOM_STORAGE_ENABLED = "E"
+private const val DOMAIN_SETTINGS_APPLIED = "F"
+private const val DOMAIN_SETTINGS_DATABASE_ID = "G"
+private const val EASYLIST_ENABLED = "H"
+private const val EASYPRIVACY_ENABLED = "I"
+private const val FANBOYS_ANNOYANCE_LIST_ENABLED = "J"
+private const val FANBOYS_SOCIAL_BLOCKING_LIST_ENABLED = "K"
+private const val FONT_SIZE = "L"
+private const val HAS_PINNED_SSL_CERTIFICATE = "M"
+private const val IGNORE_PINNED_DOMAIN_INFORMATION = "N"
+private const val JAVASCRIPT_ENABLED = "O"
+private const val PINNED_IP_ADDRESSES = "P"
+private const val PINNED_SSL_END_DATE = "Q"
+private const val PINNED_SSL_ISSUED_BY_CNAME = "R"
+private const val PINNED_SSL_ISSUED_BY_ONAME = "S"
+private const val PINNED_SSL_ISSUED_BY_UNAME = "T"
+private const val PINNED_SSL_ISSUED_TO_CNAME = "U"
+private const val PINNED_SSL_ISSUED_TO_ONAME = "V"
+private const val PINNED_SSL_ISSUED_TO_UNAME = "W"
+private const val PINNED_SSL_START_DATE = "X"
+private const val SWIPE_TO_REFRESH = "Y"
+private const val ULTRALIST_ENABLED = "Z"
+private const val ULTRAPRIVACY_ENABLED = "AA"
+private const val USER_AGENT = "AB"
+private const val WIDE_VIEWPORT = "AC"
 
 // NestedScrollWebView extends WebView to handle nested scrolls (scrolling the app bar off the screen).  It also stores extra information about the state of the WebView used by Privacy Browser.
 class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defaultStyle: Int = android.R.attr.webViewStyle) : WebView(context, attributeSet, defaultStyle),
@@ -395,35 +395,35 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS
         val savedState = Bundle()
 
         // Populate the saved state bundle.
-        savedState.putBoolean(DOMAIN_SETTINGS_APPLIED, domainSettingsApplied)
-        savedState.putInt(DOMAIN_SETTINGS_DATABASE_ID, domainSettingsDatabaseId)
+        savedState.putBoolean(ACCEPT_COOKIES, acceptCookies)
+        savedState.putBoolean(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests)
         savedState.putString(CURRENT_DOMAIN_NAME, currentDomainName)
         savedState.putString(CURRENT_URl, currentUrl)
-        savedState.putBoolean(ACCEPT_COOKIES, acceptCookies)
+        savedState.putBoolean(DOM_STORAGE_ENABLED, this.settings.domStorageEnabled)
+        savedState.putBoolean(DOMAIN_SETTINGS_APPLIED, domainSettingsApplied)
+        savedState.putInt(DOMAIN_SETTINGS_DATABASE_ID, domainSettingsDatabaseId)
         savedState.putBoolean(EASYLIST_ENABLED, easyListEnabled)
         savedState.putBoolean(EASYPRIVACY_ENABLED, easyPrivacyEnabled)
         savedState.putBoolean(FANBOYS_ANNOYANCE_LIST_ENABLED, fanboysAnnoyanceListEnabled)
         savedState.putBoolean(FANBOYS_SOCIAL_BLOCKING_LIST_ENABLED, fanboysSocialBlockingListEnabled)
-        savedState.putBoolean(ULTRALIST_ENABLED, ultraListEnabled)
-        savedState.putBoolean(ULTRAPRIVACY_ENABLED, ultraPrivacyEnabled)
-        savedState.putBoolean(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests)
+        savedState.putInt(FONT_SIZE, this.settings.textZoom)
         savedState.putBoolean(HAS_PINNED_SSL_CERTIFICATE, hasPinnedSslCertificate)
-        savedState.putString(PINNED_SSL_ISSUED_TO_CNAME, pinnedSslIssuedToCName)
-        savedState.putString(PINNED_SSL_ISSUED_TO_ONAME, pinnedSslIssuedToOName)
-        savedState.putString(PINNED_SSL_ISSUED_TO_UNAME, pinnedSslIssuedToUName)
+        savedState.putBoolean(IGNORE_PINNED_DOMAIN_INFORMATION, ignorePinnedDomainInformation)
+        savedState.putBoolean(JAVASCRIPT_ENABLED, this.settings.javaScriptEnabled)
+        savedState.putString(PINNED_IP_ADDRESSES, pinnedIpAddresses)
+        savedState.putLong(PINNED_SSL_END_DATE, pinnedSslEndDate.time)
         savedState.putString(PINNED_SSL_ISSUED_BY_CNAME, pinnedSslIssuedByCName)
         savedState.putString(PINNED_SSL_ISSUED_BY_ONAME, pinnedSslIssuedByOName)
         savedState.putString(PINNED_SSL_ISSUED_BY_UNAME, pinnedSslIssuedByUName)
+        savedState.putString(PINNED_SSL_ISSUED_TO_CNAME, pinnedSslIssuedToCName)
+        savedState.putString(PINNED_SSL_ISSUED_TO_ONAME, pinnedSslIssuedToOName)
+        savedState.putString(PINNED_SSL_ISSUED_TO_UNAME, pinnedSslIssuedToUName)
         savedState.putLong(PINNED_SSL_START_DATE, pinnedSslStartDate.time)
-        savedState.putLong(PINNED_SSL_END_DATE, pinnedSslEndDate.time)
-        savedState.putString(PINNED_IP_ADDRESSES, pinnedIpAddresses)
-        savedState.putBoolean(IGNORE_PINNED_DOMAIN_INFORMATION, ignorePinnedDomainInformation)
         savedState.putBoolean(SWIPE_TO_REFRESH, swipeToRefresh)
-        savedState.putBoolean(JAVASCRIPT_ENABLED, this.settings.javaScriptEnabled)
-        savedState.putBoolean(DOM_STORAGE_ENABLED, this.settings.domStorageEnabled)
+        savedState.putBoolean(ULTRALIST_ENABLED, ultraListEnabled)
+        savedState.putBoolean(ULTRAPRIVACY_ENABLED, ultraPrivacyEnabled)
         savedState.putString(USER_AGENT, this.settings.userAgentString)
         savedState.putBoolean(WIDE_VIEWPORT, this.settings.useWideViewPort)
-        savedState.putInt(FONT_SIZE, this.settings.textZoom)
 
         // Return the saved state bundle.
         return savedState
@@ -432,35 +432,35 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS
     // Restore the state.
     fun restoreNestedScrollWebViewState(savedState: Bundle) {
         // Restore the class variables.
-        domainSettingsApplied = savedState.getBoolean(DOMAIN_SETTINGS_APPLIED)
-        domainSettingsDatabaseId = savedState.getInt(DOMAIN_SETTINGS_DATABASE_ID)
+        acceptCookies = savedState.getBoolean(ACCEPT_COOKIES)
+        blockAllThirdPartyRequests = savedState.getBoolean(BLOCK_ALL_THIRD_PARTY_REQUESTS)
         currentDomainName = savedState.getString(CURRENT_DOMAIN_NAME)!!
         currentUrl = savedState.getString(CURRENT_URl)!!
-        acceptCookies = savedState.getBoolean(ACCEPT_COOKIES)
+        this.settings.domStorageEnabled = savedState.getBoolean(DOM_STORAGE_ENABLED)
+        domainSettingsApplied = savedState.getBoolean(DOMAIN_SETTINGS_APPLIED)
+        domainSettingsDatabaseId = savedState.getInt(DOMAIN_SETTINGS_DATABASE_ID)
         easyListEnabled = savedState.getBoolean(EASYLIST_ENABLED)
         easyPrivacyEnabled = savedState.getBoolean(EASYPRIVACY_ENABLED)
         fanboysAnnoyanceListEnabled = savedState.getBoolean(FANBOYS_ANNOYANCE_LIST_ENABLED)
         fanboysSocialBlockingListEnabled = savedState.getBoolean(FANBOYS_SOCIAL_BLOCKING_LIST_ENABLED)
-        ultraListEnabled = savedState.getBoolean(ULTRALIST_ENABLED)
-        ultraPrivacyEnabled = savedState.getBoolean(ULTRAPRIVACY_ENABLED)
-        blockAllThirdPartyRequests = savedState.getBoolean(BLOCK_ALL_THIRD_PARTY_REQUESTS)
+        this.settings.textZoom = savedState.getInt(FONT_SIZE)
         hasPinnedSslCertificate = savedState.getBoolean(HAS_PINNED_SSL_CERTIFICATE)
-        pinnedSslIssuedToCName = savedState.getString(PINNED_SSL_ISSUED_TO_CNAME)!!
-        pinnedSslIssuedToOName = savedState.getString(PINNED_SSL_ISSUED_TO_ONAME)!!
-        pinnedSslIssuedToUName = savedState.getString(PINNED_SSL_ISSUED_TO_UNAME)!!
+        ignorePinnedDomainInformation = savedState.getBoolean(IGNORE_PINNED_DOMAIN_INFORMATION)
+        this.settings.javaScriptEnabled = savedState.getBoolean(JAVASCRIPT_ENABLED)
+        pinnedIpAddresses = savedState.getString(PINNED_IP_ADDRESSES)!!
+        pinnedSslEndDate = Date(savedState.getLong(PINNED_SSL_END_DATE))
         pinnedSslIssuedByCName = savedState.getString(PINNED_SSL_ISSUED_BY_CNAME)!!
         pinnedSslIssuedByOName = savedState.getString(PINNED_SSL_ISSUED_BY_ONAME)!!
         pinnedSslIssuedByUName = savedState.getString(PINNED_SSL_ISSUED_BY_UNAME)!!
+        pinnedSslIssuedToCName = savedState.getString(PINNED_SSL_ISSUED_TO_CNAME)!!
+        pinnedSslIssuedToOName = savedState.getString(PINNED_SSL_ISSUED_TO_ONAME)!!
+        pinnedSslIssuedToUName = savedState.getString(PINNED_SSL_ISSUED_TO_UNAME)!!
         pinnedSslStartDate = Date(savedState.getLong(PINNED_SSL_START_DATE))
-        pinnedSslEndDate = Date(savedState.getLong(PINNED_SSL_END_DATE))
-        pinnedIpAddresses = savedState.getString(PINNED_IP_ADDRESSES)!!
-        ignorePinnedDomainInformation = savedState.getBoolean(IGNORE_PINNED_DOMAIN_INFORMATION)
         swipeToRefresh = savedState.getBoolean(SWIPE_TO_REFRESH)
-        this.settings.javaScriptEnabled = savedState.getBoolean(JAVASCRIPT_ENABLED)
-        this.settings.domStorageEnabled = savedState.getBoolean(DOM_STORAGE_ENABLED)
+        ultraListEnabled = savedState.getBoolean(ULTRALIST_ENABLED)
+        ultraPrivacyEnabled = savedState.getBoolean(ULTRAPRIVACY_ENABLED)
         this.settings.userAgentString = savedState.getString(USER_AGENT)
         this.settings.useWideViewPort = savedState.getBoolean(WIDE_VIEWPORT)
-        this.settings.textZoom = savedState.getInt(FONT_SIZE)
     }
 
 
index 16087e37814f86a97eebf3e927836c4d8170f9bd..70e2a78504875ed8e24ffb562d60dd486b4ea66a 100644 (file)
@@ -73,6 +73,8 @@
     <string name="unencrypted_website">Unverschlüsselte Website</string>
     <string name="no_ssl_certificate">Die Kommunikation mit dieser Website erfolgt nicht verschlüsselt.
         Dies ermöglicht Dritten, Informationen abzuhören, Ihre Bewegungen im Internet zu beobachten und böswillige Inhalte einzuschleusen.</string>
+    <string name="content_url">Content-URL</string>
+    <string name="content_url_message">Content-URLs liefern Daten aus anderen auf Ihrem Gerät installierten Apps.</string>
     <string name="ssl_certificate">SSL-Zertifikat</string>
     <string name="close">Schließen</string>
     <string name="domain">Domain</string>
index fa21f36f65f3486834c544509cc098cec6f0617f..be8b835b1453dbf03a9c45466ed7fb10205d5958 100644 (file)
@@ -69,6 +69,8 @@
     <string name="unencrypted_website">Web sin cifrar</string>
     <string name="no_ssl_certificate">La comunicación con esta página web no está cifrada.
         Esto permite a terceras partes interceptar información, rastrear su navegación e inyectar contenido malicioso.</string>
+    <string name="content_url">URL de contenido</string>
+    <string name="content_url_message">Las URL de contenido son datos cargados desde otras aplicaciones de tu dispositivo.</string>
     <string name="ssl_certificate">Certificado SSL</string>
     <string name="close">Cerrar</string>
     <string name="domain">Dominio</string>
index 477751d6c3488f83286b653704cd352ddd850caf..a755524772894f5c0668aed8c04c6cb3ecb554e4 100644 (file)
@@ -66,6 +66,8 @@
     <string name="view_ssl_certificate">Просмотр сертификата SSL</string>
     <string name="unencrypted_website">Незашифрованный веб-сайт</string>
     <string name="no_ssl_certificate">Соединение с этим сайтом не зашифровано. Это позволяет третьим сторонам перехватывать информацию, отслеживать просмотр и внедрять вредоносный контент.</string>
+    <string name="content_url">URL контента</string>
+    <string name="content_url_message">URL контента - это данные, загруженные из других приложений на вашем устройстве.</string>
     <string name="ssl_certificate">Сертификат SSL</string>
     <string name="close">Закрыть</string>
     <string name="domain">Домен</string>