From 96cf5fae34ebc2ae7ca05322837a859943e19ba0 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Wed, 16 May 2018 13:23:16 -0700 Subject: [PATCH] Redesign the user agents so they can autoupdate. https://redmine.stoutner.com/issues/216 --- .../activities/DomainsActivity.java | 111 ++++++++------ .../activities/MainWebViewActivity.java | 125 ++++++++++------ .../fragments/DomainSettingsFragment.java | 141 ++++++++++-------- .../fragments/DomainsListFragment.java | 94 +----------- .../fragments/SettingsFragment.java | 83 +++++++---- app/src/main/res/values-de/strings.xml | 58 +++---- app/src/main/res/values-es/strings.xml | 57 +++---- app/src/main/res/values-it/strings.xml | 57 +++---- app/src/main/res/values-ru/strings.xml | 57 +++---- app/src/main/res/values/strings.xml | 102 ++++++------- app/src/main/res/xml/preferences.xml | 6 +- 11 files changed, 457 insertions(+), 434 deletions(-) diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.java index 4016c761..05df4abc 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.java @@ -21,6 +21,7 @@ package com.stoutner.privacybrowser.activities; import android.content.Context; import android.content.Intent; +import android.content.res.Resources; import android.database.Cursor; import android.net.http.SslCertificate; import android.os.Bundle; @@ -96,10 +97,16 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo private int domainSettingsDatabaseIdBeforeRotate; // `goDirectlyToDatabaseId` is used in `onCreate()` and `onCreateOptionsMenu()`. - int goDirectlyToDatabaseId; + private int goDirectlyToDatabaseId; // `closeOnBack` is used in `onCreate()`, `onOptionsItemSelected()` and `onBackPressed()`. - boolean closeOnBack; + private boolean closeOnBack; + + // `coordinatorLayout` is use in `onCreate()`, `onOptionsItemSelected()`, and `onSaveInstanceState()`. + private View coordinatorLayout; + + // `resources` is used in `onCreate()`, `onOptionsItemSelected()`, and `onSaveInstanceState()`. + private Resources resources; @Override protected void onCreate(Bundle savedInstanceState) { @@ -132,10 +139,10 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo // Set the content view. setContentView(R.layout.domains_coordinatorlayout); - // Get a handle for the context. + // Populate the class variables. + coordinatorLayout = findViewById(R.id.domains_coordinatorlayout); + resources = getResources(); context = this; - - // Get a handle for the fragment manager. supportFragmentManager = getSupportFragmentManager(); // `SupportActionBar` from `android.support.v7.app.ActionBar` must be used until the minimum API is >= 21. @@ -158,7 +165,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo addDomainFAB.setOnClickListener((View view) -> { // Show the add domain `AlertDialog`. AppCompatDialogFragment addDomainDialog = new AddDomainDialog(); - addDomainDialog.show(supportFragmentManager, getResources().getString(R.string.add_domain)); + addDomainDialog.show(supportFragmentManager, resources.getString(R.string.add_domain)); }); } @@ -266,7 +273,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo if (twoPanedMode) { // The device is in two-paned mode. // Save the current domain settings if the domain settings fragment is displayed. if (findViewById(R.id.domain_settings_scrollview) != null) { - saveDomainSettings(); + saveDomainSettings(coordinatorLayout, resources); } // Dismiss the undo delete `SnackBar` if it is shown. @@ -288,13 +295,13 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo } } else if (closeOnBack) { // Go directly back to the main WebView activity because the domains activity was launched from the options menu. // Save the current domain settings. - saveDomainSettings(); + saveDomainSettings(coordinatorLayout, resources); // Go home. NavUtils.navigateUpFromSameTask(this); } else if (findViewById(R.id.domain_settings_scrollview) != null) { // The device is in single-paned mode and the domain settings fragment is displayed. // Save the current domain settings. - saveDomainSettings(); + saveDomainSettings(coordinatorLayout, resources); // Display the domains list fragment. DomainsListFragment domainsListFragment = new DomainsListFragment(); @@ -505,7 +512,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo // Store the current `DomainSettingsFragment` state in `outState`. if (findViewById(R.id.domain_settings_scrollview) != null) { // `DomainSettingsFragment` is displayed. // Save any changes that have been made to the domain settings. - saveDomainSettings(); + saveDomainSettings(coordinatorLayout, resources); // Store `DomainSettingsDisplayed`. outState.putBoolean("domainSettingsDisplayed", true); @@ -524,7 +531,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo if (twoPanedMode) { // The device is in two-paned mode. // Save the current domain settings if the domain settings fragment is displayed. if (findViewById(R.id.domain_settings_scrollview) != null) { - saveDomainSettings(); + saveDomainSettings(coordinatorLayout, resources); } // Dismiss the undo delete SnackBar if it is shown. @@ -543,13 +550,13 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo } } else if (closeOnBack) { // Go directly back to the main WebView activity because the domains activity was launched from the options menu. // Save the current domain settings. - saveDomainSettings(); + saveDomainSettings(coordinatorLayout, resources); // Pass `onBackPressed()` to the system. super.onBackPressed(); } else if (findViewById(R.id.domain_settings_scrollview) != null) { // The device is in single-paned mode and domain settings fragment is displayed. // Save the current domain settings. - saveDomainSettings(); + saveDomainSettings(coordinatorLayout, resources); // Display the domains list fragment. DomainsListFragment domainsListFragment = new DomainsListFragment(); @@ -619,26 +626,26 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo } } - private void saveDomainSettings() { + public void saveDomainSettings(View view, Resources resources) { // Get handles for the domain settings. - EditText domainNameEditText = findViewById(R.id.domain_settings_name_edittext); - Switch javaScriptSwitch = findViewById(R.id.domain_settings_javascript_switch); - Switch firstPartyCookiesSwitch = findViewById(R.id.domain_settings_first_party_cookies_switch); - Switch thirdPartyCookiesSwitch = findViewById(R.id.domain_settings_third_party_cookies_switch); - Switch domStorageSwitch = findViewById(R.id.domain_settings_dom_storage_switch); - Switch formDataSwitch = findViewById(R.id.domain_settings_form_data_switch); - Switch easyListSwitch = findViewById(R.id.domain_settings_easylist_switch); - Switch easyPrivacySwitch = findViewById(R.id.domain_settings_easyprivacy_switch); - Switch fanboysAnnoyanceSwitch = findViewById(R.id.domain_settings_fanboys_annoyance_list_switch); - Switch fanboysSocialBlockingSwitch = findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch); - Spinner userAgentSpinner = findViewById(R.id.domain_settings_user_agent_spinner); - EditText customUserAgentEditText = findViewById(R.id.domain_settings_custom_user_agent_edittext); - Spinner fontSizeSpinner = findViewById(R.id.domain_settings_font_size_spinner); - Spinner displayWebpageImagesSpinner = findViewById(R.id.domain_settings_display_webpage_images_spinner); - Spinner nightModeSpinner = findViewById(R.id.domain_settings_night_mode_spinner); - Switch pinnedSslCertificateSwitch = findViewById(R.id.domain_settings_pinned_ssl_certificate_switch); - RadioButton savedSslCertificateRadioButton = findViewById(R.id.saved_ssl_certificate_radiobutton); - RadioButton currentWebsiteCertificateRadioButton = findViewById(R.id.current_website_certificate_radiobutton); + EditText domainNameEditText = view.findViewById(R.id.domain_settings_name_edittext); + Switch javaScriptSwitch = view.findViewById(R.id.domain_settings_javascript_switch); + Switch firstPartyCookiesSwitch = view.findViewById(R.id.domain_settings_first_party_cookies_switch); + Switch thirdPartyCookiesSwitch = view.findViewById(R.id.domain_settings_third_party_cookies_switch); + Switch domStorageSwitch = view.findViewById(R.id.domain_settings_dom_storage_switch); + Switch formDataSwitch = view.findViewById(R.id.domain_settings_form_data_switch); + Switch easyListSwitch = view.findViewById(R.id.domain_settings_easylist_switch); + Switch easyPrivacySwitch = view.findViewById(R.id.domain_settings_easyprivacy_switch); + Switch fanboysAnnoyanceSwitch = view.findViewById(R.id.domain_settings_fanboys_annoyance_list_switch); + Switch fanboysSocialBlockingSwitch = view.findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch); + Spinner userAgentSpinner = view.findViewById(R.id.domain_settings_user_agent_spinner); + EditText customUserAgentEditText = view.findViewById(R.id.domain_settings_custom_user_agent_edittext); + Spinner fontSizeSpinner = view.findViewById(R.id.domain_settings_font_size_spinner); + Spinner displayWebpageImagesSpinner = view.findViewById(R.id.domain_settings_display_webpage_images_spinner); + Spinner nightModeSpinner = view.findViewById(R.id.domain_settings_night_mode_spinner); + Switch pinnedSslCertificateSwitch = view.findViewById(R.id.domain_settings_pinned_ssl_certificate_switch); + RadioButton savedSslCertificateRadioButton = view.findViewById(R.id.saved_ssl_certificate_radiobutton); + RadioButton currentWebsiteCertificateRadioButton = view.findViewById(R.id.current_website_certificate_radiobutton); // Extract the data for the domain settings. String domainNameString = domainNameEditText.getText().toString(); @@ -651,27 +658,43 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo boolean easyPrivacyEnabled = easyPrivacySwitch.isChecked(); boolean fanboysAnnoyanceEnabled = fanboysAnnoyanceSwitch.isChecked(); boolean fanboysSocialBlockingEnabled = fanboysSocialBlockingSwitch.isChecked(); - int userAgentPositionInt = userAgentSpinner.getSelectedItemPosition(); - int fontSizePositionInt = fontSizeSpinner.getSelectedItemPosition(); + int userAgentPosition = userAgentSpinner.getSelectedItemPosition(); + int fontSizePosition = fontSizeSpinner.getSelectedItemPosition(); int displayWebpageImagesInt = displayWebpageImagesSpinner.getSelectedItemPosition(); int nightModeInt = nightModeSpinner.getSelectedItemPosition(); boolean pinnedSslCertificate = pinnedSslCertificateSwitch.isChecked(); - // Get the data for the `Spinners` from the entry values string arrays. - String userAgentString = getResources().getStringArray(R.array.domain_settings_user_agent_entry_values)[userAgentPositionInt]; - int fontSizeInt = Integer.parseInt(getResources().getStringArray(R.array.domain_settings_font_size_entry_values)[fontSizePositionInt]); + // Initialize the user agent name string. + String userAgentName; + + // Set the user agent name. + switch (userAgentPosition) { + case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT: + // Set the user agent name to be `System default user agent`. + userAgentName = resources.getString(R.string.system_default_user_agent); + break; - // Check to see if we are using a custom user agent. - if (userAgentString.equals("Custom user agent")) { - // Set `userAgentString` to the custom user agent string. - userAgentString = customUserAgentEditText.getText().toString(); + case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT: + // Set the user agent name to be the custom user agent. + userAgentName = customUserAgentEditText.getText().toString(); + break; + + default: + // Get the array of user agent names. + String[] userAgentNameArray = resources.getStringArray(R.array.user_agent_names); + + // Set the user agent name from the array. The domain spinner has one more entry than the name array, so the position must be decremented. + userAgentName = userAgentNameArray[userAgentPosition - 1]; } + // Get the font size integer. + int fontSizeInt = Integer.parseInt(resources.getStringArray(R.array.domain_settings_font_size_entry_values)[fontSizePosition]); + // Save the domain settings. if (savedSslCertificateRadioButton.isChecked()) { // The current certificate is being used. // Update the database except for the certificate. domainsDatabaseHelper.updateDomainExceptCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled, - domStorageEnabled, formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt, + domStorageEnabled, formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentName, fontSizeInt, displayWebpageImagesInt, nightModeInt, pinnedSslCertificate); } else if (currentWebsiteCertificateRadioButton.isChecked()) { // The certificate is being updated with the current website certificate. // Get the current website SSL certificate. @@ -689,13 +712,13 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo // Update the database. domainsDatabaseHelper.updateDomainWithCertificate(currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled, domStorageEnabled, - formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt, nightModeInt, + formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentName, fontSizeInt, displayWebpageImagesInt, nightModeInt, pinnedSslCertificate, issuedToCommonName, issuedToOrganization, issuedToOrganizationalUnit, issuedByCommonName, issuedByOrganization, issuedByOrganizationalUnit, startDateLong, endDateLong); } else { // No certificate is selected. // Update the database, with PINNED_SSL_CERTIFICATE set to false. domainsDatabaseHelper.updateDomainExceptCertificate(currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled, domStorageEnabled, - formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt, nightModeInt, + formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentName, fontSizeInt, displayWebpageImagesInt, nightModeInt, false); } } diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java index 4d6d6b18..968e897c 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -96,6 +96,7 @@ import android.webkit.WebStorage; import android.webkit.WebView; import android.webkit.WebViewClient; import android.webkit.WebViewDatabase; +import android.widget.ArrayAdapter; import android.widget.CursorAdapter; import android.widget.EditText; import android.widget.FrameLayout; @@ -212,6 +213,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook public static Date pinnedDomainSslStartDate; public static Date pinnedDomainSslEndDate; + // The user agent constants are public static so they can be accessed from `SettingsActivity` and `DomainsActivity`. + public final static int UNRECOGNIZED_USER_AGENT = -1; + public final static int SETTINGS_WEBVIEW_DEFAULT_USER_AGENT = 1; + public final static int SETTINGS_CUSTOM_USER_AGENT = 12; + public final static int DOMAINS_SYSTEM_DEFAULT_USER_AGENT = 0; + public final static int DOMAINS_WEBVIEW_DEFAULT_USER_AGENT = 2; + public final static int DOMAINS_CUSTOM_USER_AGENT = 13; // `appBar` is used in `onCreate()`, `onOptionsItemSelected()`, `closeFindOnPage()`, and `applyAppSettings()`. private ActionBar appBar; @@ -290,7 +298,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook private Runtime privacyBrowserRuntime; // `proxyThroughOrbot` is used in `onRestart()` and `applyAppSettings()`. - boolean proxyThroughOrbot; + private boolean proxyThroughOrbot; // `incognitoModeEnabled` is used in `onCreate()` and `applyAppSettings()`. private boolean incognitoModeEnabled; @@ -410,6 +418,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // `downloadImageUrl` is used in `onCreateContextMenu()` and `onRequestPermissionResult()`. private String downloadImageUrl; + // The user agent variables are used in `onCreate()` and `applyDomainSettings()`. + private ArrayAdapter userAgentNamesArray; + private String[] userAgentDataArray; + // The request codes are used in `onCreate()`, `onCreateContextMenu()`, `onCloseDownloadLocationPermissionDialog()`, and `onRequestPermissionResult()`. private final int DOWNLOAD_FILE_REQUEST_CODE = 1; private final int DOWNLOAD_IMAGE_REQUEST_CODE = 2; @@ -1069,10 +1081,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook saveFormDataEnabled = false; nightMode = false; - // Initialize `webViewTitle`. + // Initialize the WebView title. webViewTitle = getString(R.string.no_title); - // Initialize `favoriteIconBitmap`. `ContextCompat` must be used until API >= 21. + // Initialize the favorite icon bitmap. `ContextCompat` must be used until API >= 21. Drawable favoriteIconDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.world); BitmapDrawable favoriteIconBitmapDrawable = (BitmapDrawable) favoriteIconDrawable; assert favoriteIconBitmapDrawable != null; @@ -1083,6 +1095,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook favoriteIconBitmap = favoriteIconDefaultBitmap; } + // Initialize the user agent array adapter and string array. + userAgentNamesArray = ArrayAdapter.createFromResource(this, R.array.user_agent_names, R.layout.domain_settings_spinner_item); + userAgentDataArray = getResources().getStringArray(R.array.user_agent_data); + // Apply the app settings from the shared preferences. applyAppSettings(); @@ -1739,7 +1755,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Create an intent to launch the domains activity. Intent domainsIntent = new Intent(this, DomainsActivity.class); - // Put extra information instructing the domains activity to directly load the current domain and close on back instread of returning to the domains list. + // Put extra information instructing the domains activity to directly load the current domain and close on back instead of returning to the domains list. domainsIntent.putExtra("loadDomain", domainSettingsDatabaseId); domainsIntent.putExtra("closeOnBack", true); @@ -3267,7 +3283,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook } } - // `reloadWebsite` is used if returnig from the Domains activity. Otherwise JavaScript might not function correctly if it is newly enabled. + // `reloadWebsite` is used if returning from the Domains activity. Otherwise JavaScript might not function correctly if it is newly enabled. // The deprecated `.getDrawable()` must be used until the minimum API >= 21. @SuppressWarnings("deprecation") private void applyDomainSettings(String url, boolean resetFavoriteIcon, boolean reloadWebsite) { @@ -3359,7 +3375,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Store the general preference information. String defaultFontSizeString = sharedPreferences.getString("default_font_size", "100"); - String defaultUserAgentString = sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0"); + String defaultUserAgentName = sharedPreferences.getString("user_agent", "Privacy Browser"); String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0"); nightMode = sharedPreferences.getBoolean("night_mode", false); @@ -3379,7 +3395,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook easyPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1); fanboysAnnoyanceListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1); fanboysSocialBlockingListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1); - String userAgentString = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)); + String userAgentName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)); int fontSize = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE)); displayWebpageImagesInt = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES)); int nightModeInt = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE)); @@ -3445,37 +3461,53 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Only set the user agent if the webpage is not currently loading. Otherwise, changing the user agent on redirects can cause the original website to reload. // if (!urlIsLoading) { - switch (userAgentString) { - case "System default user agent": - // Set the user agent according to the system default. - switch (defaultUserAgentString) { - case "WebView default user agent": - // Set the user agent to `""`, which uses the default value. - mainWebView.getSettings().setUserAgentString(""); - break; - - case "Custom user agent": - // Set the custom user agent. - mainWebView.getSettings().setUserAgentString(defaultCustomUserAgentString); - break; - - default: - // Use the selected user agent. - mainWebView.getSettings().setUserAgentString(defaultUserAgentString); - } - break; - - case "WebView default user agent": - // Set the user agent to `""`, which uses the default value. - mainWebView.getSettings().setUserAgentString(""); - break; - - default: - // Use the selected user agent. - mainWebView.getSettings().setUserAgentString(userAgentString); + // Set the user agent. + if (userAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent. + // Get the array position of the default user agent name. + int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName); + + // Set the user agent according to the system default. + switch (defaultUserAgentArrayPosition) { + case UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list. + // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names. + mainWebView.getSettings().setUserAgentString(defaultUserAgentName); + break; + + case SETTINGS_WEBVIEW_DEFAULT_USER_AGENT: + // Set the user agent to `""`, which uses the default value. + mainWebView.getSettings().setUserAgentString(""); + break; + + case SETTINGS_CUSTOM_USER_AGENT: + // Set the custom user agent. + mainWebView.getSettings().setUserAgentString(defaultCustomUserAgentString); + break; + + default: + // Get the user agent string from the user agent data array + mainWebView.getSettings().setUserAgentString(userAgentDataArray[defaultUserAgentArrayPosition]); + } + } else { // Set the user agent according to the stored name. + // Get the array position of the user agent name. + int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName); + + switch (userAgentArrayPosition) { + case UNRECOGNIZED_USER_AGENT: // The user agent name contains a custom user agent. + mainWebView.getSettings().setUserAgentString(userAgentName); + break; + + case SETTINGS_WEBVIEW_DEFAULT_USER_AGENT: + // Set the user agent to `""`, which uses the default value. + mainWebView.getSettings().setUserAgentString(""); + break; + + default: + // Get the user agent string from the user agent data array. + mainWebView.getSettings().setUserAgentString(userAgentDataArray[userAgentArrayPosition]); + } } - // Store the applied user agent string. + // Store the applied user agent string, which is used in the View Source activity. appliedUserAgentString = mainWebView.getSettings().getUserAgentString(); } @@ -3529,23 +3561,32 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Only set the user agent if the webpage is not currently loading. Otherwise, changing the user agent on redirects can cause the original website to reload. // if (!urlIsLoading) { - switch (defaultUserAgentString) { - case "WebView default user agent": + // Get the array position of the user agent name. + int userAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName); + + // Set the user agent. + switch (userAgentArrayPosition) { + case UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list. + // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names. + mainWebView.getSettings().setUserAgentString(defaultUserAgentName); + break; + + case SETTINGS_WEBVIEW_DEFAULT_USER_AGENT: // Set the user agent to `""`, which uses the default value. mainWebView.getSettings().setUserAgentString(""); break; - case "Custom user agent": + case SETTINGS_CUSTOM_USER_AGENT: // Set the custom user agent. mainWebView.getSettings().setUserAgentString(defaultCustomUserAgentString); break; default: - // Use the selected user agent. - mainWebView.getSettings().setUserAgentString(defaultUserAgentString); + // Get the user agent string from the user agent data array + mainWebView.getSettings().setUserAgentString(userAgentDataArray[userAgentArrayPosition]); } - // Store the applied user agent string. + // Store the applied user agent string, which is used in the View Source activity. appliedUserAgentString = mainWebView.getSettings().getUserAgentString(); } diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java index 34687487..dd138595 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java @@ -92,7 +92,7 @@ public class DomainSettingsFragment extends Fragment { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); // Store the default settings. - final String defaultUserAgentString = sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0"); + final String defaultUserAgentName = sharedPreferences.getString("user_agent", "Privacy Browser"); final String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0"); String defaultFontSizeString = sharedPreferences.getString("default_font_size", "100"); final boolean defaultDisplayWebpageImagesBoolean = sharedPreferences.getBoolean("display_website_images", true); @@ -182,7 +182,7 @@ public class DomainSettingsFragment extends Fragment { int easyPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)); int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)); int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)); - final String currentUserAgentString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)); + final String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)); int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE)); int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES)); int nightModeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE)); @@ -208,21 +208,20 @@ public class DomainSettingsFragment extends Fragment { } // Create `ArrayAdapters` for the `Spinners`and their `entry values`. - ArrayAdapter userAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_user_agent_entries, R.layout.domain_settings_spinner_item); - final ArrayAdapter userAgentEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_user_agent_entry_values, R.layout.domain_settings_spinner_item); + ArrayAdapter translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.domain_settings_spinner_item); ArrayAdapter fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entries, R.layout.domain_settings_spinner_item); ArrayAdapter fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entry_values, R.layout.domain_settings_spinner_item); final ArrayAdapter displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.domain_settings_spinner_item); ArrayAdapter nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.domain_settings_spinner_item); // Set the `DropDownViewResource` on the `Spinners`. - userAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item); + translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item); fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item); displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item); nightModeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item); // Set the `ArrayAdapters` for the `Spinners`. - userAgentSpinner.setAdapter(userAgentArrayAdapter); + userAgentSpinner.setAdapter(translatedUserAgentArrayAdapter); fontSizeSpinner.setAdapter(fontSizeArrayAdapter); displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter); nightModeSpinner.setAdapter(nightModeArrayAdapter); @@ -583,59 +582,69 @@ public class DomainSettingsFragment extends Fragment { WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview); final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString(); - // Get the position of the user agent in `userAgentEntryValuesArrayAdapter`. - int userAgentArrayPosition = userAgentEntryValuesArrayAdapter.getPosition(currentUserAgentString); + // Get a handle for the user agent array adapter. This array does not contain the `System default` entry. + ArrayAdapter userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.domain_settings_spinner_item); - // Set the user agent. - if (userAgentArrayPosition == -1) { // We are using a custom `userAgentString`. - // Set `userAgentSpinner` to `Custom`. - userAgentSpinner.setSelection(userAgentEntryValuesArrayAdapter.getPosition("Custom user agent")); + // Get the positions of the user agent and the default user agent. + int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName); + int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName); - // Hide `userAgentTextView`. + // Get a handle for the user agent data array. This array does not contain the `System default` entry. + String[] userAgentDataArray = resources.getStringArray(R.array.user_agent_data); + + // Set the user agent text. + if (currentUserAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent. + // Set the user agent according to the system default. + switch (defaultUserAgentArrayPosition) { + case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list. + // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names. + userAgentTextView.setText(defaultUserAgentName); + break; + + case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT: + // Display the `WebView` default user agent. + userAgentTextView.setText(webViewDefaultUserAgentString); + break; + + case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT: + // Display the custom user agent. + userAgentTextView.setText(defaultCustomUserAgentString); + break; + + default: + // Get the user agent string from the user agent data array. + userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]); + } + } else if (userAgentArrayPosition == MainWebViewActivity.UNRECOGNIZED_USER_AGENT) { // A custom user agent is stored in the current user agent name. + // Set the user agent spinner to `Custom user agent`. + userAgentSpinner.setSelection(MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT); + + // Hide the user agent TextView. userAgentTextView.setVisibility(View.GONE); - // Show `customUserAgentEditText` and set `userAgentString` as the text. + // Show the custom user agent EditText and set the current user agent name as the text. customUserAgentEditText.setVisibility(View.VISIBLE); - customUserAgentEditText.setText(currentUserAgentString); - } else{ // We are using one of the preset user agents. - // Set the `userAgentSpinner` selection. - userAgentSpinner.setSelection(userAgentArrayPosition); + customUserAgentEditText.setText(currentUserAgentName); + } else { // The user agent name contains one of the canonical user agents. + // Set the user agent spinner selection. The spinner has one more entry at the beginning than the user agent data array, so the position must be incremented. + userAgentSpinner.setSelection(userAgentArrayPosition + 1); - // Show `userAgentTextView`. + // Show the user agent TextView. userAgentTextView.setVisibility(View.VISIBLE); - // Hide `customUserAgentEditText`. + // Hide the custom user agent EditText. customUserAgentEditText.setVisibility(View.GONE); // Set the user agent text. - switch (currentUserAgentString) { - case "System default user agent": - // Display the user agent text string. - switch (defaultUserAgentString) { - case "WebView default user agent": - // Display the `WebView` default user agent. - userAgentTextView.setText(webViewDefaultUserAgentString); - break; - - case "Custom user agent": - // Display the custom user agent. - userAgentTextView.setText(defaultCustomUserAgentString); - break; - - default: - // Display the text from `defaultUserAgentString`. - userAgentTextView.setText(defaultUserAgentString); - } - break; - - case "WebView default user agent": - // Display the `WebView` default user agent. + switch (userAgentArrayPosition) { + case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT: + // Display the WebView default user agent. userAgentTextView.setText(webViewDefaultUserAgentString); break; default: - // Display the text from `currentUserAgentString`. - userAgentTextView.setText(currentUserAgentString); + // Get the user agent string from the user agent data array. The spinner has one more entry at the beginning than the user agent data array, so the position must be incremented. + userAgentTextView.setText(userAgentDataArray[userAgentArrayPosition + 1]); } } @@ -1210,58 +1219,60 @@ public class DomainSettingsFragment extends Fragment { userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - // Store the new user agent string. - String newUserAgentString = resources.getStringArray(R.array.domain_settings_user_agent_entry_values)[position]; - // Set the new user agent. - switch (newUserAgentString) { - case "System default user agent": - // Show `userAgentTextView`. + switch (position) { + case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT: + // Show the user agent TextView. userAgentTextView.setVisibility(View.VISIBLE); - // Hide `customUserAgentEditText`. + // Hide the custom user agent EditText. customUserAgentEditText.setVisibility(View.GONE); // Set the user text. - switch (defaultUserAgentString) { - case "WebView default user agent": + switch (defaultUserAgentArrayPosition) { + case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list. + // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names. + userAgentTextView.setText(defaultUserAgentName); + break; + + case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT: // Display the `WebView` default user agent. userAgentTextView.setText(webViewDefaultUserAgentString); break; - case "Custom user agent": + case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT: // Display the custom user agent. userAgentTextView.setText(defaultCustomUserAgentString); break; default: - // Display the text from `defaultUserAgentString`. - userAgentTextView.setText(defaultUserAgentString); + // Get the user agent string from the user agent data array. + userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]); } break; - case "WebView default user agent": - // Show `userAgentTextView` and set the text. + case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT: + // Show the user agent TextView and set the text. userAgentTextView.setVisibility(View.VISIBLE); userAgentTextView.setText(webViewDefaultUserAgentString); - // Hide `customUserAgentEditText`. + // Hide the custom user agent EditTex. customUserAgentEditText.setVisibility(View.GONE); break; - case "Custom user agent": - // Hide `userAgentTextView`. + case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT: + // Hide the user agent TextView. userAgentTextView.setVisibility(View.GONE); - // Show `customUserAgentEditText` and set `userAgentString` as the text. + // Show the custom user agent EditText and set the current user agent name as the text. customUserAgentEditText.setVisibility(View.VISIBLE); - customUserAgentEditText.setText(currentUserAgentString); + customUserAgentEditText.setText(currentUserAgentName); break; default: - // Show `userAgentTextView` and set the text. + // Show the user agent TextView and set the text from the user agent data array, which has one less entry than the spinner, so the position must be decremented. userAgentTextView.setVisibility(View.VISIBLE); - userAgentTextView.setText(newUserAgentString); + userAgentTextView.setText(userAgentDataArray[position - 1]); // Hide `customUserAgentEditText`. customUserAgentEditText.setVisibility(View.GONE); diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainsListFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainsListFragment.java index 54b09ee3..3caccf52 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainsListFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainsListFragment.java @@ -19,27 +19,21 @@ package com.stoutner.privacybrowser.fragments; -import android.net.http.SslCertificate; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; -// We have to use `android.support.v4.app.Fragment` until minimum API >= 23. Otherwise we cannot call `getContext()`. +// `android.support.v4.app.Fragment` must be used until minimum API >= 23. Otherwise `getContext()` cannot be called. import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; -import android.widget.EditText; import android.widget.ListView; -import android.widget.RadioButton; -import android.widget.Spinner; -import android.widget.Switch; import com.stoutner.privacybrowser.R; import com.stoutner.privacybrowser.activities.DomainsActivity; import com.stoutner.privacybrowser.activities.MainWebViewActivity; -import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper; public class DomainsListFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -49,9 +43,6 @@ public class DomainsListFragment extends Fragment { // Initialize `domainsListView`. ListView domainsListView = domainsListFragmentView.findViewById(R.id.domains_listview); - // Initialize the database handler. The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`. - final DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(getContext(), null, null, 0); - // Remove the incorrect lint error below that `.getSupportFragmentManager()` might be null. assert getActivity() != null; @@ -68,87 +59,14 @@ public class DomainsListFragment extends Fragment { // Save the current domain settings if operating in two-paned mode and a domain is currently selected. if (DomainsActivity.twoPanedMode && DomainsActivity.deleteMenuItem.isEnabled()) { + // Get a handle for the domain settings fragment view. View domainSettingsFragmentView = supportFragmentManager.findFragmentById(R.id.domain_settings_fragment_container).getView(); - assert domainSettingsFragmentView != null; - - // Get handles for the domain settings. - EditText domainNameEditText = domainSettingsFragmentView.findViewById(R.id.domain_settings_name_edittext); - Switch javaScriptSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_javascript_switch); - Switch firstPartyCookiesSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_first_party_cookies_switch); - Switch thirdPartyCookiesSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_third_party_cookies_switch); - Switch domStorageSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_dom_storage_switch); - Switch formDataSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_form_data_switch); - Switch easyListSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_easylist_switch); - Switch easyPrivacySwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_easyprivacy_switch); - Switch fanboysAnnoyanceSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_fanboys_annoyance_list_switch); - Switch fanboysSocialBlockingSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch); - Spinner userAgentSpinner = domainSettingsFragmentView.findViewById(R.id.domain_settings_user_agent_spinner); - EditText customUserAgentEditText = domainSettingsFragmentView.findViewById(R.id.domain_settings_custom_user_agent_edittext); - Spinner fontSizeSpinner = domainSettingsFragmentView.findViewById(R.id.domain_settings_font_size_spinner); - Spinner displayWebpageImagesSpinner = domainSettingsFragmentView.findViewById(R.id.domain_settings_display_webpage_images_spinner); - Spinner nightModeSpinner = domainSettingsFragmentView.findViewById(R.id.domain_settings_night_mode_spinner); - Switch pinnedSslCertificateSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_pinned_ssl_certificate_switch); - RadioButton savedSslCertificateRadioButton = domainSettingsFragmentView.findViewById(R.id.saved_ssl_certificate_radiobutton); - RadioButton currentWebsiteCertificateRadioButton = domainSettingsFragmentView.findViewById(R.id.current_website_certificate_radiobutton); - - // Extract the data for the domain settings. - String domainNameString = domainNameEditText.getText().toString(); - boolean javaScriptEnabled = javaScriptSwitch.isChecked(); - boolean firstPartyCookiesEnabled = firstPartyCookiesSwitch.isChecked(); - boolean thirdPartyCookiesEnabled = thirdPartyCookiesSwitch.isChecked(); - boolean domStorageEnabled = domStorageSwitch.isChecked(); - boolean formDataEnabled = formDataSwitch.isChecked(); - boolean easyListEnabled = easyListSwitch.isChecked(); - boolean easyPrivacyEnabled = easyPrivacySwitch.isChecked(); - boolean fanboysAnnoyanceEnabled = fanboysAnnoyanceSwitch.isChecked(); - boolean fanboysSocialBlockingEnabled = fanboysSocialBlockingSwitch.isChecked(); - int userAgentPositionInt = userAgentSpinner.getSelectedItemPosition(); - int fontSizePositionInt = fontSizeSpinner.getSelectedItemPosition(); - int displayWebpageImagesInt = displayWebpageImagesSpinner.getSelectedItemPosition(); - int nightModeInt = nightModeSpinner.getSelectedItemPosition(); - boolean pinnedSslCertificate = pinnedSslCertificateSwitch.isChecked(); - - // Get the data for the `Spinners` from the entry values string arrays. - String userAgentString = getResources().getStringArray(R.array.domain_settings_user_agent_entry_values)[userAgentPositionInt]; - int fontSizeInt = Integer.parseInt(getResources().getStringArray(R.array.domain_settings_font_size_entry_values)[fontSizePositionInt]); - - // Check to see if we are using a custom user agent. - if (userAgentString.equals("Custom user agent")) { - // Set `userAgentString` to the custom user agent string. - userAgentString = customUserAgentEditText.getText().toString(); - } + + // Get a handle for the domains activity. + DomainsActivity domainsActivity = new DomainsActivity(); // Save the domain settings. - if (savedSslCertificateRadioButton.isChecked()) { // The current certificate is being used. - // Update the database except for the certificate. - domainsDatabaseHelper.updateDomainExceptCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled, - domStorageEnabled, formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt, - nightModeInt, pinnedSslCertificate); - } else if (currentWebsiteCertificateRadioButton.isChecked()) { // The certificate is being updated with the current website certificate. - // Get the current website SSL certificate. - SslCertificate currentWebsiteSslCertificate = MainWebViewActivity.sslCertificate; - - // Store the values from the SSL certificate. - String issuedToCommonName = currentWebsiteSslCertificate.getIssuedTo().getCName(); - String issuedToOrganization = currentWebsiteSslCertificate.getIssuedTo().getOName(); - String issuedToOrganizationalUnit = currentWebsiteSslCertificate.getIssuedTo().getUName(); - String issuedByCommonName = currentWebsiteSslCertificate.getIssuedBy().getCName(); - String issuedByOrganization = currentWebsiteSslCertificate.getIssuedBy().getOName(); - String issuedByOrganizationalUnit = currentWebsiteSslCertificate.getIssuedBy().getUName(); - long startDateLong = currentWebsiteSslCertificate.getValidNotBeforeDate().getTime(); - long endDateLong = currentWebsiteSslCertificate.getValidNotAfterDate().getTime(); - - // Update the database. - domainsDatabaseHelper.updateDomainWithCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled, - domStorageEnabled, formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt, - nightModeInt, pinnedSslCertificate, issuedToCommonName, issuedToOrganization, issuedToOrganizationalUnit, issuedByCommonName, issuedByOrganization, - issuedByOrganizationalUnit, startDateLong, endDateLong); - } else { // No certificate is selected. - // Update the database, with PINNED_SSL_CERTIFICATE set to false. - domainsDatabaseHelper.updateDomainExceptCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled, - domStorageEnabled, formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt, - nightModeInt, false); - } + domainsActivity.saveDomainSettings(domainSettingsFragmentView, getResources()); } // Store the new `currentDomainDatabaseId`, converting it from `long` to `int` to match the format of the domains database. diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java index cff09bee..55b852e1 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java @@ -20,6 +20,7 @@ package com.stoutner.privacybrowser.fragments; import android.annotation.SuppressLint; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; @@ -29,6 +30,7 @@ import android.preference.PreferenceFragment; import android.view.LayoutInflater; import android.view.View; import android.webkit.WebView; +import android.widget.ArrayAdapter; import com.stoutner.privacybrowser.R; import com.stoutner.privacybrowser.activities.MainWebViewActivity; @@ -42,6 +44,9 @@ public class SettingsFragment extends PreferenceFragment { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); + // Get a handle for the context. + Context context = getActivity().getApplicationContext(); + // Initialize savedPreferences. savedPreferences = getPreferenceScreen().getSharedPreferences(); @@ -117,27 +122,42 @@ public class SettingsFragment extends PreferenceFragment { @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false); final WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview); - // Set the current user-agent as the summary text for the "user_agent" preference when the preference screen is loaded. - switch (savedPreferences.getString("user_agent", "PrivacyBrowser/1.0")) { - case "WebView default user agent": + // Get the user agent arrays. + ArrayAdapter userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.domain_settings_spinner_item); + String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names); + String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data); + + // Get the current user agent name from the preference. + String userAgentName = savedPreferences.getString("user_agent", "Privacy Browser"); + + // Get the array position of the user agent name. + int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName); + + // Populate the user agent summary. + switch (userAgentArrayPosition) { + case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list. + // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names. Use the current user agent entry name as the summary. + userAgentPreference.setSummary(userAgentName); + break; + + case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT: // Get the user agent text from the webview (which changes based on the version of Android and WebView installed). - userAgentPreference.setSummary(bareWebView.getSettings().getUserAgentString()); + userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString()); break; - case "Custom user agent": - // We can't use the string from the array because it is referenced in code and can't be translated. + case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT: + // Set the summary text. userAgentPreference.setSummary(R.string.custom_user_agent); break; default: - // Display the user agent from the preference as the summary text. - userAgentPreference.setSummary(savedPreferences.getString("user_agent", "PrivacyBrowser/1.0")); - break; + // Get the user agent summary from the user agent data array. + userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]); } - // Set the summary text for "customUserAgentPreference" (the default is `PrivacyBrowser/1.0`) and enable it if `userAgentPreference` it set to `Custom user agent`. + // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom. customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0")); - customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals("Custom user agent")); + customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent))); // Set the Tor homepage URL as the summary text for the `tor_homepage` preference when the preference screen is loaded. The default is DuckDuckGo: `https://3g2upl4pq6kufc4m.onion`. @@ -726,17 +746,25 @@ public class SettingsFragment extends PreferenceFragment { } case "user_agent": - String userAgentString = sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0"); + // Get the new user agent name. + String newUserAgentName = sharedPreferences.getString("user_agent", "Privacy Browser"); + + // Get the array position for the new user agent name. + int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName); - switch (userAgentString) { - case "WebView default user agent": - // Display the user agent as the summary text for `userAgentPreference`. - userAgentPreference.setSummary(bareWebView.getSettings().getUserAgentString()); + // Get the translated new user agent name. + String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition]; - // Disable `customUserAgentPreference`. + // Populate the user agent summary. + switch (newUserAgentArrayPosition) { + case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT: + // Get the user agent text from the webview (which changes based on the version of Android and WebView installed). + userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString()); + + // Disable the custom user agent preference. customUserAgentPreference.setEnabled(false); - // Set the `customUserAgentPreference` icon according to the theme. + // Set the custom user agent preference icon according to the theme. if (MainWebViewActivity.darkTheme) { customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark); } else { @@ -744,14 +772,14 @@ public class SettingsFragment extends PreferenceFragment { } break; - case "Custom user agent": - // Display `Custom user agent` as the summary text for `userAgentPreference`. + case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT: + // Set the summary text. userAgentPreference.setSummary(R.string.custom_user_agent); - // Enable `customUserAgentPreference`. + // Enable the custom user agent preference. customUserAgentPreference.setEnabled(true); - // Set the `customUserAgentPreference` icon according to the theme. + // Set the custom user agent preference icon according to the theme. if (MainWebViewActivity.darkTheme) { customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark); } else { @@ -760,24 +788,23 @@ public class SettingsFragment extends PreferenceFragment { break; default: - // Display the user agent as the summary text for `userAgentPreference`. - userAgentPreference.setSummary(sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0")); + // Get the user agent summary from the user agent data array. + userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]); - // Disable `customUserAgentPreference`. + // Disable the custom user agent preference. customUserAgentPreference.setEnabled(false); - // Set the `customUserAgentPreference` icon according to the theme. + // Set the custom user agent preference icon according to the theme. if (MainWebViewActivity.darkTheme) { customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark); } else { customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light); } - break; } break; case "custom_user_agent": - // Set the new custom user agent as the summary text for `custom_user_agent`. The default is `PrivacyBrowser/1.0`. + // Set the new custom user agent as the summary text for the preference. customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0")); break; diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 805eda38..7fe51aaa 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -170,7 +170,7 @@ Fehler Über Quelltext Weil Androids WebView keine Quelltext-Informationen zur Verfügung stellt, muss eine separate a separate Serveranfrage mit system tools gestellt werden, - die die hier dargestellten Daten erhält. Deshalb können Unterschiede zwischen diesen Daten und der mit Webview dargestellten Webseite auftreten. + die hier dargestellten Daten erhält. Deshalb können Unterschiede zwischen diesen Daten und der mit Webview dargestellten Webseite auftreten. Es ist geplant, mit Version 4.x eine eigene Engine einzuführen, die diese Einschränkungen umgeht. @@ -263,37 +263,37 @@ Formulardaten standardmäßig speichern Mit gespeicherten Formulardaten können Formularfelder auf Websites automatisch ausgefüllt werden. User Agent - - Privacy Browser 1.0 + + Privacy Browser WebView-Standard - Firefox 56 auf Android 8.0.0 - Chrome 62 auf Android 8.0.0 - Safari 11 auf iOS 11.1 - Firefox 52 auf Linux - Chromium 61 auf Linux - Firefox 56 auf Windows 10 - Chrome 62 auf Windows 10 - Edge 16 auf Windows 10 - Internet Explorer 11 auf Windows 10 - Safari 11.0.1 auf macOS 10.13.1 + Firefox auf Android + Chrome auf Android + Safari auf iOS + Firefox auf Linux + Chromium auf Linux + Firefox auf Windows + Chrome auf Windows + Edge auf Windows + Internet Explorer auf Windows + Safari auf macOS + Eigener + + + System default + Privacy Browser + WebView-Standard + Firefox auf Android + Chrome auf Android + Safari auf iOS + Firefox auf Linux + Chromium auf Linux + Firefox auf Windows + Chrome auf Windows + Edge auf Windows + Internet Explorer auf Windows + Safari auf macOS Eigener - - System default - Privacy Browser 1.0 - WebView-Standard - Firefox 56 on Android 8.0.0 - Chrome 62 on Android 8.0.0 - Safari 11 on iOS 11.1 - Firefox 52 on Linux - Chromium 61 on Linux - Firefox 56 on Windows 10 - Chrome 62 on Windows 10 - Edge 16 on Windows 10 - Internet Explorer 11 on Windows 10 - Safari 11.0.1 on macOS 10.13.1 - Eigener - Eigener User Agent Inkognito-Modus Löscht den Verlauf und den Cache nach jedem fertigen Laden einer Webseite. Zurück und vorwärts funktioniert im Inkognito-Modus nicht. diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index ef1b12de..4ec9ce36 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -149,6 +149,7 @@ Cargar URL Copiar URL + Descargar URL Correo electrónico Copiar correo electrónico Escribir correo electrónico @@ -261,37 +262,37 @@ Habilitar el guardar los datos de formulario por defecto Los datos de formularios guardados pueden rellenar automáticamente las casillas o campos de las webs. Agente de usuario - - Navegador Privado 1.0 + + Navegador Privado WebView por defecto - Firefox 56 en Android 8.0.0 - Chrome 61 en Android 8.0.0 - Safari 11 en iOS 11.1 - Firefox 52 en Linux - Chromium 62 en Linux - Firefox 56 en Windows 10 - Chrome 62 en Windows 10 - Edge 16 en Windows 10 - Internet Explorer 11 en Windows 10 - Safari 11.0.1 en macOS 10.13.1 + Firefox en Android + Chrome en Android + Safari en iOS + Firefox en Linux + Chromium en Linux + Firefox en Windows + Chrome en Windows + Edge en Windows + Internet Explorer en Windows + Safari en macOS + Personalizado + + + Por defecto del sistema + Navegador Privado + WebView por defecto + Firefox en Android + Chrome en Android + Safari en iOS + Firefox en Linux + Chromium en Linux + Firefox en Windows + Chrome en Windows + Edge en Windows + Internet Explorer en Windows + Safari en macOS Personalizado - - Por defecto del sistema - Navegador Privado 1.0 - WebView por defecto - Firefox 56 en Android 8.0.0 - Chrome 62 en Android 8.0.0 - Safari 11 en iOS 11.1 - Firefox 52 en Linux - Chromium 61 en Linux - Firefox 56 en Windows 10 - Chrome 62 en Windows 10 - Edge 16 en Windows 10 - Internet Explorer 11 en Windows 10 - Safari 11.0.1 en macOS 10.13.1 - Personalizado - Agente de usuario personalizado Modo incógnito Borrar el historial y el caché después de que cada página web termine de cargar. Adelante y atrás no funcionan en el Modo incógnito. diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 124cf763..9d28f1a6 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -151,6 +151,7 @@ Apri URL Copia URL + Scarica URL Indirizzo Email Copia Indirizzo Email Scrivi Email @@ -261,37 +262,37 @@ Abilita il salvataggio dei dati dei moduli I dati dei moduli salvati permettono di auto-compilare i campi dei moduli nei siti web. User agent - - Privacy Browser 1.0 + + Privacy Browser WebView Default - Firefox 56 su Android 8.0.0 - Chrome 61 su Android 8.0.0 - Safari 11 su iOS 11.1 - Firefox 52 su Linux - Chromium 62 su Linux - Firefox 56 su Windows 10 - Chrome 62 su Windows 10 - Edge 16 su Windows 10 - Internet Explorer 11 su Windows 10 - Safari 11.0.1 su macOS 10.13.1 + Firefox su Android + Chrome su Android + Safari su iOS + Firefox su Linux + Chromium su Linux + Firefox su Windows + Chrome su Windows + Edge su Windows + Internet Explorer su Windows + Safari su macOS + Personalizzato + + + Impostazioni di default + Privacy Browser + WebView Default + Firefox su Android + Chrome su Android + Safari su iOS + Firefox su Linux + Chromium su Linux + Firefox su Windows + Chrome su Windows + Edge su Windows + Internet Explorer su Windows + Safari su macOS Personalizzato - - Impostazioni di default - Privacy Browser 1.0 - WebView Default - Firefox 56 su Android 8.0.0 - Chrome 62 su Android 8.0.0 - Safari 11 su iOS 11.1 - Firefox 52 su Linux - Chromium 61 su Linux - Firefox 56 su Windows 10 - Chrome 62 su Windows 10 - Edge 16 su Windows 10 - Internet Explorer 11 su Windows 10 - Safari 11.0.1 su macOS 10.13.1 - Personalizzato - User agent personalizzato Modalità Incognito Cancella la cronologia e la cache al termine del caricamento di ogni pagina. I pulsanti Avanti e Indietro non funzionano in modalità incognito. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index aa99f13a..ec05533e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -152,6 +152,7 @@ Загрузить URL Копировать URL + Сохранить файл из URL Адрес email Копировать адрес email Написать email @@ -262,37 +263,37 @@ Разрешить сохранение данных формы по умолчанию Сохраненные данные формы могут автоматически заполнять поля на веб-сайтах. User agent - - Privacy Browser 1.0 + + Privacy Browser WebView по умолчанию - Firefox 56 на Android 8.0.0 - Chrome 62 на Android 8.0.0 - Safari 11 на iOS 11.1 - Firefox 52 на Linux - Chromium 61 на Linux - Firefox 56 на Windows 10 - Chrome 62 на Windows 10 - Edge 16 на Windows 10 - Internet Explorer 11 на Windows 10 - Safari 11.0.1 на macOS 10.13.1 + Firefox на Android + Chrome на Android + Safari на iOS + Firefox на Linux + Chromium на Linux + Firefox на Windows + Chrome на Windows + Edge на Windows + Internet Explorer на Windows + Safari на macOS + Пользовательский + + + Настройки по умолчанию + Privacy Browser + WebView по умолчанию + Firefox на Android + Chrome на Android + Safari на iOS + Firefox на Linux + Chromium на Linux + Firefox на Windows + Chrome на Windows + Edge на Windows + Internet Explorer на Windows + Safari на macOS Пользовательский - - Настройки по умолчанию - Privacy Browser 1.0 - WebView по умолчанию - Firefox 56 на Android 8.0.0 - Chrome 62 на Android 8.0.0 - Safari 11 на iOS 11.1 - Firefox 52 на Linux - Chromium 61 на Linux - Firefox 56 на Windows 10 - Chrome 62 на Windows 10 - Edge 16 на Windows 10 - Internet Explorer 11 на Windows 10 - Safari 11.0.1 на macOS 10.13.1 - Пользовательский - Пользовательский user agent Режим инкогнито Очистка журнала и кэша после завершения загрузки каждой веб-страницы. Кнопки \'Вперед\' и \'Назад\' не работают в этом режиме. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3e67bedf..dd6b75fc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -264,69 +264,69 @@ Enable saving of form data by default Saved form data can auto-populate fields on websites. User agent - - Privacy Browser 1.0 + + Privacy Browser WebView Default - Firefox 56 on Android 8.0.0 - Chrome 62 on Android 8.0.0 - Safari 11 on iOS 11.1 - Firefox 52 on Linux - Chromium 61 on Linux - Firefox 56 on Windows 10 - Chrome 62 on Windows 10 - Edge 16 on Windows 10 - Internet Explorer 11 on Windows 10 - Safari 11.0.1 on macOS 10.13.1 + Firefox on Android + Chrome on Android + Safari on iOS + Firefox on Linux + Chromium on Linux + Firefox on Windows + Chrome on Windows + Edge on Windows + Internet Explorer on Windows + Safari on macOS Custom - + + System default + Privacy Browser + WebView Default + Firefox on Android + Chrome on Android + Safari on iOS + Firefox on Linux + Chromium on Linux + Firefox on Windows + Chrome on Windows + Edge on Windows + Internet Explorer on Windows + Safari on macOS + Custom + + + Privacy Browser + WebView Default + Firefox on Android + Chrome on Android + Safari on iOS + Firefox on Linux + Chromium on Linux + Firefox on Windows + Chrome on Windows + Edge on Windows + Internet Explorer on Windows + Safari on macOS + Custom user agent + + PrivacyBrowser/1.0 WebView default user agent - Mozilla/5.0 (Android 8.0.0; Mobile; rv:56.0) Gecko/56.0 Firefox/56.0 - Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPR5.170623.011) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 + Mozilla/5.0 (Android 8.1.0; Mobile; rv:60.0) Gecko/60.0 Firefox/60.0 + Mozilla/5.0 (Linux; Android 8.1.0; Pixel 2 XL Build/OPM4.171019.016.B1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36 Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0 Mobile/15B92 Safari/604.1 Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0 - Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36 - Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299 + Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36 + Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0 + Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36 + Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134 Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.4 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.4 Custom user agent - - System default - Privacy Browser 1.0 - WebView Default - Firefox 56 on Android 8.0.0 - Chrome 62 on Android 8.0.0 - Safari 11 on iOS 11.1 - Firefox 52 on Linux - Chromium 61 on Linux - Firefox 56 on Windows 10 - Chrome 62 on Windows 10 - Edge 16 on Windows 10 - Internet Explorer 11 on Windows 10 - Safari 11.0.1 on macOS 10.13.1 - Custom - - - System default user agent - PrivacyBrowser/1.0 - WebView default user agent - Mozilla/5.0 (Android 8.0.0; Mobile; rv:56.0) Gecko/56.0 Firefox/56.0 - Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPR5.170623.011) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 - Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0 Mobile/15B92 Safari/604.1 - Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0 - Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36 - Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299 - Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.4 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.4 - Custom user agent - Custom user agent + System default user agent Incognito Mode Clear the history and cache after each webpage finishes loading. Forward and back do not work in Incognito Mode. Do Not Track diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 759bcbad..f4dcff29 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -56,9 +56,9 @@ -- 2.43.0