]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
Add X-Requested-With settings. https://redmine.stoutner.com/issues/819
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebViewActivity.java
index 9bea7991873988a291707cced7e440ccb7c40fbf..1a8ba7d5b53291ba57c2a4876d561627a22d44fc 100644 (file)
@@ -118,7 +118,6 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 import androidx.viewpager.widget.ViewPager;
 import androidx.webkit.WebSettingsCompat;
 import androidx.webkit.WebViewFeature;
-import kotlin.Pair;
 
 import com.google.android.material.appbar.AppBarLayout;
 import com.google.android.material.floatingactionbutton.FloatingActionButton;
@@ -153,6 +152,7 @@ import com.stoutner.privacybrowser.helpers.BlocklistHelper;
 import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
 import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper;
 import com.stoutner.privacybrowser.helpers.ProxyHelper;
+import com.stoutner.privacybrowser.helpers.SanitizeUrlHelper;
 import com.stoutner.privacybrowser.views.NestedScrollWebView;
 
 import java.io.ByteArrayInputStream;
@@ -174,15 +174,15 @@ 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;
 import java.util.concurrent.Executors;
 
+import kotlin.Pair;
+
 public class MainWebViewActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener,
         EditBookmarkFolderDialog.EditBookmarkFolderListener, FontSizeDialog.UpdateFontSizeListener, NavigationView.OnNavigationItemSelectedListener, OpenDialog.OpenListener,
         PinnedMismatchDialog.PinnedMismatchListener, PopulateBlocklists.PopulateBlocklistsListener, SaveDialog.SaveListener, UrlHistoryDialog.NavigateHistoryListener,
@@ -195,7 +195,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     public static String proxyMode = ProxyHelper.NONE;
 
     // Declare the public static variables.
-    public static String currentBookmarksFolder;
+    public static String currentBookmarksFolder = "";
     public static boolean restartFromBookmarksActivity;
     public static WebViewPagerAdapter webViewPagerAdapter;
 
@@ -234,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;
 
@@ -273,13 +270,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private int defaultProgressViewStartOffset;
     private int defaultProgressViewEndOffset;
 
-    // The URL sanitizers are set in `applyAppSettings()` and used in `sanitizeUrl()`.
-    private boolean sanitizeGoogleAnalytics;
-    private boolean sanitizeFacebookClickIds;
-    private boolean sanitizeTwitterAmpRedirects;
+    // Declare the helpers.
+    private BookmarksDatabaseHelper bookmarksDatabaseHelper;
+    private DomainsDatabaseHelper domainsDatabaseHelper;
+    private ProxyHelper proxyHelper;
+    private SanitizeUrlHelper sanitizeUrlHelper;
 
     // Declare the class variables
-    private BookmarksDatabaseHelper bookmarksDatabaseHelper;
     private boolean bottomAppBar;
     private boolean displayingFullScreenVideo;
     private boolean downloadWithExternalApp;
@@ -289,9 +286,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private boolean inFullScreenBrowsingMode;
     private boolean loadingNewIntent;
     private BroadcastReceiver orbotStatusBroadcastReceiver;
-    private ProxyHelper proxyHelper;
     private boolean reapplyAppSettingsOnRestart;
     private boolean reapplyDomainSettingsOnRestart;
+    private boolean sanitizeAmpRedirects;
+    private boolean sanitizeTrackingQueries;
     private boolean scrollAppBar;
     private boolean waitingForProxy;
     private String webViewDefaultUserAgent;
@@ -532,9 +530,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Enable the drawing of the entire webpage.  This makes it possible to save a website image.  This must be done before anything else happens with the WebView.
         WebView.enableSlowWholeDocumentDraw();
 
-        // Set the theme.
-        setTheme(R.style.PrivacyBrowser);
-
         // Set the content view according to the position of the app bar.
         if (bottomAppBar) setContentView(R.layout.main_framelayout_bottom_appbar);
         else setContentView(R.layout.main_framelayout_top_appbar);
@@ -600,8 +595,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Store up to 100 tabs in memory.
         webViewPager.setOffscreenPageLimit(100);
 
-        // Instantiate the proxy helper.
+        // Instantiate the helpers.
+        bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this);
+        domainsDatabaseHelper = new DomainsDatabaseHelper(this);
         proxyHelper = new ProxyHelper();
+        sanitizeUrlHelper = new SanitizeUrlHelper();
 
         // Initialize the app.
         initializeApp();
@@ -618,9 +616,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Run the default commands.
         super.onNewIntent(intent);
 
-        // Replace the intent that started the app with this one.
-        setIntent(intent);
-
         // Check to see if the app is being restarted from a saved state.
         if (savedStateArrayList == null || savedStateArrayList.size() == 0) {  // The activity is not being restarted from a saved state.
             // Get the information from the intent.
@@ -692,6 +687,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     drawerLayout.closeDrawer(GravityCompat.END);
                 }
             }
