Redirects aus URL-Anfragen (Queries).
Eine Liste der aktuellen URL-Modifikationen kann einem <a href="https://www.stoutner.com/url-modification/">Blog-Post</a> entnommen werden.
Die URL-Modifikationen können in den Einstellungen deaktiviert werden, sollten sie Probleme bereiten.</p>
+
+
+ <h3><svg class="header"><use href="../shared_images/disabled_by_default.svg#icon"/></svg> X-Requested-With Header</h3>
+
+ <p>Google programmed Android’s WebView to send an X-Requested-With header with every request.
+ The value of the X-Requested-With header is set to the application ID, which in the case of Privacy Browser is <code>com.stoutner.privacybrowser.standard</code>.
+ Currently, it isn't possible to remove this header, but the value can be changed. By default, Privacy Browser sends a null (empty) value for the X-Requested-With header.
+ Even though the spec allows for null header values, some web servers don't like them, so Privacy Browser has the option to revert to the default behavior of sending the app ID.
+ Because this setting is cached when a URL is first loaded, and isn't changed when reloading a page or navigating history,
+ changes to this setting may not be applied until Privacy Browser is restarted.
+ There is a <a href="https://www.stoutner.com/the-x-requested-with-header/">blog post</a> with additional information.
+ The X-Requested-With header will be <a href="https://redmine.stoutner.com/issues/37">completely removed</a> in the 4.x series with the release of Privacy WebView.</p>
</body>
</html>
\ No newline at end of file
<p>Privacy Browser removes tracking IDs and AMP (<a href="https://en.wikipedia.org/wiki/Accelerated_Mobile_Pages">Accelerated Mobile Pages</a>) redirects from URL queries.
There is a blog post that is updated with the <a href="https://www.stoutner.com/url-modification/">current list</a> of modifications.
URL modification can be turned off in the settings if it is causing issues.</p>
+
+
+ <h3><svg class="header"><use href="../shared_images/disabled_by_default.svg#icon"/></svg> X-Requested-With Header</h3>
+
+ <p>Google programmed Android’s WebView to send an X-Requested-With header with every request.
+ The value of the X-Requested-With header is set to the application ID, which in the case of Privacy Browser is <code>com.stoutner.privacybrowser.standard</code>.
+ Currently, it isn't possible to remove this header, but the value can be changed. By default, Privacy Browser sends a null (empty) value for the X-Requested-With header.
+ Even though the spec allows for null header values, some web servers don't like them, so Privacy Browser has the option to revert to the default behavior of sending the app ID.
+ Because this setting is cached when a URL is first loaded, and isn't changed when reloading a page or navigating history,
+ changes to this setting may not be applied until Privacy Browser is restarted.
+ There is a <a href="https://www.stoutner.com/the-x-requested-with-header/">blog post</a> with additional information.
+ The X-Requested-With header will be <a href="https://redmine.stoutner.com/issues/37">completely removed</a> in the 4.x series with the release of Privacy WebView.</p>
</body>
</html>
\ No newline at end of file
<!--
Copyright © 2017-2022 Soren Stoutner <soren@stoutner.com>.
- Translation 2017,2019,2021 Jose A. León. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
+ Translation 2017,2019,2021-2022 Jose A. León. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
<p>Navegador Privado elimina los ID de seguimiento y las redirecciones AMP (<a href="https://en.wikipedia.org/wiki/Accelerated_Mobile_Pages">Accelerated Mobile Pages</a>) de las consultas de las URL.
Hay una entrada del blog que se actualiza con la <a href="https://www.stoutner.com/url-modification/">lista actual</a> de modificaciones.
La modificación de la URL se puede desactivar en la configuración si está causando problemas.</p>
+
+
+ <h3><svg class="header"><use href="../shared_images/disabled_by_default.svg#icon"/></svg> X-Requested-With Header</h3>
+
+ <p>Google programmed Android’s WebView to send an X-Requested-With header with every request.
+ The value of the X-Requested-With header is set to the application ID, which in the case of Privacy Browser is <code>com.stoutner.privacybrowser.standard</code>.
+ Currently, it isn't possible to remove this header, but the value can be changed. By default, Privacy Browser sends a null (empty) value for the X-Requested-With header.
+ Even though the spec allows for null header values, some web servers don't like them, so Privacy Browser has the option to revert to the default behavior of sending the app ID.
+ Because this setting is cached when a URL is first loaded, and isn't changed when reloading a page or navigating history,
+ changes to this setting may not be applied until Privacy Browser is restarted.
+ There is a <a href="https://www.stoutner.com/the-x-requested-with-header/">blog post</a> with additional information.
+ The X-Requested-With header will be <a href="https://redmine.stoutner.com/issues/37">completely removed</a> in the 4.x series with the release of Privacy WebView.</p>
</body>
</html>
\ No newline at end of file
<p>Privacy Browser removes tracking IDs and AMP (<a href="https://en.wikipedia.org/wiki/Accelerated_Mobile_Pages">Accelerated Mobile Pages</a>) redirects from URL queries.
There is a blog post that is updated with the <a href="https://www.stoutner.com/url-modification/">current list</a> of modifications.
URL modification can be turned off in the settings if it is causing issues.</p>
+
+
+ <h3><svg class="header"><use href="../shared_images/disabled_by_default.svg#icon"/></svg> X-Requested-With Header</h3>
+
+ <p>Google programmed Android’s WebView to send an X-Requested-With header with every request.
+ The value of the X-Requested-With header is set to the application ID, which in the case of Privacy Browser is <code>com.stoutner.privacybrowser.standard</code>.
+ Currently, it isn't possible to remove this header, but the value can be changed. By default, Privacy Browser sends a null (empty) value for the X-Requested-With header.
+ Even though the spec allows for null header values, some web servers don't like them, so Privacy Browser has the option to revert to the default behavior of sending the app ID.
+ Because this setting is cached when a URL is first loaded, and isn't changed when reloading a page or navigating history,
+ changes to this setting may not be applied until Privacy Browser is restarted.
+ There is a <a href="https://www.stoutner.com/the-x-requested-with-header/">blog post</a> with additional information.
+ The X-Requested-With header will be <a href="https://redmine.stoutner.com/issues/37">completely removed</a> in the 4.x series with the release of Privacy WebView.</p>
</body>
</html>
\ No newline at end of file
<p>Privacy Browser removes tracking IDs and AMP (<a href="https://en.wikipedia.org/wiki/Accelerated_Mobile_Pages">Accelerated Mobile Pages</a>) redirects from URL queries.
There is a blog post that is updated with the <a href="https://www.stoutner.com/url-modification/">current list</a> of modifications.
URL modification can be turned off in the settings if it is causing issues.</p>
+
+
+ <h3><svg class="header"><use href="../shared_images/disabled_by_default.svg#icon"/></svg> X-Requested-With Header</h3>
+
+ <p>Google programmed Android’s WebView to send an X-Requested-With header with every request.
+ The value of the X-Requested-With header is set to the application ID, which in the case of Privacy Browser is <code>com.stoutner.privacybrowser.standard</code>.
+ Currently, it isn't possible to remove this header, but the value can be changed. By default, Privacy Browser sends a null (empty) value for the X-Requested-With header.
+ Even though the spec allows for null header values, some web servers don't like them, so Privacy Browser has the option to revert to the default behavior of sending the app ID.
+ Because this setting is cached when a URL is first loaded, and isn't changed when reloading a page or navigating history,
+ changes to this setting may not be applied until Privacy Browser is restarted.
+ There is a <a href="https://www.stoutner.com/the-x-requested-with-header/">blog post</a> with additional information.
+ The X-Requested-With header will be <a href="https://redmine.stoutner.com/issues/37">completely removed</a> in the 4.x series with the release of Privacy WebView.</p>
</body>
</html>
\ No newline at end of file
<p>Privacy Browser removes tracking IDs and AMP (<a href="https://en.wikipedia.org/wiki/Accelerated_Mobile_Pages">Accelerated Mobile Pages</a>) redirects from URL queries.
There is a blog post that is updated with the <a href="https://www.stoutner.com/url-modification/">current list</a> of modifications.
URL modification can be turned off in the settings if it is causing issues.</p>
+
+
+ <h3><svg class="header"><use href="../shared_images/disabled_by_default.svg#icon"/></svg> X-Requested-With Header</h3>
+
+ <p>Google programmed Android’s WebView to send an X-Requested-With header with every request.
+ The value of the X-Requested-With header is set to the application ID, which in the case of Privacy Browser is <code>com.stoutner.privacybrowser.standard</code>.
+ Currently, it isn't possible to remove this header, but the value can be changed. By default, Privacy Browser sends a null (empty) value for the X-Requested-With header.
+ Even though the spec allows for null header values, some web servers don't like them, so Privacy Browser has the option to revert to the default behavior of sending the app ID.
+ Because this setting is cached when a URL is first loaded, and isn't changed when reloading a page or navigating history,
+ changes to this setting may not be applied until Privacy Browser is restarted.
+ There is a <a href="https://www.stoutner.com/the-x-requested-with-header/">blog post</a> with additional information.
+ The X-Requested-With header will be <a href="https://redmine.stoutner.com/issues/37">completely removed</a> in the 4.x series with the release of Privacy WebView.</p>
</body>
</html>
\ No newline at end of file
<p>Privacy Browser удаляет идентификаторы отслеживания и перенаправления AMP (<a href="https://en.wikipedia.org/wiki/Accelerated_Mobile_Pages">Accelerated Mobile Pages</a>) из URL.
В блоге опубликован обновляемый <a href="https://www.stoutner.com/url-modification/">актуальный список</a> модификаций.
Модификация URL может быть отключена в настройках, если она вызывает проблемы.</p>
+
+
+ <h3><svg class="header"><use href="../shared_images/disabled_by_default.svg#icon"/></svg> X-Requested-With Header</h3>
+
+ <p>Google programmed Android’s WebView to send an X-Requested-With header with every request.
+ The value of the X-Requested-With header is set to the application ID, which in the case of Privacy Browser is <code>com.stoutner.privacybrowser.standard</code>.
+ Currently, it isn't possible to remove this header, but the value can be changed. By default, Privacy Browser sends a null (empty) value for the X-Requested-With header.
+ Even though the spec allows for null header values, some web servers don't like them, so Privacy Browser has the option to revert to the default behavior of sending the app ID.
+ Because this setting is cached when a URL is first loaded, and isn't changed when reloading a page or navigating history,
+ changes to this setting may not be applied until Privacy Browser is restarted.
+ There is a <a href="https://www.stoutner.com/the-x-requested-with-header/">blog post</a> with additional information.
+ The X-Requested-With header will be <a href="https://redmine.stoutner.com/issues/37">completely removed</a> in the 4.x series with the release of Privacy WebView.</p>
</body>
</html>
\ No newline at end of file
<p>Privacy Browser removes tracking IDs and AMP (<a href="https://en.wikipedia.org/wiki/Accelerated_Mobile_Pages">Accelerated Mobile Pages</a>) redirects from URL queries.
There is a blog post that is updated with the <a href="https://www.stoutner.com/url-modification/">current list</a> of modifications.
URL modification can be turned off in the settings if it is causing issues.</p>
+
+
+ <h3><svg class="header"><use href="../shared_images/disabled_by_default.svg#icon"/></svg> X-Requested-With Header</h3>
+
+ <p>Google programmed Android’s WebView to send an X-Requested-With header with every request.
+ The value of the X-Requested-With header is set to the application ID, which in the case of Privacy Browser is <code>com.stoutner.privacybrowser.standard</code>.
+ Currently, it isn't possible to remove this header, but the value can be changed. By default, Privacy Browser sends a null (empty) value for the X-Requested-With header.
+ Even though the spec allows for null header values, some web servers don't like them, so Privacy Browser has the option to revert to the default behavior of sending the app ID.
+ Because this setting is cached when a URL is first loaded, and isn't changed when reloading a page or navigating history,
+ changes to this setting may not be applied until Privacy Browser is restarted.
+ There is a <a href="https://www.stoutner.com/the-x-requested-with-header/">blog post</a> with additional information.
+ The X-Requested-With header will be <a href="https://redmine.stoutner.com/issues/37">completely removed</a> in the 4.x series with the release of Privacy WebView.</p>
</body>
</html>
\ No newline at end of file
import java.util.ArrayList;
import java.util.Date;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
// `findNextOnPage()`, `closeFindOnPage()`, `loadUrlFromTextBox()`, `onSslMismatchBack()`, `applyProxy()`, and `applyDomainSettings()`.
private NestedScrollWebView currentWebView;
- // `customHeader` is used in `onCreate()`, `onOptionsItemSelected()`, `onCreateContextMenu()`, and `loadUrl()`.
- private final Map<String, String> customHeaders = new HashMap<>();
-
// The search URL is set in `applyAppSettings()` and used in `onNewIntent()`, `loadUrlFromTextBox()`, `initializeApp()`, and `initializeWebView()`.
private String searchURL;
}
});
- // Replace the header that `WebView` creates for `X-Requested-With` with a null value. The default value is the application ID (com.stoutner.privacybrowser.standard).
- customHeaders.put("X-Requested-With", "");
-
// Inflate a bare WebView to get the default user agent. It is not used to render content on the screen.
@SuppressLint("InflateParams") View webViewLayout = getLayoutInflater().inflate(R.layout.bare_webview, null, false);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// Store the general preference information.
+ boolean defaultXRequestedWithHeader = sharedPreferences.getBoolean(getString(R.string.x_requested_with_header_key), true);
String defaultFontSizeString = sharedPreferences.getString("font_size", getString(R.string.font_size_default_value));
String defaultUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
boolean defaultSwipeToRefresh = sharedPreferences.getBoolean("swipe_to_refresh", true);
boolean saveFormData = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);
nestedScrollWebView.setEasyListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);
nestedScrollWebView.setEasyPrivacyEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);
- nestedScrollWebView.setFanboysAnnoyanceListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);
+ nestedScrollWebView.setFanboysAnnoyanceListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(
+ DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);
nestedScrollWebView.setFanboysSocialBlockingListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(
DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1);
nestedScrollWebView.setUltraListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST)) == 1);
nestedScrollWebView.setUltraPrivacyEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1);
- nestedScrollWebView.setBlockAllThirdPartyRequests(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1);
+ nestedScrollWebView.setBlockAllThirdPartyRequests(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(
+ DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1);
String userAgentName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT));
+ int xRequestedWithHeaderInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.X_REQUESTED_WITH_HEADER));
int fontSize = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE));
int swipeToRefreshInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
int webViewThemeInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME));
nestedScrollWebView.getSettings().setSaveFormData(saveFormData);
}
+ // Set the X-Requested-With header.
+ switch (xRequestedWithHeaderInt) {
+ case DomainsDatabaseHelper.SYSTEM_DEFAULT:
+ if (defaultXRequestedWithHeader)
+ nestedScrollWebView.setXRequestedWithHeader();
+ else
+ nestedScrollWebView.resetXRequestedWithHeader();
+ break;
+
+ case DomainsDatabaseHelper.ENABLED:
+ nestedScrollWebView.setXRequestedWithHeader();
+ break;
+
+ case DomainsDatabaseHelper.DISABLED:
+ nestedScrollWebView.resetXRequestedWithHeader();
+ break;
+ }
+
// Apply the font size.
try { // Try the specified font size to see if it is valid.
if (fontSize == 0) { // Apply the default font size.
// Disable swipe to refresh.
swipeRefreshLayout.setEnabled(false);
+ break;
}
// Check to see if WebView themes are supported.
nestedScrollWebView.getSettings().setSaveFormData(saveFormData);
}
+ // Store the X-Requested-With header status in the nested scroll WebView.
+ if (defaultXRequestedWithHeader)
+ nestedScrollWebView.setXRequestedWithHeader();
+ else
+ nestedScrollWebView.resetXRequestedWithHeader();
+
// Store the swipe to refresh status in the nested scroll WebView.
nestedScrollWebView.setSwipeToRefresh(defaultSwipeToRefresh);
// Load the URL if directed. This makes sure that the domain settings are properly loaded before the URL. By using `loadUrl()`, instead of `loadUrlFromBase()`, the Referer header will never be sent.
if (loadUrl) {
- nestedScrollWebView.loadUrl(url, customHeaders);
+ nestedScrollWebView.loadUrl(url, nestedScrollWebView.getXRequestedWithHeader());
}
}
}
}
- // Clear the custom headers.
- customHeaders.clear();
-
// Manually delete the `app_webview` folder, which contains the cookies, DOM storage, form data, and `Service Worker` cache.
// See `https://code.google.com/p/android/issues/detail?id=233826&thanks=233826&ts=1486670530`.
if (clearEverything) {
import androidx.appcompat.app.AppCompatActivity;
-import com.stoutner.privacybrowser.R;
import com.stoutner.privacybrowser.fragments.SettingsFragment;
public class SettingsActivity extends AppCompatActivity {
import java.util.Date;
public class DomainSettingsFragment extends Fragment {
- // Initialize the public class constants. These are used by activities calling this fragment.
+ // Initialize the public class constants.
public static final String DATABASE_ID = "database_id";
public static final String SCROLL_Y = "scroll_y";
- // Define the public variables. `databaseId` is public static so it can be accessed from `DomainsActivity`. It is also used in `onCreate()` and `onCreateView()`.
+ // Declare the public variables. `databaseId` is public static so it can be accessed from `DomainsActivity`.
public static int databaseId;
- // Define the class variables.
+ // Declare the class variables.
private int scrollY;
@Override
scrollY = getArguments().getInt(SCROLL_Y);
}
- // The deprecated `getDrawable()` must be used until the minimum API >= 21.
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate `domain_settings_fragment`. `false` does not attach it to the root `container`.
ImageView xRequestedWithHeaderImageView = domainSettingsView.findViewById(R.id.x_requested_with_header_imageview);
Spinner xRequestedWithHeaderSpinner = domainSettingsView.findViewById(R.id.x_requested_with_header_spinner);
TextView xRequestedWithHeaderTextView = domainSettingsView.findViewById(R.id.x_requested_with_header_textview);
+ TextView xRequestedWithHeaderExplanationTextView = domainSettingsView.findViewById(R.id.x_requested_with_header_explanation_textview);
Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.font_size_spinner);
TextView defaultFontSizeTextView = domainSettingsView.findViewById(R.id.default_font_size_textview);
EditText customFontSizeEditText = domainSettingsView.findViewById(R.id.custom_font_size_edittext);
xRequestedWithHeaderSpinner.performClick();
});
+ // Open the X-Requested-With header spinner when the explanation text view is clicked.
+ xRequestedWithHeaderExplanationTextView.setOnClickListener((View v) -> {
+ // Open the X-Requested header spinner.
+ xRequestedWithHeaderSpinner.performClick();
+ });
+
// Display the font size settings.
if (fontSizeInt == 0) { // `0` is the code for system default font size.
// Set the font size to the system default
xRequestedWithHeaderPreference.setIcon(R.drawable.x_requested_with_header_enabled);
else
xRequestedWithHeaderPreference.setIcon(R.drawable.x_requested_with_header_disabled);
+
+ // Restart Privacy Browser.
+ restartPrivacyBrowser();
break;
case "incognito_mode":
private const val SAVE_FORM_DATA = "save_form_data"
private const val USER_AGENT = "user_agent"
private const val CUSTOM_USER_AGENT = "custom_user_agent"
+private const val X_REQUESTED_WITH_HEADER = "x_requested_with_header"
private const val INCOGNITO_MODE = "incognito_mode"
private const val ALLOW_SCREENSHOTS = "allow_screenshots"
private const val EASYLIST = "easylist"
// Populate the preferences table with the current app bar values.
// This can switch to using the variables directly once the API >= 30. <https://www.sqlite.org/datatype3.html#boolean_datatype>
// <https://developer.android.com/reference/android/database/sqlite/package-summary>
- if (hideAppBar) {
+ if (hideAppBar)
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $HIDE_APP_BAR = 1")
- } else {
+ else
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $HIDE_APP_BAR = 0")
- }
- if (scrollAppBar) {
+ if (scrollAppBar)
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $SCROLL_APP_BAR = 1")
- } else {
+ else
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $SCROLL_APP_BAR = 0")
- }
}
// Upgrade from schema version 5, first used in Privacy Browser 2.17, to schema version 6, first used in Privacy Browser 3.0.
// Populate the preferences table with the current open intents value.
// This can switch to using the variables directly once the API >= 30. <https://www.sqlite.org/datatype3.html#boolean_datatype>
// <https://developer.android.com/reference/android/database/sqlite/package-summary>
- if (openIntentsInNewTab) {
+ if (openIntentsInNewTab)
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $OPEN_INTENTS_IN_NEW_TAB = 1")
- } else {
+ else
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $OPEN_INTENTS_IN_NEW_TAB = 0")
- }
}
// Upgrade from schema version 6, first used in Privacy Browser 3.0, to schema version 7, first used in Privacy Browser 3.1.
// Populate the preferences with the current Tracking Queries value. Google Analytics was renamed Tracking Queries in schema version 15.
// This can switch to using the variables directly once the API >= 30. <https://www.sqlite.org/datatype3.html#boolean_datatype>
// <https://developer.android.com/reference/android/database/sqlite/package-summary>
- if (trackingQueries) {
+ if (trackingQueries)
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET google_analytics = 1")
- } else {
+ else
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET google_analytics = 0")
- }
// Populate the preferences table with the current AMP Redirects value. Twitter AMP Redirects was renamed AMP Redirects in schema version 15.
- if (ampRedirects) {
+ if (ampRedirects)
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET twitter_amp_redirects = 1")
- } else {
+ else
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET twitter_amp_redirects = 0")
- }
// Populate the preferences table with the current wide viewport value.
- if (wideViewport) {
+ if (wideViewport)
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $WIDE_VIEWPORT = 1")
- } else {
+ else
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $WIDE_VIEWPORT = 0")
- }
}
// Upgrade from schema version 7, first used in Privacy Browser 3.1, to schema version 8, first used in Privacy Browser 3.2.
// Populate the preferences table with the current clear logcat value.
// This can switch to using the variables directly once the API >= 30. <https://www.sqlite.org/datatype3.html#boolean_datatype>
// <https://developer.android.com/reference/android/database/sqlite/package-summary>
- if (clearLogcat) {
+ if (clearLogcat)
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $CLEAR_LOGCAT = 1")
- } else {
+ else
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $CLEAR_LOGCAT = 0")
- }
}
// Upgrade from schema version 12, first used in Privacy Browser 3.6, to schema version 13, first used in Privacy Browser 3.7.
// Populate the preferences table with the current download with external app value.
// This can switch to using the variables directly once the API >= 30. <https://www.sqlite.org/datatype3.html#boolean_datatype>
// <https://developer.android.com/reference/android/database/sqlite/package-summary>
- if (downloadWithExternalApp) {
+ if (downloadWithExternalApp)
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $DOWNLOAD_WITH_EXTERNAL_APP = 1")
- } else {
+ else
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $DOWNLOAD_WITH_EXTERNAL_APP = 0")
- }
// Populate the preferences table with the current bottom app bar value.
- if (bottomAppBar) {
+ if (bottomAppBar)
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $BOTTOM_APP_BAR = 1")
- } else {
+ else
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $BOTTOM_APP_BAR = 0")
- }
}
// Upgrade from schema version 14, first used in Privacy Browser 3.8, to schema version 15, first used in Privacy Browser 3.11.
// Copy the data from the old columns to the new ones.
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $TRACKING_QUERIES = google_analytics")
importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $AMP_REDIRECTS = twitter_amp_redirects")
+
+ // Create the new X-Requested-with header columns.
+ importDatabase.execSQL("ALTER TABLE $PREFERENCES_TABLE ADD COLUMN $X_REQUESTED_WITH_HEADER BOOLEAN")
+ importDatabase.execSQL("ALTER TABLE ${DomainsDatabaseHelper.DOMAINS_TABLE} ADD COLUMN ${DomainsDatabaseHelper.X_REQUESTED_WITH_HEADER} INTEGER")
+
+ // Get the current X-Requested-With header preferences value.
+ val xRequestedWithHeader = sharedPreferences.getBoolean(X_REQUESTED_WITH_HEADER, true)
+
+ // Populate the Preferences X-Requested-With header with the current value. The domains X-Requested-With header will default to 0, which is `System default`.
+ // This can switch to using the variables directly once the API >= 30. <https://www.sqlite.org/datatype3.html#boolean_datatype>
+ // <https://developer.android.com/reference/android/database/sqlite/package-summary>
+ if (xRequestedWithHeader)
+ importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $X_REQUESTED_WITH_HEADER = 1")
+ else
+ importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $X_REQUESTED_WITH_HEADER = 0")
}
// Get a cursor for the bookmarks table.
domainContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS,
importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)))
domainContentValues.put(DomainsDatabaseHelper.USER_AGENT, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT)))
+ domainContentValues.put(DomainsDatabaseHelper.X_REQUESTED_WITH_HEADER, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.X_REQUESTED_WITH_HEADER)))
domainContentValues.put(DomainsDatabaseHelper.FONT_SIZE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE)))
domainContentValues.put(DomainsDatabaseHelper.SWIPE_TO_REFRESH, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH)))
domainContentValues.put(DomainsDatabaseHelper.WEBVIEW_THEME, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME)))
.putBoolean(SAVE_FORM_DATA, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(SAVE_FORM_DATA)) == 1) // Save form data can be removed once the minimum API >= 26.
.putString(USER_AGENT, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(USER_AGENT)))
.putString(CUSTOM_USER_AGENT, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(CUSTOM_USER_AGENT)))
+ .putBoolean(X_REQUESTED_WITH_HEADER, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(X_REQUESTED_WITH_HEADER)) == 1)
.putBoolean(INCOGNITO_MODE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(INCOGNITO_MODE)) == 1)
.putBoolean(ALLOW_SCREENSHOTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(ALLOW_SCREENSHOTS)) == 1)
.putBoolean(EASYLIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(EASYLIST)) == 1)
domainContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)))
domainContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)))
domainContentValues.put(DomainsDatabaseHelper.USER_AGENT, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT)))
+ domainContentValues.put(DomainsDatabaseHelper.X_REQUESTED_WITH_HEADER, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.X_REQUESTED_WITH_HEADER)))
domainContentValues.put(DomainsDatabaseHelper.FONT_SIZE, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE)))
domainContentValues.put(DomainsDatabaseHelper.SWIPE_TO_REFRESH, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH)))
domainContentValues.put(DomainsDatabaseHelper.WEBVIEW_THEME, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME)))
"$SAVE_FORM_DATA BOOLEAN, " +
"$USER_AGENT TEXT, " +
"$CUSTOM_USER_AGENT TEXT, " +
+ "$X_REQUESTED_WITH_HEADER BOOLEAN, " +
"$INCOGNITO_MODE BOOLEAN, " +
"$ALLOW_SCREENSHOTS BOOLEAN, " +
"$EASYLIST BOOLEAN, " +
preferencesContentValues.put(SAVE_FORM_DATA, sharedPreferences.getBoolean(SAVE_FORM_DATA, false)) // Save form data can be removed once the minimum API >= 26.
preferencesContentValues.put(USER_AGENT, sharedPreferences.getString(USER_AGENT, context.getString(R.string.user_agent_default_value)))
preferencesContentValues.put(CUSTOM_USER_AGENT, sharedPreferences.getString(CUSTOM_USER_AGENT, context.getString(R.string.custom_user_agent_default_value)))
+ preferencesContentValues.put(X_REQUESTED_WITH_HEADER, sharedPreferences.getBoolean(X_REQUESTED_WITH_HEADER, true))
preferencesContentValues.put(INCOGNITO_MODE, sharedPreferences.getBoolean(INCOGNITO_MODE, false))
preferencesContentValues.put(ALLOW_SCREENSHOTS, sharedPreferences.getBoolean(ALLOW_SCREENSHOTS, false))
preferencesContentValues.put(EASYLIST, sharedPreferences.getBoolean(EASYLIST, true))
private var ultraListBlockedRequests = 0
private var ultraPrivacyBlockedRequests = 0
private var thirdPartyBlockedRequests = 0
+ private var xRequestedWithHeader = mutableMapOf<String, String>()
init {
// Enable nested scrolling by default.
}
+ // X-Requested-With header.
+ fun getXRequestedWithHeader() : MutableMap<String, String> {
+ // Return the X-Requested-With header.
+ return xRequestedWithHeader
+ }
+
+ fun setXRequestedWithHeader() {
+ // Set the X-Requested-With header to use a null value.
+ if (xRequestedWithHeader.isEmpty())
+ xRequestedWithHeader["X-Requested-With"] = ""
+ }
+
+ fun resetXRequestedWithHeader() {
+ // Clear the map, which resets the X-Requested-With header to use the default value of the application ID (com.stoutner.privacybrowser.standard).
+ xRequestedWithHeader.clear()
+ }
+
+
// Publicly expose the scroll ranges.
fun getHorizontalScrollRange(): Int {
// Return the horizontal scroll range.
android:layout_marginStart="45dp"
android:layout_marginEnd="36dp"
android:textSize="13sp" />
+
+ <TextView
+ android:id="@+id/x_requested_with_header_explanation_textview"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_marginTop="8dp"
+ android:layout_marginStart="45dp"
+ android:layout_marginEnd="36dp"
+ android:textSize="11sp"
+ android:text="@string/x_requested_with_header_explanation" />
</LinearLayout>
<!-- Font Size. -->
<string name="custom_user_agent">Custom user agent</string>
<string name="system_default_user_agent" translatable="false">System default user agent</string> <!-- This item is referenced in code. It is never displayed on the screen. -->
<string name="x_requested_with_header">X-Requested-With header</string>
- <string name="x_requested_with_header_summary">When enabled, Privacy Browser send a null value for the X-Requested-With header. Usually this isn\'t a problem, but a few websites don\'t like it.</string>
+ <string name="x_requested_with_header_summary">When enabled, Privacy Browser send a null value for the X-Requested-With header. Usually this isn\'t a problem, but a few websites don\'t like it.
+ Changing this settings will restart Privacy Browser.</string>
+ <string name="x_requested_with_header_explanation">Changes to the X-Requested-With header might not be applied until Privacy Browser is restarted.</string>
<string name="incognito_mode">Incognito Mode</string>
<string name="incognito_mode_summary">Clear the history and cache after each webpage finishes loading. In Incognito Mode, back closes the tab (or the app if there is only one tab).</string>
<string name="allow_screenshots">Allow screenshots</string>