]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebView.java
Change the default user-agent to `PrivacyBrowser/1.0`.
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebView.java
index 00ea17818b35ef6ce111c33c0dabcee5be73c8f7..1024a7dbf10b4bb929a3396129656f5f8239ba70 100644 (file)
@@ -38,6 +38,7 @@ import android.preference.PreferenceManager;
 import android.print.PrintDocumentAdapter;
 import android.print.PrintManager;
 import android.support.annotation.NonNull;
+import android.support.design.widget.CoordinatorLayout;
 import android.support.design.widget.NavigationView;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.ActivityCompat;
@@ -52,13 +53,15 @@ import android.support.v7.app.AppCompatDialogFragment;
 import android.support.v7.widget.Toolbar;
 import android.text.Editable;
 import android.text.TextWatcher;
-import android.util.Log;
 import android.util.Patterns;
 import android.view.ContextMenu;
+import android.view.GestureDetector;
 import android.view.KeyEvent;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.WindowManager;
 import android.view.inputmethod.InputMethodManager;
 import android.webkit.CookieManager;
 import android.webkit.DownloadListener;
@@ -77,12 +80,8 @@ import android.widget.ProgressBar;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
-// These three GMS (Google Mobile Services) lines need to be removed for F-Droid to build correctly.
-import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
-import com.google.android.gms.common.GooglePlayServicesRepairableException;
-import com.google.android.gms.security.ProviderInstaller;
-
 import com.stoutner.privacybrowser.BannerAd;
+import com.stoutner.privacybrowser.BuildConfig;
 import com.stoutner.privacybrowser.R;
 import com.stoutner.privacybrowser.helpers.OrbotProxyHelper;
 import com.stoutner.privacybrowser.dialogs.CreateHomeScreenShortcut;
@@ -119,9 +118,22 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     public static SslCertificate sslCertificate;
 
 
+
+    // `drawerLayout` is used in `onCreate()`, `onNewIntent()`, and `onBackPressed()`.
+    private DrawerLayout drawerLayout;
+
+    // `rootCoordinatorLayout` is used in `onCreate()` and `applySettings()`.
+    private CoordinatorLayout rootCoordinatorLayout;
+
     // 'mainWebView' is used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, `onCreateContextMenu()`, `findPreviousOnPage()`, `findNextOnPage()`, `closeFindOnPage()`, and `loadUrlFromTextBox()`.
     private WebView mainWebView;
 
+    // `findOnPageEditText` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
+    private EditText findOnPageEditText;
+
+    // `fullScreenVideoFrameLayout` is used in `onCreate()` and `onConfigurationChanged()`.
+    private FrameLayout fullScreenVideoFrameLayout;
+
     // `swipeRefreshLayout` is used in `onCreate()`, `onPrepareOptionsMenu`, and `onRestart()`.
     private SwipeRefreshLayout swipeRefreshLayout;
 
@@ -159,15 +171,18 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     // `javaScriptEnabledSearchURL` is used in `loadURLFromTextBox()` and `applySettings()`.
     private String javaScriptEnabledSearchURL;
 
+    // `hideSystemBarsOnFullscreen` is used in `onCreate()` and `applySettings()`.
+    private boolean hideSystemBarsOnFullscreen;
+
+    // `translucentNavigationBarOnFullscreen` is used in `onCreate()` and `applySettings()`.
+    private boolean translucentNavigationBarOnFullscreen;
+
     // `mainMenu` is used in `onCreateOptionsMenu()` and `updatePrivacyIcons()`.
     private Menu mainMenu;
 
     // `drawerToggle` is used in `onCreate()`, `onPostCreate()`, `onConfigurationChanged()`, `onNewIntent()`, and `onNavigationItemSelected()`.
     private ActionBarDrawerToggle drawerToggle;
 
-    // `drawerLayout` is used in `onCreate()`, `onNewIntent()`, and `onBackPressed()`.
-    private DrawerLayout drawerLayout;
-
     // `urlTextBox` is used in `onCreate()`, `onOptionsItemSelected()`, and `loadUrlFromTextBox()`.
     private EditText urlTextBox;
 
