X-Git-Url: https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Factivities%2FViewSourceActivity.java;h=e4899ea329669f741c3b6355558b7e3f4bceba6e;hp=bcb94c18ef74a1776c7cc59fcfd1d90fd4cf3b0b;hb=b82022327701273b1b56419e8d6042895c0bc7b9;hpb=729652a6a06a8c1bf6244c56089a9c0db84e283e diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.java index bcb94c18..e4899ea3 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.java @@ -1,5 +1,5 @@ /* - * Copyright © 2017-2019 Soren Stoutner . + * Copyright © 2017-2020 Soren Stoutner . * * This file is part of Privacy Browser . * @@ -20,12 +20,17 @@ package com.stoutner.privacybrowser.activities; import android.app.Activity; -import android.app.DialogFragment; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.os.Build; import android.os.Bundle; +import android.os.LocaleList; +import android.preference.PreferenceManager; import android.text.Spanned; import android.text.style.ForegroundColorSpan; +import android.util.TypedValue; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; @@ -33,16 +38,27 @@ import android.view.View; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import android.widget.ProgressBar; +import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; // The AndroidX toolbar must be used until the minimum API is >= 21. +import androidx.appcompat.widget.Toolbar; import androidx.core.app.NavUtils; +import androidx.fragment.app.DialogFragment; +import androidx.lifecycle.ViewModelProvider; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import com.google.android.material.snackbar.Snackbar; import com.stoutner.privacybrowser.R; -import com.stoutner.privacybrowser.asynctasks.GetSource; import com.stoutner.privacybrowser.dialogs.AboutViewSourceDialog; +import com.stoutner.privacybrowser.helpers.ProxyHelper; +import com.stoutner.privacybrowser.viewmodelfactories.WebViewSourceFactory; +import com.stoutner.privacybrowser.viewmodels.WebViewSource; + +import java.net.Proxy; +import java.util.Locale; public class ViewSourceActivity extends AppCompatActivity { // `activity` is used in `onCreate()` and `goBack()`. @@ -55,17 +71,19 @@ public class ViewSourceActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { + // Get a handle for the shared preferences. + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + + // Get the screenshot preference. + boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false); + // Disable screenshots if not allowed. - if (!MainWebViewActivity.allowScreenshots) { + if (!allowScreenshots) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); } // Set the theme. - if (MainWebViewActivity.darkTheme) { - setTheme(R.style.PrivacyBrowserDark); - } else { - setTheme(R.style.PrivacyBrowserLight); - } + setTheme(R.style.PrivacyBrowser); // Run the default commands. super.onCreate(savedInstanceState); @@ -73,8 +91,12 @@ public class ViewSourceActivity extends AppCompatActivity { // Get the launching intent Intent intent = getIntent(); - // Get the user agent. + // Get the information from the intent. String userAgent = intent.getStringExtra("user_agent"); + String currentUrl = intent.getStringExtra("current_url"); + + // Remove the incorrect lint warning below that the user agent might be null. + assert userAgent != null; // Store a handle for the current activity. activity = this; @@ -82,8 +104,10 @@ public class ViewSourceActivity extends AppCompatActivity { // Set the content view. setContentView(R.layout.view_source_coordinatorlayout); - // The AndroidX toolbar must be used until the minimum API is >= 21. + // Get a handle for the toolbar. Toolbar toolbar = findViewById(R.id.view_source_toolbar); + + // Set the support action bar. setSupportActionBar(toolbar); // Get a handle for the action bar. @@ -96,20 +120,32 @@ public class ViewSourceActivity extends AppCompatActivity { actionBar.setCustomView(R.layout.view_source_app_bar); actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); - // Get a handle for the url text box. + // Get handles for the views. EditText urlEditText = findViewById(R.id.url_edittext); - - // Get the formatted URL string from the main activity. - String formattedUrlString = MainWebViewActivity.formattedUrlString; + TextView requestHeadersTextView = findViewById(R.id.request_headers); + TextView responseMessageTextView = findViewById(R.id.response_message); + TextView responseHeadersTextView = findViewById(R.id.response_headers); + TextView responseBodyTextView = findViewById(R.id.response_body); + ProgressBar progressBar = findViewById(R.id.progress_bar); + SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.view_source_swiperefreshlayout); // Populate the URL text box. - urlEditText.setText(formattedUrlString); + urlEditText.setText(currentUrl); - // Initialize the foreground color spans for highlighting the URLs. We have to use the deprecated `getColor()` until API >= 23. - redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700)); + // Initialize the gray foreground color spans for highlighting the URLs. The deprecated `getResources()` must be used until API >= 23. initialGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500)); finalGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500)); + // Get the current theme status. + int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; + + // Set the red color span according to the theme. + if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) { + redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700)); + } else { + redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_900)); + } + // Apply text highlighting to the URL. highlightUrlText(); @@ -138,6 +174,146 @@ public class ViewSourceActivity extends AppCompatActivity { } }); + // Set the refresh color scheme according to the theme. + if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) { + swipeRefreshLayout.setColorSchemeResources(R.color.blue_700); + } else { + swipeRefreshLayout.setColorSchemeResources(R.color.violet_500); + } + + // Initialize a color background typed value. + TypedValue colorBackgroundTypedValue = new TypedValue(); + + // Get the color background from the theme. + getTheme().resolveAttribute(android.R.attr.colorBackground, colorBackgroundTypedValue, true); + + // Get the color background int from the typed value. + int colorBackgroundInt = colorBackgroundTypedValue.data; + + // Set the swipe refresh background color. + swipeRefreshLayout.setProgressBackgroundColorSchemeColor(colorBackgroundInt); + + // Get the Do Not Track status. + boolean doNotTrack = sharedPreferences.getBoolean("do_not_track", false); + + // Instantiate a locale string. + String localeString; + + // Populate the locale string. + if (Build.VERSION.SDK_INT >= 24) { // SDK >= 24 has a list of locales. + // Get the list of locales. + LocaleList localeList = getResources().getConfiguration().getLocales(); + + // Initialize a string builder to extract the locales from the list. + StringBuilder localesStringBuilder = new StringBuilder(); + + // Initialize a `q` value, which is used by `WebView` to indicate the order of importance of the languages. + int q = 10; + + // Populate the string builder with the contents of the locales list. + for (int i = 0; i < localeList.size(); i++) { + // Append a comma if there is already an item in the string builder. + if (i > 0) { + localesStringBuilder.append(","); + } + + // Get the locale from the list. + Locale locale = localeList.get(i); + + // Add the locale to the string. `locale` by default displays as `en_US`, but WebView uses the `en-US` format. + localesStringBuilder.append(locale.getLanguage()); + localesStringBuilder.append("-"); + localesStringBuilder.append(locale.getCountry()); + + // If not the first locale, append `;q=0.x`, which drops by .1 for each removal from the main locale until q=0.1. + if (q < 10) { + localesStringBuilder.append(";q=0."); + localesStringBuilder.append(q); + } + + // Decrement `q` if it is greater than 1. + if (q > 1) { + q--; + } + + // Add a second entry for the language only portion of the locale. + localesStringBuilder.append(","); + localesStringBuilder.append(locale.getLanguage()); + + // Append `1;q=0.x`, which drops by .1 for each removal form the main locale until q=0.1. + localesStringBuilder.append(";q=0."); + localesStringBuilder.append(q); + + // Decrement `q` if it is greater than 1. + if (q > 1) { + q--; + } + } + + // Store the populated string builder in the locale string. + localeString = localesStringBuilder.toString(); + } else { // SDK < 24 only has a primary locale. + // Store the locale in the locale string. + localeString = Locale.getDefault().toString(); + } + + // Instantiate the proxy helper. + ProxyHelper proxyHelper = new ProxyHelper(); + + // Get the current proxy. + Proxy proxy = proxyHelper.getCurrentProxy(this); + + // Make the progress bar visible. + progressBar.setVisibility(View.VISIBLE); + + // Set the progress bar to be indeterminate. + progressBar.setIndeterminate(true); + + // Instantiate the WebView source factory. + ViewModelProvider.Factory webViewSourceFactory = new WebViewSourceFactory(currentUrl, userAgent, doNotTrack, localeString, proxy, MainWebViewActivity.executorService); + + // Instantiate the WebView source view model class. + final WebViewSource webViewSource = new ViewModelProvider(this, webViewSourceFactory).get(WebViewSource.class); + + // Create a source observer. + webViewSource.observeSource().observe(this, sourceStringArray -> { + // Populate the text views. This can take a long time, and freezes the user interface, if the response body is particularly large. + requestHeadersTextView.setText(sourceStringArray[0]); + responseMessageTextView.setText(sourceStringArray[1]); + responseHeadersTextView.setText(sourceStringArray[2]); + responseBodyTextView.setText(sourceStringArray[3]); + + // Hide the progress bar. + progressBar.setIndeterminate(false); + progressBar.setVisibility(View.GONE); + + //Stop the swipe to refresh indicator if it is running + swipeRefreshLayout.setRefreshing(false); + }); + + // Create an error observer. + webViewSource.observeErrors().observe(this, errorString -> { + // Display an error snackbar if the string is not `""`. + if (!errorString.equals("")) { + Snackbar.make(swipeRefreshLayout, errorString, Snackbar.LENGTH_LONG).show(); + } + }); + + // Implement swipe to refresh. + swipeRefreshLayout.setOnRefreshListener(() -> { + // Make the progress bar visible. + progressBar.setVisibility(View.VISIBLE); + + // Set the progress bar to be indeterminate. + progressBar.setIndeterminate(true); + + // Get the URL. + String urlString = urlEditText.getText().toString(); + + // Get the updated source. + webViewSource.updateSource(urlString); + }); + // Set the go button on the keyboard to request new source data. urlEditText.setOnKeyListener((View v, int keyCode, KeyEvent event) -> { // Request new source data if the enter key was pressed. @@ -148,13 +324,17 @@ public class ViewSourceActivity extends AppCompatActivity { // Remove the focus from the URL box. urlEditText.clearFocus(); + // Make the progress bar visible. + progressBar.setVisibility(View.VISIBLE); + + // Set the progress bar to be indeterminate. + progressBar.setIndeterminate(true); + // Get the URL. - String url = urlEditText.getText().toString(); + String urlString = urlEditText.getText().toString(); - // Get new source data for the current URL if it beings with `http`. - if (url.startsWith("http")) { - new GetSource(this, userAgent).execute(url); - } + // Get the updated source. + webViewSource.updateSource(urlString); // Consume the key press. return true; @@ -163,34 +343,6 @@ public class ViewSourceActivity extends AppCompatActivity { return false; } }); - - // Implement swipe to refresh. - SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.view_source_swiperefreshlayout); - swipeRefreshLayout.setOnRefreshListener(() -> { - // Get the URL. - String url = urlEditText.getText().toString(); - - // Get new source data for the URL if it begins with `http`. - if (url.startsWith("http")) { - new GetSource(this, userAgent).execute(url); - } else { - // Stop the refresh animation. - swipeRefreshLayout.setRefreshing(false); - } - }); - - // Set the swipe to refresh color according to the theme. - if (MainWebViewActivity.darkTheme) { - swipeRefreshLayout.setColorSchemeResources(R.color.blue_600); - swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.gray_800); - } else { - swipeRefreshLayout.setColorSchemeResources(R.color.blue_700); - } - - // Get the source using an AsyncTask if the URL begins with `http`. - if (formattedUrlString.startsWith("http")) { - new GetSource(this, userAgent).execute(formattedUrlString); - } } @Override @@ -203,12 +355,12 @@ public class ViewSourceActivity extends AppCompatActivity { } @Override - public boolean onOptionsItemSelected(MenuItem menuItem) { + public boolean onOptionsItemSelected(@NonNull MenuItem menuItem) { // Get a handle for the about alert dialog. DialogFragment aboutDialogFragment = new AboutViewSourceDialog(); // Show the about alert dialog. - aboutDialogFragment.show(getFragmentManager(), getString(R.string.about)); + aboutDialogFragment.show(getSupportFragmentManager(), getString(R.string.about)); // Consume the event. return true;