+        } else {  // The app has been restarted.
+            // Replace the intent that started the app with this one.  This will load the tab after the others have been restored.
+            setIntent(intent);
         }
     }
 
@@ -1952,9 +1950,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 Uri currentUri = Uri.parse(currentWebView.getUrl());
                 String currentDomain = currentUri.getHost();
 
-                // Initialize the database handler.
-                DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(this);
-
                 // Create the domain and store the database ID.
                 int newDomainDatabaseId = domainsDatabaseHelper.addDomain(currentDomain);
 
@@ -3382,15 +3377,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         drawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.navigation_drawer));
         drawerLayout.setDrawerTitle(GravityCompat.END, getString(R.string.bookmarks));
 
-        // Initialize the bookmarks database helper.
-        bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this);
-
-        // Initialize `currentBookmarksFolder`.  `""` is the home folder in the database.
-        currentBookmarksFolder = "";
-
-        // Load the home folder, which is `""` in the database.
+        // Load the bookmarks folder.
         loadBookmarksFolder();
 
+        // Handle clicks on bookmarks.
         bookmarksListView.setOnItemClickListener((parent, view, position, id) -> {
             // Convert the id from long to int to match the format of the bookmarks database.
             int databaseId = (int) id;
@@ -3497,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);
 
@@ -3519,9 +3506,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Store the values from the shared preferences in variables.
         incognitoModeEnabled = sharedPreferences.getBoolean("incognito_mode", false);
-        sanitizeGoogleAnalytics = sharedPreferences.getBoolean("google_analytics", true);
-        sanitizeFacebookClickIds = sharedPreferences.getBoolean("facebook_click_ids", true);
-        sanitizeTwitterAmpRedirects = sharedPreferences.getBoolean("twitter_amp_redirects", true);
+        sanitizeTrackingQueries = sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true);
+        sanitizeAmpRedirects = sharedPreferences.getBoolean(getString(R.string.amp_redirects_key), true);
         proxyMode = sharedPreferences.getString("proxy", getString(R.string.proxy_default_value));
         fullScreenBrowsingModeEnabled = sharedPreferences.getBoolean("full_screen_browsing_mode", false);
         downloadWithExternalApp = sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false);
@@ -3737,10 +3723,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
             }
 
-            // Initialize the database handler.
-            DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(this);
-
-            // Get a full cursor from `domainsDatabaseHelper`.
+            // Get a full domain name cursor.
             Cursor domainNameCursor = domainsDatabaseHelper.getDomainNameCursorOrderedByDomain();
 
             // Initialize `domainSettingsSet`.
@@ -3795,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);
@@ -3831,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));
@@ -3877,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.
@@ -3966,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.
@@ -4070,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);
 
@@ -4158,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());
         }
     }
 
@@ -4498,49 +4510,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     private String sanitizeUrl(String url) {
-        // Sanitize Google Analytics.
-        if (sanitizeGoogleAnalytics) {
-            // Remove `?utm_`.
-            if (url.contains("?utm_")) {
-                url = url.substring(0, url.indexOf("?utm_"));
-            }
-
-            // Remove `&utm_`.
-            if (url.contains("&utm_")) {
-                url = url.substring(0, url.indexOf("&utm_"));
-            }
-        }
-
-        // Sanitize Facebook Click IDs.
-        if (sanitizeFacebookClickIds) {
-            // Remove `?fbclid=`.
-            if (url.contains("?fbclid=")) {
-                url = url.substring(0, url.indexOf("?fbclid="));
-            }
-
-            // Remove `&fbclid=`.
-            if (url.contains("&fbclid=")) {
-                url = url.substring(0, url.indexOf("&fbclid="));
-            }
+        // Sanitize tracking queries.
+        if (sanitizeTrackingQueries)
+            url = sanitizeUrlHelper.sanitizeTrackingQueries(url);
 
-            // Remove `?fbadid=`.
-            if (url.contains("?fbadid=")) {
-                url = url.substring(0, url.indexOf("?fbadid="));
-            }
-
-            // Remove `&fbadid=`.
-            if (url.contains("&fbadid=")) {
-                url = url.substring(0, url.indexOf("&fbadid="));
-            }
-        }
-
-        // Sanitize Twitter AMP redirects.
-        if (sanitizeTwitterAmpRedirects) {
-            // Remove `?amp=1`.
-            if (url.contains("?amp=1")) {
-                url = url.substring(0, url.indexOf("?amp=1"));
-            }
-        }
+        // Sanitize AMP redirects.
+        if (sanitizeAmpRedirects)
+            url = sanitizeUrlHelper.sanitizeAmpRedirects(url);
 
         // Return the sanitized URL.
         return url;
@@ -4916,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) {