@@ -177,9 +192,6 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     // `sslErrorHandler` is used in `onCreate()`, `onSslErrorCancel()`, and `onSslErrorProceed`.
     private SslErrorHandler sslErrorHandler;
 
-    // `findOnPageEditText` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
-    private EditText findOnPageEditText;
-
     // `inputMethodManager` is used in `onOptionsItemSelected()`, `loadUrlFromTextBox()`, and `closeFindOnPage()`.
     private InputMethodManager inputMethodManager;
 
@@ -188,29 +200,17 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     @SuppressLint("SetJavaScriptEnabled")
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.main_coordinatorlayout);
-
-        // API 19 uses an old version of OpenSSL, which exposes users to man-in-the-middle attacks.
-        if (Build.VERSION.SDK_INT == 19) {
-            try {
-                // Update OpenSSL using Google Play Services.  This command must be removed for the build to succeed on F-Droid.
-                ProviderInstaller.installIfNeeded(this);
-            } catch (GooglePlayServicesRepairableException exception) {
-                Log.i("Privacy Browser", "OpenSSL needs to be updated");
-            } catch (GooglePlayServicesNotAvailableException exception) {
-                Log.i("Privacy Browser", "OpenSSL cannot be updated because Google Play Services are not available");
-            }
-        }
+        setContentView(R.layout.drawerlayout);
 
         // Get a handle for `inputMethodManager`.
         inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
 
-        // We need to use the SupportActionBar from android.support.v7.app.ActionBar until the minimum API is >= 21.
-        Toolbar supportAppBar = (Toolbar) findViewById(R.id.appBar);
+        // We need to use the `SupportActionBar` from `android.support.v7.app.ActionBar` until the minimum API is >= 21.
+        Toolbar supportAppBar = (Toolbar) findViewById(R.id.app_bar);
         setSupportActionBar(supportAppBar);
         appBar = getSupportActionBar();
 
-        // This is needed to get rid of the Android Studio warning that appBar might be null.
+        // This is needed to get rid of the Android Studio warning that `appBar` might be null.
         assert appBar != null;
 
         // Add the custom url_app_bar layout, which shows the favoriteIcon, urlTextBar, and progressBar.
@@ -239,15 +239,96 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             }
         });
 
-        // Get handles for `fullScreenVideoFrameLayout`, `mainWebView`, and `find_on_page_edittext`.
-        final FrameLayout fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.fullScreenVideoFrameLayout);
+        // Get handles for views that need to be accessed.
+        drawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout);
+        rootCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.root_coordinatorlayout);
         mainWebView = (WebView) findViewById(R.id.mainWebView);
         findOnPageEditText = (EditText) findViewById(R.id.find_on_page_edittext);
