X-Git-Url: https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Factivities%2FViewSourceActivity.java;fp=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Factivities%2FViewSourceActivity.java;h=0000000000000000000000000000000000000000;hp=e4899ea329669f741c3b6355558b7e3f4bceba6e;hb=606b5659cfd41c546fcbf248dcde72fd3c60d1c3;hpb=8a06558b0071fa94e2a7d1093b3118417ac5cc8f diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.java deleted file mode 100644 index e4899ea3..00000000 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.java +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright © 2017-2020 Soren Stoutner . - * - * This file is part of Privacy Browser . - * - * Privacy Browser is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Privacy Browser is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Privacy Browser. If not, see . - */ - -package com.stoutner.privacybrowser.activities; - -import android.app.Activity; -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; -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; -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.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()`. - private Activity activity; - - // The color spans are used in `onCreate()` and `highlightUrlText()`. - private ForegroundColorSpan redColorSpan; - private ForegroundColorSpan initialGrayColorSpan; - private ForegroundColorSpan finalGrayColorSpan; - - @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 (!allowScreenshots) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); - } - - // Set the theme. - setTheme(R.style.PrivacyBrowser); - - // Run the default commands. - super.onCreate(savedInstanceState); - - // Get the launching intent - Intent intent = getIntent(); - - // 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; - - // Set the content view. - setContentView(R.layout.view_source_coordinatorlayout); - - // 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. - final ActionBar actionBar = getSupportActionBar(); - - // Remove the incorrect lint warning that the action bar might be null. - assert actionBar != null; - - // Add the custom layout to the action bar. - actionBar.setCustomView(R.layout.view_source_app_bar); - actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); - - // Get handles for the views. - EditText urlEditText = findViewById(R.id.url_edittext); - 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(currentUrl); - - // 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(); - - // Get a handle for the input method manager, which is used to hide the keyboard. - InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - - // Remove the lint warning that the input method manager might be null. - assert inputMethodManager != null; - - // Remove the formatting from the URL when the user is editing the text. - urlEditText.setOnFocusChangeListener((View v, boolean hasFocus) -> { - if (hasFocus) { // The user is editing `urlTextBox`. - // Remove the highlighting. - urlEditText.getText().removeSpan(redColorSpan); - urlEditText.getText().removeSpan(initialGrayColorSpan); - urlEditText.getText().removeSpan(finalGrayColorSpan); - } else { // The user has stopped editing `urlTextBox`. - // Hide the soft keyboard. - inputMethodManager.hideSoftInputFromWindow(urlEditText.getWindowToken(), 0); - - // Move to the beginning of the string. - urlEditText.setSelection(0); - - // Reapply the highlighting. - highlightUrlText(); - } - }); - - // 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. - if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { - // Hide the soft keyboard. - inputMethodManager.hideSoftInputFromWindow(urlEditText.getWindowToken(), 0); - - // 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 urlString = urlEditText.getText().toString(); - - // Get the updated source. - webViewSource.updateSource(urlString); - - // Consume the key press. - return true; - } else { - // Do not consume the key press. - return false; - } - }); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu. This adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.view_source_options_menu, menu); - - // Display the menu. - return true; - } - - @Override - 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(getSupportFragmentManager(), getString(R.string.about)); - - // Consume the event. - return true; - } - - public void goBack(View view) { - // Go home. - NavUtils.navigateUpFromSameTask(activity); - } - - private void highlightUrlText() { - // Get a handle for the URL EditText. - EditText urlEditText = findViewById(R.id.url_edittext); - - // Get the URL string. - String urlString = urlEditText.getText().toString(); - - // Highlight the URL according to the protocol. - if (urlString.startsWith("file://")) { // This is a file URL. - // De-emphasize only the protocol. - urlEditText.getText().setSpan(initialGrayColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } else if (urlString.startsWith("content://")) { - // De-emphasize only the protocol. - urlEditText.getText().setSpan(initialGrayColorSpan, 0, 10, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } else { // This is a web URL. - // Get the index of the `/` immediately after the domain name. - int endOfDomainName = urlString.indexOf("/", (urlString.indexOf("//") + 2)); - - // Create a base URL string. - String baseUrl; - - // Get the base URL. - if (endOfDomainName > 0) { // There is at least one character after the base URL. - // Get the base URL. - baseUrl = urlString.substring(0, endOfDomainName); - } else { // There are no characters after the base URL. - // Set the base URL to be the entire URL string. - baseUrl = urlString; - } - - // Get the index of the last `.` in the domain. - int lastDotIndex = baseUrl.lastIndexOf("."); - - // Get the index of the penultimate `.` in the domain. - int penultimateDotIndex = baseUrl.lastIndexOf(".", lastDotIndex - 1); - - // Markup the beginning of the URL. - if (urlString.startsWith("http://")) { // Highlight the protocol of connections that are not encrypted. - urlEditText.getText().setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - - // De-emphasize subdomains. - if (penultimateDotIndex > 0) { // There is more than one subdomain in the domain name. - urlEditText.getText().setSpan(initialGrayColorSpan, 7, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } - } else if (urlString.startsWith("https://")) { // De-emphasize the protocol of connections that are encrypted. - if (penultimateDotIndex > 0) { // There is more than one subdomain in the domain name. - // De-emphasize the protocol and the additional subdomains. - urlEditText.getText().setSpan(initialGrayColorSpan, 0, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } else { // There is only one subdomain in the domain name. - // De-emphasize only the protocol. - urlEditText.getText().setSpan(initialGrayColorSpan, 0, 8, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } - } - - // De-emphasize the text after the domain name. - if (endOfDomainName > 0) { - urlEditText.getText().setSpan(finalGrayColorSpan, endOfDomainName, urlString.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } - } - } -} \ No newline at end of file