]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/commitdiff
Add X-Requested-With settings. https://redmine.stoutner.com/issues/819
authorSoren Stoutner <soren@stoutner.com>
Mon, 25 Jul 2022 23:46:15 +0000 (16:46 -0700)
committerSoren Stoutner <soren@stoutner.com>
Mon, 25 Jul 2022 23:46:15 +0000 (16:46 -0700)
16 files changed:
app/src/main/assets/de/guide_tracking_ids.html
app/src/main/assets/en/guide_tracking_ids.html
app/src/main/assets/es/guide_tracking_ids.html
app/src/main/assets/fr/guide_tracking_ids.html
app/src/main/assets/it/guide_tracking_ids.html
app/src/main/assets/pt-rBR/guide_tracking_ids.html
app/src/main/assets/ru/guide_tracking_ids.html
app/src/main/assets/tr/guide_tracking_ids.html
app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/SettingsActivity.java
app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java
app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java
app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.kt
app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt
app/src/main/res/layout/domain_settings_fragment.xml
app/src/main/res/values/strings.xml

index aabfb79607d9c8eeff085e87cb5ede1ceb2990b1..88d87f5e56b665192eeeaecb0ca65165429f92f2 100644 (file)
             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
index eaf2ca3dec39ec51991bfe7b78fdde8c8607f5e8..2de881932d1a25d5d4e880faa518274ebf3bb72e 100644 (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
index ad8ab3fda644164bd6fade8caaa4ed8ca3e6d92a..5e5320254d2a531ab6476dda1f67bfc45a8c5955 100644 (file)
@@ -1,7 +1,7 @@
 <!--
   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
index 245761a6269dd8626023a6c49675b24b9943325f..e0f6e164e3f0741ed04a3fa7784e43d915d47f6f 100644 (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
index 04ec23b61fe583277cc49bc619bcd08c6f5f187c..078e99376ca763a9c5e57f165ff9403c2c4724a4 100644 (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
index ba507583947b4c2d464e645adbc29fcd6b8cbffb..65ccbbce7497c7d969c33cf9954487b71bd17a33 100644 (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
index 2b44c55d1714334705894a7bfe2a100977571e6b..0df86fb62852ae216fb91a89a2b87db645865e65 100644 (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
index 31d1d6fb5efaa33b396576f641780a360f654b7a..6935377fd347683a07c88fd7e66f8c6852b17605 100644 (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
index cd5a3d8444e6ac6cae3de63abe226dae5fd71066..1a8ba7d5b53291ba57c2a4876d561627a22d44fc 100644 (file)
@@ -174,10 +174,8 @@ import java.text.NumberFormat;
 
 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;
@@ -236,9 +234,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `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;
 
@@ -3492,9 +3487,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             }
         });
 
-        // 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);
 
@@ -3786,6 +3778,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             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);
@@ -3822,13 +3815,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 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));
@@ -3868,6 +3864,24 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     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.
@@ -3957,6 +3971,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Disable swipe to refresh.
                         swipeRefreshLayout.setEnabled(false);
+                        break;
                 }
 
                 // Check to see if WebView themes are supported.
@@ -4061,6 +4076,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     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);
 
@@ -4149,7 +4170,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // 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());
         }
     }
 
@@ -4871,9 +4892,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             }
         }
 
-        // 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) {
index d21ccbb53be4aa0a52e073fe7f0599dcc791e711..66986bac793ae8c5ff684d3a02b3b265189eedfd 100644 (file)
@@ -26,7 +26,6 @@ import android.view.WindowManager;
 
 import androidx.appcompat.app.AppCompatActivity;
 
-import com.stoutner.privacybrowser.R;
 import com.stoutner.privacybrowser.fragments.SettingsFragment;
 
 public class SettingsActivity extends AppCompatActivity {
index 89f8513ed42072a13cd08a76906820af4894a9d9..3a216eb164d588105f9560bbe94036c00c54da23 100644 (file)
@@ -63,14 +63,14 @@ import java.util.Calendar;
 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
@@ -86,7 +86,6 @@ public class DomainSettingsFragment extends Fragment {
         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`.
@@ -142,6 +141,7 @@ public class DomainSettingsFragment extends Fragment {
         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);
@@ -535,6 +535,12 @@ public class DomainSettingsFragment extends Fragment {
             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
index e79e399e026e649b042911a6909132ed9b0e1491..9c80f5908138fef0b366ab0145ad772745c91f06 100644 (file)
@@ -849,6 +849,9 @@ public class SettingsFragment extends PreferenceFragmentCompat {
                         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":
index 415fd92bae463388180c9d59eb4b8169bec88fba..5dfd845e09c556bf4f10a44ef57d04c3c7005240 100644 (file)
@@ -46,6 +46,7 @@ private const val DOM_STORAGE = "dom_storage"
 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"
@@ -167,17 +168,15 @@ class ImportExportDatabaseHelper {
                 // 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.
@@ -191,11 +190,10 @@ class ImportExportDatabaseHelper {
                 // 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.
@@ -218,25 +216,22 @@ class ImportExportDatabaseHelper {
                 // 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.
@@ -340,11 +335,10 @@ class ImportExportDatabaseHelper {
                 // 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.
@@ -377,18 +371,16 @@ class ImportExportDatabaseHelper {
                 // 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.
@@ -406,6 +398,21 @@ class ImportExportDatabaseHelper {
                 // 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.
@@ -479,6 +486,7 @@ class ImportExportDatabaseHelper {
                 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)))
@@ -528,6 +536,7 @@ class ImportExportDatabaseHelper {
                 .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)
@@ -661,6 +670,7 @@ class ImportExportDatabaseHelper {
                 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)))
@@ -701,6 +711,7 @@ class ImportExportDatabaseHelper {
                     "$SAVE_FORM_DATA BOOLEAN, " +
                     "$USER_AGENT TEXT, " +
                     "$CUSTOM_USER_AGENT TEXT, " +
+                    "$X_REQUESTED_WITH_HEADER BOOLEAN, " +
                     "$INCOGNITO_MODE BOOLEAN, " +
                     "$ALLOW_SCREENSHOTS BOOLEAN, " +
                     "$EASYLIST BOOLEAN, " +
@@ -753,6 +764,7 @@ class ImportExportDatabaseHelper {
             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))
index ad34be8327baa58234dc08ae8735554eec6ee5f2..4011f5a5aba4fe689a628fbd8523afa306e634f6 100644 (file)
@@ -137,6 +137,7 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS
     private var ultraListBlockedRequests = 0
     private var ultraPrivacyBlockedRequests = 0
     private var thirdPartyBlockedRequests = 0
+    private var xRequestedWithHeader = mutableMapOf<String, String>()
 
     init {
         // Enable nested scrolling by default.
@@ -295,6 +296,24 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS
     }
 
 
+    // 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.
index b741aed00cc72bd9900e8856d8849009eec989a2..0f43c16e54bc2df51564ce04c4f2ff9046b12cb3 100644 (file)
                 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. -->
index 9d9fc616a38b2bce2dcf64575294019c0b51e77c..9fd6dbb0b030a909a837165656872312cfa43f3d 100644 (file)
         <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>