+        fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.full_screen_video_framelayout);
+
+        // Create a double-tap listener to toggle full-screen mode.
+        final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
+            // Override `onDoubleTap()`.  All other events are handled using the default settings.
+            @Override
+            public boolean onDoubleTap(MotionEvent event) {
+                if (appBar.isShowing()) {  // If `appBar` is visible, switch to full screen mode.
+                    // Hide the `appBar`.
+                    appBar.hide();
+
+                    // Hide the `BannerAd` in the free flavor.
+                    if (BuildConfig.FLAVOR.contentEquals("free")) {
+                        BannerAd.hideAd(adView);
+                    }
+
+                    // Modify the system bars.
+                    if (hideSystemBarsOnFullscreen) {  // Hide everything.
+                        // Remove the translucent overlays.
+                        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+                        // Remove the translucent status bar overlay on the `Drawer Layout`, which is special and needs its own command.
+                        drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+
+                        /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+                         * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+                         * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically rehides them after they are shown.
+                         */
+                        rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+
+                        // Set `rootCoordinatorLayout` to fill the whole screen.
+                        rootCoordinatorLayout.setFitsSystemWindows(false);
+                    } else {  // Hide everything except the status and navigation bars.
+                        // Set `rootCoordinatorLayout` to fit under the status and navigation bars.
+                        rootCoordinatorLayout.setFitsSystemWindows(false);
+
+                        if (translucentNavigationBarOnFullscreen) {  // There is an Android Support Library bug that causes a scrim to print on the right side of the `Drawer Layout` when the navigation bar is displayed on the right of the screen.
+                            // Set the navigation bar to be translucent.
+                            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+                        }
+                    }
+                } else {  // Switch to normal viewing mode.
+                    // Show the `appBar`.
+                    appBar.show();
+
+                    // Show the `BannerAd` in the free flavor.
+                    if (BuildConfig.FLAVOR.contentEquals("free")) {
+                        // Reload the ad.  Because the screen may have rotated, we need to use `reloadAfterRotate`.
+                        BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
+
+                        // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
+                        adView = findViewById(R.id.adView);
+                    }
+
+                    // Remove the translucent navigation bar flag if it is set.
+                    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+
+                    // Add the translucent status flag if it is unset.  This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
+                    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+                    // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+                    rootCoordinatorLayout.setSystemUiVisibility(0);
+
+                    // Constrain `rootCoordinatorLayout` inside the status and navigation bars.
+                    rootCoordinatorLayout.setFitsSystemWindows(true);
+                }
+
+                // Consume the double-tap.
+                return true;
+            }
+        });
+
+        // Pass all touch events on `mainWebView` through `gestureDetector` to check for double-taps.
+        mainWebView.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                // Send the `event` to `gestureDetector`.
+                return gestureDetector.onTouchEvent(event);
+            }
+        });
 
         // Update `findOnPageCountTextView`.
         mainWebView.setFindListener(new WebView.FindListener() {
             // Get a handle for `findOnPageCountTextView`.
-            TextView findOnPageCountTextView = (TextView) findViewById(R.id.find_on_page_count_textview);
+            final TextView findOnPageCountTextView = (TextView) findViewById(R.id.find_on_page_count_textview);
 
             @Override
             public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, boolean isDoneCounting) {
@@ -310,16 +391,14 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             }
         });
 
-        // Create the navigation drawer.
-        drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
-        // `DrawerTitle` identifies the drawer in accessibility mode.
+        // `DrawerTitle` identifies the `DrawerLayout` in accessibility mode.
         drawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.navigation_drawer));
 
         // Listen for touches on the navigation menu.
-        final NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);
+        final NavigationView navigationView = (NavigationView) findViewById(R.id.navigationview);
         navigationView.setNavigationItemSelectedListener(this);
 
-        // Get handles for `navigationMenu` and the back and forward menu items.  The menu is zero-based, so item 1 and 2 and the second and third items in the menu.
+        // Get handles for `navigationMenu` and the back and forward menu items.  The menu is zero-based, so items 1, 2, and 3 are the second, third, and fourth entries in the menu.
         final Menu navigationMenu = navigationView.getMenu();
         final MenuItem navigationBackMenuItem = navigationMenu.getItem(1);
         final MenuItem navigationForwardMenuItem = navigationMenu.getItem(2);
@@ -352,7 +431,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         });
 
         // drawerToggle creates the hamburger icon at the start of the AppBar.
