X-Git-Url: https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Fdialogs%2FViewSslCertificateDialog.java;h=d27b1930cdbf2aa079d90b4a8688678d757739d7;hp=c236d3a86e78061a3a581ab2e012fd269de48afd;hb=bc2e180db377eedadbe1ea455d8fb311ead8f9d6;hpb=892e8297ba8d23a37c091fb38325929dcf7d17c9 diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/ViewSslCertificateDialog.java b/app/src/main/java/com/stoutner/privacybrowser/dialogs/ViewSslCertificateDialog.java index c236d3a8..d27b1930 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/ViewSslCertificateDialog.java +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/ViewSslCertificateDialog.java @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2019 Soren Stoutner . + * Copyright © 2016-2020 Soren Stoutner . * * This file is part of Privacy Browser . * @@ -21,71 +21,123 @@ package com.stoutner.privacybrowser.dialogs; import android.annotation.SuppressLint; import android.app.Activity; -import android.app.AlertDialog; import android.app.Dialog; -import android.app.DialogFragment; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Configuration; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.net.http.SslCertificate; -import android.os.AsyncTask; import android.os.Bundle; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.view.LayoutInflater; +import android.view.View; import android.view.WindowManager; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import androidx.preference.PreferenceManager; + import com.stoutner.privacybrowser.activities.MainWebViewActivity; import com.stoutner.privacybrowser.R; +import com.stoutner.privacybrowser.fragments.WebViewTabFragment; +import com.stoutner.privacybrowser.views.NestedScrollWebView; -import java.lang.ref.WeakReference; -import java.net.InetAddress; -import java.net.UnknownHostException; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; -// `@SuppressLing("InflateParams")` removes the warning about using `null` as the parent view group when inflating the `AlertDialog`. -@SuppressLint("InflateParams") public class ViewSslCertificateDialog extends DialogFragment { + public static ViewSslCertificateDialog displayDialog(long webViewFragmentId) { + // Create an arguments bundle. + Bundle argumentsBundle = new Bundle(); + + // Store the WebView fragment ID in the bundle. + argumentsBundle.putLong("webview_fragment_id", webViewFragmentId); + + // Create a new instance of the dialog. + ViewSslCertificateDialog viewSslCertificateDialog = new ViewSslCertificateDialog(); + + // Add the bundle to the dialog. + viewSslCertificateDialog.setArguments(argumentsBundle); + + // Return the new dialog. + return viewSslCertificateDialog; + } + + // `@SuppressLint("InflateParams")` removes the warning about using `null` as the parent view group when inflating the alert dialog. + @SuppressLint("InflateParams") + @Override + @NonNull public Dialog onCreateDialog(Bundle savedInstanceState) { + // Get a handle for the activity and the context. + Activity activity = requireActivity(); + Context context = requireContext(); + // Get the activity's layout inflater. - LayoutInflater layoutInflater = getActivity().getLayoutInflater(); + LayoutInflater layoutInflater = activity.getLayoutInflater(); + + // Get the arguments. + Bundle arguments = getArguments(); + + // Remove the incorrect lint warning below that the arguments might be null. + assert arguments != null; + + // Get the current position of this WebView fragment. + int webViewPosition = MainWebViewActivity.webViewPagerAdapter.getPositionForId(arguments.getLong("webview_fragment_id")); + + // Get the WebView tab fragment. + WebViewTabFragment webViewTabFragment = MainWebViewActivity.webViewPagerAdapter.getPageFragment(webViewPosition); + + // Get the fragment view. + View fragmentView = webViewTabFragment.getView(); + + // Remove the incorrect lint warning below that the fragment view might be null. + assert fragmentView != null; + + // Get a handle for the current WebView. + NestedScrollWebView nestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview); - // Create a drawable version of the favorite icon. - Drawable favoriteIconDrawable = new BitmapDrawable(getResources(), MainWebViewActivity.favoriteIconBitmap); // Use a builder to create the alert dialog. - AlertDialog.Builder dialogBuilder; + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context, R.style.PrivacyBrowserAlertDialog); - // Set the style according to the theme. - if (MainWebViewActivity.darkTheme) { - dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogDark); - } else { - dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogLight); - } + // Create a drawable version of the favorite icon. + Drawable favoriteIconDrawable = new BitmapDrawable(getResources(), nestedScrollWebView.getFavoriteOrDefaultIcon()); // Set the icon. dialogBuilder.setIcon(favoriteIconDrawable); - // Set a listener on the negative button. Using `null` as the listener closes the dialog without doing anything else. + // Set the close button listener. Using `null` as the listener closes the dialog without doing anything else. dialogBuilder.setNegativeButton(R.string.close, null); + // Get the SSL certificate. + SslCertificate sslCertificate = nestedScrollWebView.getCertificate(); + + // Get a handle for the shared preferences. + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + + // Get the screenshot preference. + boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false); + // Check to see if the website is encrypted. - if (MainWebViewActivity.sslCertificate == null) { // The website is not encrypted. + if (sslCertificate == null) { // The website is not encrypted. // Set the title. dialogBuilder.setTitle(R.string.unencrypted_website); - // Set the Layout. The parent view is `null` because it will be assigned by `AlertDialog`. - dialogBuilder.setView(layoutInflater.inflate(R.layout.unencrypted_website, null)); + // Set the Layout. The parent view is `null` because it will be assigned by the alert dialog. + dialogBuilder.setView(layoutInflater.inflate(R.layout.unencrypted_website_dialog, null)); // Create an alert dialog from the alert dialog builder. final AlertDialog alertDialog = dialogBuilder.create(); // Disable screenshots if not allowed. - if (!MainWebViewActivity.allowScreenshots) { + if (!allowScreenshots) { // Remove the warning below that `getWindow()` might be null. assert alertDialog.getWindow() != null; @@ -95,19 +147,18 @@ public class ViewSslCertificateDialog extends DialogFragment { // `onCreateDialog` requires the return of an `AlertDialog`. return alertDialog; - } else { // Display the SSL certificate information // Set the title. dialogBuilder.setTitle(R.string.ssl_certificate); - // Set the layout. The parent view is `null` because it will be assigned by `AlertDialog`. - dialogBuilder.setView(layoutInflater.inflate(R.layout.view_ssl_certificate, null)); + // Set the layout. The parent view is `null` because it will be assigned by the alert dialog. + dialogBuilder.setView(layoutInflater.inflate(R.layout.view_ssl_certificate_dialog, null)); // Create an alert dialog from the builder. final AlertDialog alertDialog = dialogBuilder.create(); // Disable screenshots if not allowed. - if (!MainWebViewActivity.allowScreenshots) { + if (!allowScreenshots) { // Remove the warning below that `getWindow()` might be null. assert alertDialog.getWindow() != null; @@ -130,8 +181,21 @@ public class ViewSslCertificateDialog extends DialogFragment { TextView startDateTextView = alertDialog.findViewById(R.id.start_date); TextView endDateTextView = alertDialog.findViewById(R.id.end_date); + // Remove the incorrect warning that the views might be null. + assert domainTextView != null; + assert ipAddressesTextView != null; + assert issuedToCNameTextView != null; + assert issuedToONameTextView != null; + assert issuedToUNameTextView != null; + assert issuedByCNameTextView != null; + assert issuedByONameTextView != null; + assert issuedByUNameTextView != null; + assert startDateTextView != null; + assert endDateTextView != null; + // Setup the labels. String domainLabel = getString(R.string.domain_label) + " "; + String ipAddressesLabel = getString(R.string.ip_addresses) + " "; String cNameLabel = getString(R.string.common_name) + " "; String oNameLabel = getString(R.string.organization) + " "; String uNameLabel = getString(R.string.organizational_unit) + " "; @@ -139,17 +203,11 @@ public class ViewSslCertificateDialog extends DialogFragment { String endDateLabel = getString(R.string.end_date) + " "; // Convert the formatted URL string to a URI. - Uri uri = Uri.parse(MainWebViewActivity.formattedUrlString); + Uri uri = Uri.parse(nestedScrollWebView.getUrl()); // Extract the domain name from the URI. String domainString = uri.getHost(); - // Get the IP addresses. - new GetIpAddresses(getActivity(), alertDialog).execute(domainString); - - // Get the SSL certificate. - SslCertificate sslCertificate = MainWebViewActivity.sslCertificate; - // Get the strings from the SSL certificate. String issuedToCName = sslCertificate.getIssuedTo().getCName(); String issuedToOName = sslCertificate.getIssuedTo().getOName(); @@ -162,6 +220,7 @@ public class ViewSslCertificateDialog extends DialogFragment { // Create spannable string builders for each text view that needs multiple colors of text. SpannableStringBuilder domainStringBuilder = new SpannableStringBuilder(domainLabel + domainString); + SpannableStringBuilder ipAddressesStringBuilder = new SpannableStringBuilder(ipAddressesLabel + nestedScrollWebView.getCurrentIpAddresses()); SpannableStringBuilder issuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + issuedToCName); SpannableStringBuilder issuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + issuedToOName); SpannableStringBuilder issuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + issuedToUName); @@ -171,25 +230,26 @@ public class ViewSslCertificateDialog extends DialogFragment { SpannableStringBuilder startDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(startDate)); SpannableStringBuilder endDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(endDate)); - // Create a red foreground color span. The deprecated `getColor` must be used until the minimum API >= 23. - @SuppressWarnings("deprecation") ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700)); - - // Create a blue foreground color span. + // Define the color spans. ForegroundColorSpan blueColorSpan; + ForegroundColorSpan redColorSpan; - // Set the blue color span according to the theme. The deprecated `getColor()` must be used until the minimum API >= 23. - if (MainWebViewActivity.darkTheme) { - //noinspection deprecation - blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_400)); + // Get the current theme status. + int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; + + // Set the color spans according to the theme. The deprecated `getResources()` must be used until the minimum API >= 23. + if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) { + blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.violet_500)); + redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_900)); } else { - //noinspection deprecation blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700)); + redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700)); } // Remove the incorrect lint error that `.equals` might produce a NullPointerException. assert domainString != null; - // Formet the `domainString` and `issuedToCName` colors. + // Formet the domain string and issued to CName colors. if (domainString.equals(issuedToCName)) { // `domainString` and `issuedToCName` match. // Set the strings to be blue. domainStringBuilder.setSpan(blueColorSpan, domainLabel.length(), domainStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); @@ -231,13 +291,15 @@ public class ViewSslCertificateDialog extends DialogFragment { issuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), issuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); } - // Set the issued to and issued by spans to display the certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction. + // Set the IP addresses, issued to, and issued by spans 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); 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); + // Get the current date. Date currentDate = Calendar.getInstance().getTime(); // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction. @@ -256,7 +318,7 @@ public class ViewSslCertificateDialog extends DialogFragment { // Display the strings. domainTextView.setText(domainStringBuilder); - ipAddressesTextView.setText(getString(R.string.ip_addresses)); + ipAddressesTextView.setText(ipAddressesStringBuilder); issuedToCNameTextView.setText(issuedToCNameStringBuilder); issuedToONameTextView.setText(issuedToONameStringBuilder); issuedToUNameTextView.setText(issuedToUNameStringBuilder); @@ -266,101 +328,8 @@ public class ViewSslCertificateDialog extends DialogFragment { startDateTextView.setText(startDateStringBuilder); endDateTextView.setText(endDateStringBuilder); - // `onCreateDialog` requires the return of an `AlertDialog`. + // `onCreateDialog` requires the return of an alert dialog. return alertDialog; } } - - // This must run asynchronously because it involves a network request. `String` declares the parameters. `Void` does not declare progress units. `String` contains the results. - private static class GetIpAddresses extends AsyncTask { - // The weak references are used to determine if the activity or the alert dialog have disappeared while the AsyncTask is running. - private WeakReference activityWeakReference; - private WeakReference alertDialogWeakReference; - - GetIpAddresses(Activity activity, AlertDialog alertDialog) { - // Populate the weak references. - activityWeakReference = new WeakReference<>(activity); - alertDialogWeakReference = new WeakReference<>(alertDialog); - } - - @Override - protected SpannableStringBuilder doInBackground(String... domainName) { - // Get handles for the activity and the alert dialog. - Activity activity = activityWeakReference.get(); - AlertDialog alertDialog = alertDialogWeakReference.get(); - - // Abort if the activity or the dialog is gone. - if ((activity == null) || (activity.isFinishing()) || (alertDialog == null)) { - return new SpannableStringBuilder(); - } - - // Initialize an IP address string builder. - StringBuilder ipAddresses = new StringBuilder(); - - // Get an array with the IP addresses for the host. - try { - // Get an array with all the IP addresses for the domain. - InetAddress[] inetAddressesArray = InetAddress.getAllByName(domainName[0]); - - // Add each IP address to the string builder. - for (InetAddress inetAddress : inetAddressesArray) { - if (ipAddresses.length() == 0) { // This is the first IP address. - // Add the IP Address to the string builder. - ipAddresses.append(inetAddress.getHostAddress()); - } else { // This is not the first IP address. - // Add a line break to the string builder first. - ipAddresses.append("\n"); - - // Add the IP address to the string builder. - ipAddresses.append(inetAddress.getHostAddress()); - } - } - } catch (UnknownHostException exception) { - // Do nothing. - } - - // Set the label. - String ipAddressesLabel = activity.getString(R.string.ip_addresses) + " "; - - // Create a spannable string builder. - SpannableStringBuilder ipAddressesStringBuilder = new SpannableStringBuilder(ipAddressesLabel + ipAddresses); - - // Create a blue foreground color span. - ForegroundColorSpan blueColorSpan; - - // Set the blue color span according to the theme. The deprecated `getColor()` must be used until the minimum API >= 23. - if (MainWebViewActivity.darkTheme) { - //noinspection deprecation - blueColorSpan = new ForegroundColorSpan(activity.getResources().getColor(R.color.blue_400)); - } else { - //noinspection deprecation - blueColorSpan = new ForegroundColorSpan(activity.getResources().getColor(R.color.blue_700)); - } - - // 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); - - // Return the formatted string. - return ipAddressesStringBuilder; - } - - // `onPostExecute()` operates on the UI thread. - @Override - protected void onPostExecute(SpannableStringBuilder ipAddresses) { - // Get handles for the activity and the alert dialog. - Activity activity = activityWeakReference.get(); - AlertDialog alertDialog = alertDialogWeakReference.get(); - - // Abort if the activity or the alert dialog is gone. - if ((activity == null) || (activity.isFinishing()) || (alertDialog == null)) { - return; - } - - // Get a handle for the IP addresses text view. - TextView ipAddressesTextView = alertDialog.findViewById(R.id.ip_addresses); - - // Populate the IP addresses text view. - ipAddressesTextView.setText(ipAddresses); - } - } } \ No newline at end of file