-        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, supportAppBar, R.string.open_navigation, R.string.close_navigation);
+        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, supportAppBar, R.string.open_navigation_drawer, R.string.close_navigation_drawer);
 
         mainWebView.setWebViewClient(new WebViewClient() {
             // `shouldOverrideUrlLoading` makes this `WebView` the default handler for URLs inside the app, so that links are not kicked out to other apps.
@@ -360,7 +439,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             @SuppressWarnings("deprecation")
             @Override
             public boolean shouldOverrideUrlLoading(WebView view, String url) {
-                // Use an external email program if the link begins with "mailto:".
+                // Use an external email program if the link begins with `mailto:`.
                 if (url.startsWith("mailto:")) {
                     // We use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched.
                     Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
@@ -446,38 +525,51 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             // Enter full screen video
             @Override
             public void onShowCustomView(View view, CustomViewCallback callback) {
-                appBar.hide();
-
-                // Show the fullScreenVideoFrameLayout.
-                fullScreenVideoFrameLayout.addView(view);
-                fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
+                // Pause the ad if this is the free flavor.
+                if (BuildConfig.FLAVOR.contentEquals("free")) {
+                    BannerAd.pauseAd(adView);
+                }
 
-                // Hide the mainWebView.
-                mainWebView.setVisibility(View.GONE);
+                // Remove the translucent overlays.
+                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
 
-                // Hide the ad if this is the free flavor.
-                BannerAd.hideAd(adView);
+                // Remove the translucent status bar overlay on the `Drawer Layout`, which is special and needs its own command.
+                drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
 
-                /* SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bars on the bottom or right of the screen.
-                 * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar across the top of the screen.
-                 * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the navigation and status bars ghosted overlays and automatically rehides them.
+                /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+                 * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+                 * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically rehides them after they are shown.
                  */
-                view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+                rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+
+                // Set `rootCoordinatorLayout` to fill the entire screen.
+                rootCoordinatorLayout.setFitsSystemWindows(false);
+
+                // Add `view` to `fullScreenVideoFrameLayout` and display it on the screen.
+                fullScreenVideoFrameLayout.addView(view);
+                fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
             }
 
             // Exit full screen video
             public void onHideCustomView() {
-                appBar.show();
+                // Hide `fullScreenVideoFrameLayout`.
+                fullScreenVideoFrameLayout.removeAllViews();
+                fullScreenVideoFrameLayout.setVisibility(View.GONE);
 
-                // Show the mainWebView.
-                mainWebView.setVisibility(View.VISIBLE);
+                // Add the translucent status flag.  This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
+                getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+                // Set `rootCoordinatorLayout` to fit inside the status and navigation bars.  This also clears the `SYSTEM_UI` flags.
+                rootCoordinatorLayout.setFitsSystemWindows(true);
 
                 // Show the ad if this is the free flavor.
-                BannerAd.showAd(adView);
+                if (BuildConfig.FLAVOR.contentEquals("free")) {
+                    // Reload the ad.  Because the screen may have rotated, we need to use `reloadAfterRotate`.
+                    BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
 
-                // Hide the fullScreenVideoFrameLayout.
-                fullScreenVideoFrameLayout.removeAllViews();
-                fullScreenVideoFrameLayout.setVisibility(View.GONE);
+                    // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
+                    adView = findViewById(R.id.adView);
+                }
             }
         });
 
@@ -877,7 +969,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
 
             case R.id.find_on_page:
                 // Hide the URL app bar.
-                Toolbar appBarToolbar = (Toolbar) findViewById(R.id.appBar);
+                Toolbar appBarToolbar = (Toolbar) findViewById(R.id.app_bar);
                 appBarToolbar.setVisibility(View.GONE);
 
                 // Show the Find on Page `RelativeLayout`.
@@ -1073,11 +1165,14 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
-        // Reload the ad if this is the free flavor.
-        BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
+        // Reload the ad for the free flavor if we are not in full screen mode.
+        if (BuildConfig.FLAVOR.contentEquals("free") && adView.isShown() && !fullScreenVideoFrameLayout.isShown()) {
+            // Reload the ad.
+            BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
 
-        // Reinitialize the adView variable, as the View will have been removed and re-added in the free flavor by BannerAd.reloadAfterRotate().
-        adView = findViewById(R.id.adView);
+            // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
+            adView = findViewById(R.id.adView);
+        }
 
         // `invalidateOptionsMenu` should recalculate the number of action buttons from the menu to display on the app bar, but it doesn't because of the this bug:  https://code.google.com/p/android/issues/detail?id=20493#c8
         // ActivityCompat.invalidateOptionsMenu(this);
@@ -1322,11 +1417,9 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         mainWebView.clearHistory();
     }
 
-    // Override onBackPressed to handle the navigation drawer and mainWebView.
+    // Override `onBackPressed` to handle the navigation drawer and `mainWebView`.
     @Override
     public void onBackPressed() {
-        final WebView mainWebView = (WebView) findViewById(R.id.mainWebView);
-
         // Close the navigation drawer if it is available.  GravityCompat.START is the drawer on the left on Left-to-Right layout text.
         if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
             drawerLayout.closeDrawer(GravityCompat.START);
@@ -1335,7 +1428,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             if (mainWebView.canGoBack()) {
                 mainWebView.goBack();
             } else {
-                // Pass onBackPressed to the system.
+                // Pass `onBackPressed()` to the system.
                 super.onBackPressed();
             }
         }
@@ -1345,10 +1438,14 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     public void onPause() {
         // Pause `mainWebView`.
         mainWebView.onPause();
+
+        // Stop all JavaScript.
         mainWebView.pauseTimers();
 
-        // We need to pause the adView or it will continue to consume resources in the background on the free flavor.
-        BannerAd.pauseAd(adView);
+        // Pause the adView or it will continue to consume resources in the background on the free flavor.
+        if (BuildConfig.FLAVOR.contentEquals("free")) {
+            BannerAd.pauseAd(adView);
+        }
 
         super.onPause();
     }
@@ -1357,12 +1454,16 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     public void onResume() {
         super.onResume();
 
-        // Resume `mainWebView`.
+        // Resume JavaScript (if enabled).
         mainWebView.resumeTimers();
+
+        // Resume `mainWebView`.
         mainWebView.onResume();
 
-        // We need to resume the adView for the free flavor.
-        BannerAd.resumeAd(adView);
+        // Resume the adView for the free flavor.
+        if (BuildConfig.FLAVOR.contentEquals("free")) {
+            BannerAd.resumeAd(adView);
+        }
     }
 
     @Override
@@ -1447,7 +1548,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         findOnPageLinearLayout.setVisibility(View.GONE);
 
         // Show the URL app bar.
-        Toolbar appBarToolbar = (Toolbar) findViewById(R.id.appBar);
+        Toolbar appBarToolbar = (Toolbar) findViewById(R.id.app_bar);
         appBarToolbar.setVisibility(View.VISIBLE);
 
         // Hide the keyboard so we can see the webpage.  `0` indicates no additional flags.
@@ -1459,7 +1560,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
         // Store the values from `sharedPreferences` in variables.
-        String userAgentString = sharedPreferences.getString("user_agent", "Default user agent");
+        String userAgentString = sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0");
         String customUserAgentString = sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0");
         String javaScriptDisabledSearchString = sharedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=");
         String javaScriptDisabledCustomSearchString = sharedPreferences.getString("javascript_disabled_search_custom_url", "");
@@ -1470,6 +1571,8 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         swipeToRefreshEnabled = sharedPreferences.getBoolean("swipe_to_refresh_enabled", false);
         boolean doNotTrackEnabled = sharedPreferences.getBoolean("do_not_track", true);
         boolean proxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
+        hideSystemBarsOnFullscreen = sharedPreferences.getBoolean("hide_system_bars", false);
+        translucentNavigationBarOnFullscreen = sharedPreferences.getBoolean("translucent_navigation_bar", true);
 
         // Because they can be modified on-the-fly by the user, these default settings are only applied when the program first runs.
         if (javaScriptEnabled == null) {  // If `javaScriptEnabled` is null the program is just starting.
@@ -1543,6 +1646,37 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         } else {  // Reset the proxy to default.  The host is `""` and the port is `"0"`.
             OrbotProxyHelper.setProxy(getApplicationContext(), this, "", "0");
         }
+
+        // If we are in full screen mode update the `SYSTEM_UI` flags.
+        if (!appBar.isShowing()) {
+            if (hideSystemBarsOnFullscreen) {  // Hide everything.
+                // Remove the translucent navigation setting if it is currently flagged.
+                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+
+                // Remove the translucent status bar overlay.
+                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+                // Remove the translucent status bar overlay on the `Drawer Layout`, which is special and needs its own command.
+                drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+
+                /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+                 * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+                 * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically rehides them after they are shown.
+                 */
+                rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+            } else {  // Hide everything except the status and navigation bars.
+                // Add the translucent status flag if it is unset.
+                getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+                if (translucentNavigationBarOnFullscreen) {
+                    // Set the navigation bar to be translucent.
+                    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+                } else {
+                    // Set the navigation bar to be black.
+                    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+                }
+            }
+        }
     }
 
     private void updatePrivacyIcons(boolean runInvalidateOptionsMenu) {