Temporarially disable Find on Page until the feature is completed.
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / MainWebViewActivity.java
index 87f30afe125afe43b6fc8e7f818223050fd730c6..982ff2d254c1de5ad9df6e43a2e7a489d22c970d 100644 (file)
@@ -31,10 +31,14 @@ import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.net.http.SslCertificate;
 import android.net.http.SslError;
 import android.os.Build;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
 import android.net.http.SslError;
 import android.os.Build;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintManager;
+import android.support.annotation.NonNull;
 import android.support.design.widget.NavigationView;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.ActivityCompat;
 import android.support.design.widget.NavigationView;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.ActivityCompat;
@@ -45,6 +49,7 @@ import android.support.v4.widget.SwipeRefreshLayout;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.ActionBarDrawerToggle;
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.ActionBarDrawerToggle;
 import android.support.v7.app.AppCompatActivity;
+import android.support.v7.app.AppCompatDialogFragment;
 import android.support.v7.widget.Toolbar;
 import android.util.Patterns;
 import android.view.KeyEvent;
 import android.support.v7.widget.Toolbar;
 import android.util.Patterns;
 import android.view.KeyEvent;
@@ -75,73 +80,65 @@ import java.util.Map;
 // We need to use AppCompatActivity from android.support.v7.app.AppCompatActivity to have access to the SupportActionBar until the minimum API is >= 21.
 public class MainWebViewActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, CreateHomeScreenShortcut.CreateHomeScreenSchortcutListener,
         SslCertificateError.SslCertificateErrorListener, DownloadFile.DownloadFileListener {
 // We need to use AppCompatActivity from android.support.v7.app.AppCompatActivity to have access to the SupportActionBar until the minimum API is >= 21.
 public class MainWebViewActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, CreateHomeScreenShortcut.CreateHomeScreenSchortcutListener,
         SslCertificateError.SslCertificateErrorListener, DownloadFile.DownloadFileListener {
-    // `privacyBrowserContext` is public static so it can be accessed from `SettingsFragment`.
-    // It is also used in `onCreate()` and `onConfigurationChanged()`.
-    public static Context privacyBrowserContext;
 
     // `appBar` is public static so it can be accessed from `OrbotProxyHelper`.
 
     // `appBar` is public static so it can be accessed from `OrbotProxyHelper`.
-    // It is also used in `onCreate()`.
+    // It is also used in `onCreate()` and `onOptionsItemSelected()`.
     public static ActionBar appBar;
 
     // `favoriteIcon` is public static so it can be accessed from `CreateHomeScreenShortcut`, `BookmarksActivity`, `CreateBookmark`, `CreateBookmarkFolder`, and `EditBookmark`.
     // It is also used in `onCreate()` and `onCreateHomeScreenShortcutCreate()`.
     public static Bitmap favoriteIcon;
 
     public static ActionBar appBar;
 
     // `favoriteIcon` is public static so it can be accessed from `CreateHomeScreenShortcut`, `BookmarksActivity`, `CreateBookmark`, `CreateBookmarkFolder`, and `EditBookmark`.
     // It is also used in `onCreate()` and `onCreateHomeScreenShortcutCreate()`.
     public static Bitmap favoriteIcon;
 
-    // `privacyBrowserActivity` is public static so it can be accessed from `SettingsFragment`.
-    // It is also used in `onCreate()`, `onCreateOptionsMenu()`, and `onOptionsItemSelected()`,
-    public static Activity privacyBrowserActivity;
-
-    // `mainWebView` is public static so it can be accessed from `SettingsFragment`.
-    // It is also used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, and `loadUrlFromTextBox()`.
-    public static WebView mainWebView;
-
     // `formattedUrlString` is public static so it can be accessed from `BookmarksActivity`.
     // It is also used in `onCreate()`, `onOptionsItemSelected()`, `onCreateHomeScreenShortcutCreate()`, and `loadUrlFromTextBox()`.
     public static String formattedUrlString;
 
     // `formattedUrlString` is public static so it can be accessed from `BookmarksActivity`.
     // It is also used in `onCreate()`, `onOptionsItemSelected()`, `onCreateHomeScreenShortcutCreate()`, and `loadUrlFromTextBox()`.
     public static String formattedUrlString;
 
-    // `mainMenu` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onCreateOptionsMenu()` and `onOptionsItemSelected()`.
-    public static Menu mainMenu;
+    // `sslCertificate` is public static so it can be accessed from `ViewSslCertificate`.  It is also used in `onCreate()`.
+    public static SslCertificate sslCertificate;
+
 
 
-    // `cookieManager` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onCreate()`, `onOptionsItemSelected()`, and `onNavigationItemSelected()`.
-    public static CookieManager cookieManager;
+    // 'mainWebView' is used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, and `loadUrlFromTextBox()`.
+    private WebView mainWebView;
 
 
-    // `javaScriptEnabled` is public static so it can be accessed from `SettingsFragment`.
-    // It is also used in `onCreate()`, `onCreateOptionsMenu()`, `onOptionsItemSelected()`, and `loadUrlFromTextBox()`.
-    public static boolean javaScriptEnabled;
+    // `swipeRefreshLayout` is used in `onCreate()`, `onPrepareOptionsMenu`, and `onRestart()`.
+    private SwipeRefreshLayout swipeRefreshLayout;
 
 
-    // `firstPartyCookiesEnabled` is public static so it can be accessed from `SettingsFragment`.
-    // It is also used in `onCreate()`, `onCreateOptionsMenu()`, `onPrepareOptionsMenu()`, and `onOptionsItemSelected()`.
-    public static boolean firstPartyCookiesEnabled;
+    // `cookieManager` is used in `onCreate()`, `onOptionsItemSelected()`, and `onNavigationItemSelected()`, and `onRestart()`.
+    private CookieManager cookieManager;
 
 
-    // `thirdPartyCookiesEnables` is public static so it can be accessed from `SettingsFragment`.
-    // It is also used in `onCreate()`, `onCreateOptionsMenu()`, `onPrepareOptionsMenu()`, and `onOptionsItemSelected()`.
-    public static boolean thirdPartyCookiesEnabled;
+    // `customHeader` is used in `onCreate()`, `onOptionsItemSelected()`, and `loadUrlFromTextBox()`.
+    private final Map<String, String> customHeaders = new HashMap<>();
 
 
-    // `domStorageEnabled` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onCreate()`, `onCreateOptionsMenu()`, and `onOptionsItemSelected()`.
-    public static boolean domStorageEnabled;
+    // `javaScriptEnabled` is also used in `onCreate()`, `onCreateOptionsMenu()`, `onOptionsItemSelected()`, `loadUrlFromTextBox()`, and `applySettings()`.
+    // It is `Boolean` instead of `boolean` because `applySettings()` needs to know if it is `null`.
+    private Boolean javaScriptEnabled;
 
 
-    // `saveFormDataEnabled` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onCreate()`, `onCreateOptionsMenu()`, and `onOptionsItemSelected()`.
-    public static boolean saveFormDataEnabled;
+    // `firstPartyCookiesEnabled` is used in `onCreate()`, `onCreateOptionsMenu()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applySettings()`.
+    private boolean firstPartyCookiesEnabled;
 
 
-    // `javaScriptDisabledSearchURL` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onCreate()` and `loadURLFromTextBox()`.
-    public static String javaScriptDisabledSearchURL;
+    // `thirdPartyCookiesEnabled` used in `onCreate()`, `onCreateOptionsMenu()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applySettings()`.
+    private boolean thirdPartyCookiesEnabled;
 
 
-    // `javaScriptEnabledSearchURL` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onCreate()` and `loadURLFromTextBox()`.
-    public static String javaScriptEnabledSearchURL;
+    // `domStorageEnabled` is used in `onCreate()`, `onCreateOptionsMenu()`, `onOptionsItemSelected()`, and `applySettings()`.
+    private boolean domStorageEnabled;
 
 
-    // `homepage` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onCreate()` and `onOptionsItemSelected()`.
-    public static String homepage;
+    // `saveFormDataEnabled` is used in `onCreate()`, `onCreateOptionsMenu()`, `onOptionsItemSelected()`, and `applySettings()`.
+    private boolean saveFormDataEnabled;
 
 
-    // `swipeToRefresh` is public static so it can be accessed from SettingsFragment.  It is also used in onCreate().
-    public static SwipeRefreshLayout swipeToRefresh;
+    // `swipeToRefreshEnabled` is used in `onPrepareOptionsMenu()` and `applySettings()`.
+    private boolean swipeToRefreshEnabled;
 
 
-    // `swipeToRefreshEnabled` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onCreate()`.
-    public static boolean swipeToRefreshEnabled;
+    // 'homepage' is used in `onCreate()`, `onNavigationItemSelected()`, and `applySettings()`.
+    private String homepage;
 
 
-    // `customHeader` is public static so it can be accessed from `BookmarksActivity`.  It is also used in `onCreate()`, `onOptionsItemSelected()`, and `loadUrlFromTextBox()`.
-    public static Map<String, String> customHeaders = new HashMap<String, String>();
+    // `javaScriptDisabledSearchURL` is used in `loadURLFromTextBox()` and `applySettings()`.
+    private String javaScriptDisabledSearchURL;
 
 
+    // `javaScriptEnabledSearchURL` is used in `loadURLFromTextBox()` and `applySettings()`.
+    private String javaScriptEnabledSearchURL;
 
 
+    // `mainMenu` is used in `onCreateOptionsMenu()` and `updatePrivacyIcons()`.
+    private Menu mainMenu;
 
     // `drawerToggle` is used in `onCreate()`, `onPostCreate()`, `onConfigurationChanged()`, `onNewIntent()`, and `onNavigationItemSelected()`.
     private ActionBarDrawerToggle drawerToggle;
 
     // `drawerToggle` is used in `onCreate()`, `onPostCreate()`, `onConfigurationChanged()`, `onNewIntent()`, and `onNavigationItemSelected()`.
     private ActionBarDrawerToggle drawerToggle;
@@ -158,8 +155,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     // `sslErrorHandler` is used in `onCreate()`, `onSslErrorCancel()`, and `onSslErrorProceed`.
     private SslErrorHandler sslErrorHandler;
 
     // `sslErrorHandler` is used in `onCreate()`, `onSslErrorCancel()`, and `onSslErrorProceed`.
     private SslErrorHandler sslErrorHandler;
 
-    // `sharedPreferences` is used in `onCreate()` and `onCreateOptionsMenu()`.
-    SharedPreferences sharedPreferences;
+    private MenuItem toggleJavaScript;
 
     @Override
     // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.  The whole premise of Privacy Browser is built around an understanding of these dangers.
 
     @Override
     // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.  The whole premise of Privacy Browser is built around an understanding of these dangers.
@@ -168,12 +164,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main_coordinatorlayout);
 
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main_coordinatorlayout);
 
-        // We need a handle for the activity, which is accessed from `SettingsFragment` and fed into `updatePrivacyIcons()`.
-        privacyBrowserActivity = this;
-
-        // Get a handle for the application context.
-        privacyBrowserContext = getApplicationContext();
-
         // 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);
         setSupportActionBar(supportAppBar);
         // 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);
         setSupportActionBar(supportAppBar);
@@ -182,8 +172,8 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // This is needed to get rid of the Android Studio warning that appBar might be null.
         assert appBar != null;
 
         // This is needed to get rid of the Android Studio warning that appBar might be null.
         assert appBar != null;
 
-        // Add the custom url_bar layout, which shows the favoriteIcon, urlTextBar, and progressBar.
-        appBar.setCustomView(R.layout.url_bar);
+        // Add the custom url_app_bar layout, which shows the favoriteIcon, urlTextBar, and progressBar.
+        appBar.setCustomView(R.layout.url_app_bar);
         appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
 
         // Set the "go" button on the keyboard to load the URL in urlTextBox.
         appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
 
         // Set the "go" button on the keyboard to load the URL in urlTextBox.
@@ -210,10 +200,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         final FrameLayout fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.fullScreenVideoFrameLayout);
 
         // Implement swipe to refresh
         final FrameLayout fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.fullScreenVideoFrameLayout);
 
         // Implement swipe to refresh
-        swipeToRefresh = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
-        assert swipeToRefresh != null; //This assert removes the incorrect warning on the following line that swipeToRefresh might be null.
-        swipeToRefresh.setColorSchemeResources(R.color.blue_700);
-        swipeToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
+        swipeRefreshLayout.setColorSchemeResources(R.color.blue_700);
+        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
             @Override
             public void onRefresh() {
                 mainWebView.reload();
             @Override
             public void onRefresh() {
                 mainWebView.reload();
@@ -229,14 +218,15 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
 
         // Listen for touches on the navigation menu.
         final NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);
 
         // Listen for touches on the navigation menu.
         final NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);
-        assert navigationView != null; // This assert removes the incorrect warning on the following line that navigationView might be null.
         navigationView.setNavigationItemSelectedListener(this);
 
         // 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);
 
         mainWebView.setWebViewClient(new WebViewClient() {
         navigationView.setNavigationItemSelectedListener(this);
 
         // 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);
 
         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.
+            // `shouldOverrideUrlLoading` makes this `WebView` the default handler for URLs inside the app, so that links are not kicked out to other apps.
+            // We have to use the deprecated `shouldOverrideUrlLoading` until API >= 24.
+            @SuppressWarnings("deprecation")
             @Override
             public boolean shouldOverrideUrlLoading(WebView view, String url) {
                 // Use an external email program if the link begins with "mailto:".
             @Override
             public boolean shouldOverrideUrlLoading(WebView view, String url) {
                 // Use an external email program if the link begins with "mailto:".
@@ -262,6 +252,10 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             // Update the URL in urlTextBox when the page starts to load.
             @Override
             public void onPageStarted(WebView view, String url, Bitmap favicon) {
             // Update the URL in urlTextBox when the page starts to load.
             @Override
             public void onPageStarted(WebView view, String url, Bitmap favicon) {
+                // We need to update `formattedUrlString` at the beginning of the load, so that if the user toggles JavaScript during the load the new website is reloaded.
+                formattedUrlString = url;
+
+                // Display the loading URL is the URL text box.
                 urlTextBox.setText(url);
             }
 
                 urlTextBox.setText(url);
             }
 
@@ -274,6 +268,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 if (!urlTextBox.hasFocus()) {
                     urlTextBox.setText(formattedUrlString);
                 }
                 if (!urlTextBox.hasFocus()) {
                     urlTextBox.setText(formattedUrlString);
                 }
+
+                // Store the SSL certificate so it can be accessed from `ViewSslCertificate`.
+                sslCertificate = mainWebView.getCertificate();
             }
 
             // Handle SSL Certificate errors.
             }
 
             // Handle SSL Certificate errors.
@@ -299,8 +296,8 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 } else {
                     progressBar.setVisibility(View.GONE);
 
                 } else {
                     progressBar.setVisibility(View.GONE);
 
-                    //Stop the SwipeToRefresh indicator if it is running
-                    swipeToRefresh.setRefreshing(false);
+                    //Stop the `SwipeToRefresh` indicator if it is running
+                    swipeRefreshLayout.setRefreshing(false);
                 }
             }
 
                 }
             }
 
@@ -321,7 +318,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 appBar.hide();
 
                 // Show the fullScreenVideoFrameLayout.
                 appBar.hide();
 
                 // Show the fullScreenVideoFrameLayout.
-                assert fullScreenVideoFrameLayout != null; //This assert removes the incorrect warning on the following line that fullScreenVideoFrameLayout might be null.
                 fullScreenVideoFrameLayout.addView(view);
                 fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
 
                 fullScreenVideoFrameLayout.addView(view);
                 fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
 
@@ -349,7 +345,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 BannerAd.showAd(adView);
 
                 // Hide the fullScreenVideoFrameLayout.
                 BannerAd.showAd(adView);
 
                 // Hide the fullScreenVideoFrameLayout.
-                assert fullScreenVideoFrameLayout != null; //This assert removes the incorrect warning on the following line that fullScreenVideoFrameLayout might be null.
                 fullScreenVideoFrameLayout.removeAllViews();
                 fullScreenVideoFrameLayout.setVisibility(View.GONE);
             }
                 fullScreenVideoFrameLayout.removeAllViews();
                 fullScreenVideoFrameLayout.setVisibility(View.GONE);
             }
@@ -360,8 +355,8 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             @Override
             public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
                 // Show the `DownloadFile` `AlertDialog` and name this instance `@string/download`.
             @Override
             public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
                 // Show the `DownloadFile` `AlertDialog` and name this instance `@string/download`.
-                DialogFragment downloadFileDialogFragment = DownloadFile.fromUrl(url, contentDisposition, contentLength);
-                downloadFileDialogFragment.show(getFragmentManager(), getResources().getString(R.string.download));
+                AppCompatDialogFragment downloadFileDialogFragment = DownloadFile.fromUrl(url, contentDisposition, contentLength);
+                downloadFileDialogFragment.show(getSupportFragmentManager(), getResources().getString(R.string.download));
             }
         });
 
             }
         });
 
@@ -371,99 +366,17 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // Hide zoom controls.
         mainWebView.getSettings().setDisplayZoomControls(false);
 
         // Hide zoom controls.
         mainWebView.getSettings().setDisplayZoomControls(false);
 
-
-        // Initialize the default preference values the first time the program is run.
-        PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
-
-        // Get the shared preference values.
-        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
-
-        // Set JavaScript initial status.  The default value is false.
-        javaScriptEnabled = sharedPreferences.getBoolean("javascript_enabled", false);
-        mainWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
-
         // Initialize cookieManager.
         cookieManager = CookieManager.getInstance();
 
         // Initialize cookieManager.
         cookieManager = CookieManager.getInstance();
 
-        // Set cookies initial status.  The default value is false.
-        firstPartyCookiesEnabled = sharedPreferences.getBoolean("first_party_cookies_enabled", false);
-        cookieManager.setAcceptCookie(firstPartyCookiesEnabled);
-
-        // Set third-party cookies initial status if API >= 21.  The default value is false.
-        if (Build.VERSION.SDK_INT >= 21) {
-            thirdPartyCookiesEnabled = sharedPreferences.getBoolean("third_party_cookies_enabled", false);
-            cookieManager.setAcceptThirdPartyCookies(mainWebView, thirdPartyCookiesEnabled);
-        }
-
-        // Set DOM storage initial status.  The default value is false.
-        domStorageEnabled = sharedPreferences.getBoolean("dom_storage_enabled", false);
-        mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
-
-        // Set the saved form data initial status.  The default is false.
-        saveFormDataEnabled = sharedPreferences.getBoolean("save_form_data_enabled", false);
-        mainWebView.getSettings().setSaveFormData(saveFormDataEnabled);
-
-        // Set the user agent initial status.
-        String userAgentString = sharedPreferences.getString("user_agent", "Default user agent");
-        switch (userAgentString) {
-            case "Default user agent":
-                // Do nothing.
-                break;
-
-            case "Custom user agent":
-                // Set the custom user agent on mainWebView,  The default is "PrivacyBrowser/1.0".
-                mainWebView.getSettings().setUserAgentString(sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0"));
-                break;
-
-            default:
-                // Set the selected user agent on mainWebView.  The default is "PrivacyBrowser/1.0".
-                mainWebView.getSettings().setUserAgentString(sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0"));
-                break;
-        }
-
-        // Set the initial string for JavaScript disabled search.
-        if (sharedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=").equals("Custom URL")) {
-            // Get the custom URL string.  The default is "".
-            javaScriptDisabledSearchURL = sharedPreferences.getString("javascript_disabled_search_custom_url", "");
-        } else {
-            // Use the string from javascript_disabled_search.
-            javaScriptDisabledSearchURL = sharedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=");
-        }
-
-        // Set the initial string for JavaScript enabled search.
-        if (sharedPreferences.getString("javascript_enabled_search", "https://duckduckgo.com/?q=").equals("Custom URL")) {
-            // Get the custom URL string.  The default is "".
-            javaScriptEnabledSearchURL = sharedPreferences.getString("javascript_enabled_search_custom_url", "");
-        } else {
-            // Use the string from javascript_enabled_search.
-            javaScriptEnabledSearchURL = sharedPreferences.getString("javascript_enabled_search", "https://duckduckgo.com/?q=");
-        }
-
-
-        // Set the homepage initial status.  The default value is `https://www.duckduckgo.com`.
-        homepage = sharedPreferences.getString("homepage", "https://www.duckduckgo.com");
-
-        // Set the font size initial status.  the default value is `100`.
-        String defaultFontSizeString = sharedPreferences.getString("default_font_size", "100");
-        mainWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString));
-
-        // Set the swipe to refresh initial status.  The default is `true`.
-        swipeToRefreshEnabled = sharedPreferences.getBoolean("swipe_to_refresh_enabled", true);
-        swipeToRefresh.setEnabled(swipeToRefreshEnabled);
-
-
         // 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", "");
 
         // 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", "");
 
-        // Set Do Not Track.  The default is true.
-        if (sharedPreferences.getBoolean("do_not_track", true)) {
-            customHeaders.put("DNT", "1");
-        }
+        // Initialize the default preference values the first time the program is run.
+        PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
 
 
-        // Set Orbot proxy status.  The default is `false`.
-        if (sharedPreferences.getBoolean("proxy_through_orbot", false)) {
-            OrbotProxyHelper.setProxy(privacyBrowserContext, privacyBrowserActivity, "localhost", "8118");
-        }
+        // Apply the settings from the shared preferences.
+        applySettings();
 
         // Get the intent information that started the app.
         final Intent intent = getIntent();
 
         // Get the intent information that started the app.
         final Intent intent = getIntent();
@@ -485,7 +398,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // If the favorite icon is null, load the default.
         if (favoriteIcon == null) {
             // We have to use `ContextCompat` until API >= 21.
         // If the favorite icon is null, load the default.
         if (favoriteIcon == null) {
             // We have to use `ContextCompat` until API >= 21.
-            Drawable favoriteIconDrawable = ContextCompat.getDrawable(privacyBrowserContext, R.drawable.world);
+            Drawable favoriteIconDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.world);
             BitmapDrawable favoriteIconBitmapDrawable = (BitmapDrawable) favoriteIconDrawable;
             favoriteIcon = favoriteIconBitmapDrawable.getBitmap();
         }
             BitmapDrawable favoriteIconBitmapDrawable = (BitmapDrawable) favoriteIconDrawable;
             favoriteIcon = favoriteIconBitmapDrawable.getBitmap();
         }
@@ -524,23 +437,24 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // Inflate the menu; this adds items to the action bar if it is present.
         getMenuInflater().inflate(R.menu.webview_options_menu, menu);
 
         // Inflate the menu; this adds items to the action bar if it is present.
         getMenuInflater().inflate(R.menu.webview_options_menu, menu);
 
-        // Set mainMenu so it can be used by onOptionsItemSelected.
+        // Set mainMenu so it can be used by `onOptionsItemSelected()` and `updatePrivacyIcons`.
         mainMenu = menu;
 
         mainMenu = menu;
 
-        // Set the initial status of the privacy icon.
-        updatePrivacyIcons(privacyBrowserActivity);
+        // Set the initial status of the privacy icons.  `false` does not call `invalidateOptionsMenu` as the last step.
+        updatePrivacyIcons(false);
 
         // Get handles for the menu items.
 
         // Get handles for the menu items.
+        toggleJavaScript = menu.findItem(R.id.toggleJavaScript);
         MenuItem toggleFirstPartyCookies = menu.findItem(R.id.toggleFirstPartyCookies);
         MenuItem toggleThirdPartyCookies = menu.findItem(R.id.toggleThirdPartyCookies);
         MenuItem toggleDomStorage = menu.findItem(R.id.toggleDomStorage);
         MenuItem toggleSaveFormData = menu.findItem(R.id.toggleSaveFormData);
 
         MenuItem toggleFirstPartyCookies = menu.findItem(R.id.toggleFirstPartyCookies);
         MenuItem toggleThirdPartyCookies = menu.findItem(R.id.toggleThirdPartyCookies);
         MenuItem toggleDomStorage = menu.findItem(R.id.toggleDomStorage);
         MenuItem toggleSaveFormData = menu.findItem(R.id.toggleSaveFormData);
 
-        // Set the initial status of the menu item checkboxes.
-        toggleFirstPartyCookies.setChecked(firstPartyCookiesEnabled);
-        toggleThirdPartyCookies.setChecked(thirdPartyCookiesEnabled);
-        toggleDomStorage.setChecked(domStorageEnabled);
-        toggleSaveFormData.setChecked(saveFormDataEnabled);
+        // Only display third-Party Cookies if SDK >= 21
+        toggleThirdPartyCookies.setVisible(Build.VERSION.SDK_INT >= 21);
+
+        // Get the shared preference values.  `this` references the current context.
+        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
         // Set the status of the additional app bar icons.  The default is `false`.
         if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
 
         // Set the status of the additional app bar icons.  The default is `false`.
         if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
@@ -558,27 +472,37 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
 
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
 
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
-        // Only enable Third-Party Cookies if SDK >= 21 and First-Party Cookies are enabled.
+        // Get handles for the menu items.
+        MenuItem toggleFirstPartyCookies = menu.findItem(R.id.toggleFirstPartyCookies);
         MenuItem toggleThirdPartyCookies = menu.findItem(R.id.toggleThirdPartyCookies);
         MenuItem toggleThirdPartyCookies = menu.findItem(R.id.toggleThirdPartyCookies);
-        if ((Build.VERSION.SDK_INT >= 21) && firstPartyCookiesEnabled) {
-            toggleThirdPartyCookies.setEnabled(true);
-        } else {
-            toggleThirdPartyCookies.setEnabled(false);
-        }
+        MenuItem toggleDomStorage = menu.findItem(R.id.toggleDomStorage);
+        MenuItem toggleSaveFormData = menu.findItem(R.id.toggleSaveFormData);
+        MenuItem clearCookies = menu.findItem(R.id.clearCookies);
+        MenuItem clearFormData = menu.findItem(R.id.clearFormData);
+        MenuItem refreshMenuItem = menu.findItem(R.id.refresh);
+
+        // Set the status of the menu item checkboxes.
+        toggleFirstPartyCookies.setChecked(firstPartyCookiesEnabled);
+        toggleThirdPartyCookies.setChecked(thirdPartyCookiesEnabled);
+        toggleDomStorage.setChecked(domStorageEnabled);
+        toggleSaveFormData.setChecked(saveFormDataEnabled);
+
+        // Enable third-party cookies if first-party cookies are enabled.
+        toggleThirdPartyCookies.setEnabled(firstPartyCookiesEnabled);
 
         // Enable DOM Storage if JavaScript is enabled.
 
         // Enable DOM Storage if JavaScript is enabled.
-        MenuItem toggleDomStorage = menu.findItem(R.id.toggleDomStorage);
         toggleDomStorage.setEnabled(javaScriptEnabled);
 
         // Enable Clear Cookies if there are any.
         toggleDomStorage.setEnabled(javaScriptEnabled);
 
         // Enable Clear Cookies if there are any.
-        MenuItem clearCookies = menu.findItem(R.id.clearCookies);
         clearCookies.setEnabled(cookieManager.hasCookies());
 
         // Enable Clear Form Data is there is any.
         clearCookies.setEnabled(cookieManager.hasCookies());
 
         // Enable Clear Form Data is there is any.
-        MenuItem clearFormData = menu.findItem(R.id.clearFormData);
         WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this);
         clearFormData.setEnabled(mainWebViewDatabase.hasFormData());
 
         WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this);
         clearFormData.setEnabled(mainWebViewDatabase.hasFormData());
 
+        // Only show `Refresh` if `swipeToRefresh` is disabled.
+        refreshMenuItem.setVisible(!swipeToRefreshEnabled);
+
         // Initialize font size variables.
         int fontSize = mainWebView.getSettings().getTextZoom();
         String fontSizeTitle;
         // Initialize font size variables.
         int fontSize = mainWebView.getSettings().getTextZoom();
         String fontSizeTitle;
@@ -632,10 +556,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         fontSizeMenuItem.setTitle(fontSizeTitle);
         selectedFontSizeMenuItem.setChecked(true);
 
         fontSizeMenuItem.setTitle(fontSizeTitle);
         selectedFontSizeMenuItem.setChecked(true);
 
-        // Only show `Refresh` if `swipeToRefresh` is disabled.
-        MenuItem refreshMenuItem = menu.findItem(R.id.refresh);
-        refreshMenuItem.setVisible(!swipeToRefreshEnabled);
-
         // Run all the other default commands.
         super.onPrepareOptionsMenu(menu);
 
         // Run all the other default commands.
         super.onPrepareOptionsMenu(menu);
 
@@ -660,18 +580,16 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 // Apply the new JavaScript status.
                 mainWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
 
                 // Apply the new JavaScript status.
                 mainWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
 
-                // Update the privacy icon.
-                updatePrivacyIcons(privacyBrowserActivity);
+                // Update the privacy icon.  `true` runs `invalidateOptionsMenu` as the last step.
+                updatePrivacyIcons(true);
 
                 // Display a `Snackbar`.
 
                 // Display a `Snackbar`.
-                if (javaScriptEnabled) {
+                if (javaScriptEnabled) {  // JavaScrip is enabled.
                     Snackbar.make(findViewById(R.id.mainWebView), R.string.javascript_enabled, Snackbar.LENGTH_SHORT).show();
                     Snackbar.make(findViewById(R.id.mainWebView), R.string.javascript_enabled, Snackbar.LENGTH_SHORT).show();
-                } else {
-                    if (firstPartyCookiesEnabled) {
-                        Snackbar.make(findViewById(R.id.mainWebView), R.string.javascript_disabled, Snackbar.LENGTH_SHORT).show();
-                    } else {
-                        Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
-                    }
+                } else if (firstPartyCookiesEnabled) {  // JavaScript is disabled, but first-party cookies are enabled.
+                    Snackbar.make(findViewById(R.id.mainWebView), R.string.javascript_disabled, Snackbar.LENGTH_SHORT).show();
+                } else {  // Privacy mode.
+                    Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
                 }
 
                 // Reload the WebView.
                 }
 
                 // Reload the WebView.
@@ -688,18 +606,16 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 // Apply the new cookie status.
                 cookieManager.setAcceptCookie(firstPartyCookiesEnabled);
 
                 // Apply the new cookie status.
                 cookieManager.setAcceptCookie(firstPartyCookiesEnabled);
 
-                // Update the privacy icon.
-                updatePrivacyIcons(privacyBrowserActivity);
+                // Update the privacy icon.  `true` runs `invalidateOptionsMenu` as the last step.
+                updatePrivacyIcons(true);
 
                 // Display a `Snackbar`.
 
                 // Display a `Snackbar`.
-                if (firstPartyCookiesEnabled) {
+                if (firstPartyCookiesEnabled) {  // First-party cookies are enabled.
                     Snackbar.make(findViewById(R.id.mainWebView), R.string.first_party_cookies_enabled, Snackbar.LENGTH_SHORT).show();
                     Snackbar.make(findViewById(R.id.mainWebView), R.string.first_party_cookies_enabled, Snackbar.LENGTH_SHORT).show();
-                } else {
-                    if (javaScriptEnabled) {
-                        Snackbar.make(findViewById(R.id.mainWebView), R.string.first_party_cookies_disabled, Snackbar.LENGTH_SHORT).show();
-                    } else {
-                        Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
-                    }
+                } else if (javaScriptEnabled){  // JavaScript is still enabled.
+                    Snackbar.make(findViewById(R.id.mainWebView), R.string.first_party_cookies_disabled, Snackbar.LENGTH_SHORT).show();
+                } else {  // Privacy mode.
+                    Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
                 }
 
                 // Reload the WebView.
                 }
 
                 // Reload the WebView.
@@ -739,6 +655,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 // Apply the new DOM Storage status.
                 mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
 
                 // Apply the new DOM Storage status.
                 mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
 
+                // Update the privacy icon.  `true` runs `invalidateOptionsMenu` as the last step.
+                updatePrivacyIcons(true);
+
                 // Display a `Snackbar`.
                 if (domStorageEnabled) {
                     Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show();
                 // Display a `Snackbar`.
                 if (domStorageEnabled) {
                     Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show();
@@ -767,6 +686,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                     Snackbar.make(findViewById(R.id.mainWebView), R.string.form_data_disabled, Snackbar.LENGTH_SHORT).show();
                 }
 
                     Snackbar.make(findViewById(R.id.mainWebView), R.string.form_data_disabled, Snackbar.LENGTH_SHORT).show();
                 }
 
+                // Update the privacy icon.  `true` runs `invalidateOptionsMenu` as the last step.
+                updatePrivacyIcons(true);
+
                 // Reload the WebView.
                 mainWebView.reload();
                 return true;
                 // Reload the WebView.
                 mainWebView.reload();
                 return true;
@@ -820,6 +742,14 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 mainWebView.getSettings().setTextZoom(200);
                 return true;
 
                 mainWebView.getSettings().setTextZoom(200);
                 return true;
 
+            /*
+            case R.id.find_on_page:
+                appBar.setCustomView(R.layout.find_on_page_app_bar);
+                toggleJavaScript.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+                appBar.invalidateOptionsMenu();
+                return true;
+                */
+
             case R.id.share:
                 Intent shareIntent = new Intent();
                 shareIntent.setAction(Intent.ACTION_SEND);
             case R.id.share:
                 Intent shareIntent = new Intent();
                 shareIntent.setAction(Intent.ACTION_SEND);
@@ -830,12 +760,23 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
 
             case R.id.addToHomescreen:
                 // Show the `CreateHomeScreenShortcut` `AlertDialog` and name this instance `@string/create_shortcut`.
 
             case R.id.addToHomescreen:
                 // Show the `CreateHomeScreenShortcut` `AlertDialog` and name this instance `@string/create_shortcut`.
-                DialogFragment createHomeScreenShortcutDialogFragment = new CreateHomeScreenShortcut();
-                createHomeScreenShortcutDialogFragment.show(getFragmentManager(), getResources().getString(R.string.create_shortcut));
+                AppCompatDialogFragment createHomeScreenShortcutDialogFragment = new CreateHomeScreenShortcut();
+                createHomeScreenShortcutDialogFragment.show(getSupportFragmentManager(), getResources().getString(R.string.create_shortcut));
 
                 //Everything else will be handled by `CreateHomeScreenShortcut` and the associated listener below.
                 return true;
 
 
                 //Everything else will be handled by `CreateHomeScreenShortcut` and the associated listener below.
                 return true;
 
+            case R.id.print:
+                // Get a `PrintManager` instance.
+                PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
+
+                // Convert `mainWebView` to `printDocumentAdapter`.
+                PrintDocumentAdapter printDocumentAdapter = mainWebView.createPrintDocumentAdapter();
+
+                // Print the document.  The print attributes are `null`.
+                printManager.print(getResources().getString(R.string.privacy_browser_web_page), printDocumentAdapter, null);
+                return true;
+
             case R.id.refresh:
                 mainWebView.reload();
                 return true;
             case R.id.refresh:
                 mainWebView.reload();
                 return true;
@@ -846,10 +787,10 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         }
     }
 
         }
     }
 
-    @Override
     // removeAllCookies is deprecated, but it is required for API < 21.
     @SuppressWarnings("deprecation")
     // removeAllCookies is deprecated, but it is required for API < 21.
     @SuppressWarnings("deprecation")
-    public boolean onNavigationItemSelected(MenuItem menuItem) {
+    @Override
+    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
         int menuItemId = menuItem.getItemId();
 
         switch (menuItemId) {
         int menuItemId = menuItem.getItemId();
 
         switch (menuItemId) {
@@ -926,7 +867,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 mainWebView.clearHistory();
 
                 // Clear any SSL certificate preferences.
                 mainWebView.clearHistory();
 
                 // Clear any SSL certificate preferences.
-                MainWebViewActivity.mainWebView.clearSslPreferences();
+                mainWebView.clearSslPreferences();
 
                 // Clear `formattedUrlString`.
                 formattedUrlString = null;
 
                 // Clear `formattedUrlString`.
                 formattedUrlString = null;
@@ -967,17 +908,17 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         super.onConfigurationChanged(newConfig);
 
         // Reload the ad if this is the free flavor.
         super.onConfigurationChanged(newConfig);
 
         // Reload the ad if this is the free flavor.
-        BannerAd.reloadAfterRotate(adView, privacyBrowserContext, getString(R.string.ad_id));
+        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);
 
         // `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
 
         // 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);
 
         // `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
-        invalidateOptionsMenu();
+        // ActivityCompat.invalidateOptionsMenu(this);
     }
 
     @Override
     }
 
     @Override
-    public void onCreateHomeScreenShortcut(DialogFragment dialogFragment) {
+    public void onCreateHomeScreenShortcut(AppCompatDialogFragment dialogFragment) {
         // Get shortcutNameEditText from the alert dialog.
         EditText shortcutNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.shortcut_name_edittext);
 
         // Get shortcutNameEditText from the alert dialog.
         EditText shortcutNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.shortcut_name_edittext);
 
@@ -996,7 +937,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     }
 
     @Override
     }
 
     @Override
-    public void onDownloadFile(DialogFragment dialogFragment, String downloadUrl) {
+    public void onDownloadFile(AppCompatDialogFragment dialogFragment, String downloadUrl) {
         DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
         DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(downloadUrl));
 
         DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
         DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(downloadUrl));
 
@@ -1004,9 +945,12 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         EditText downloadFileNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.download_file_name);
         String fileName = downloadFileNameEditText.getText().toString();
 
         EditText downloadFileNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.download_file_name);
         String fileName = downloadFileNameEditText.getText().toString();
 
-        // Set the download save in the the `DIRECTORY_DOWNLOADS`using `fileName`.
         // Once we have `WRITE_EXTERNAL_STORAGE` permissions we can use `setDestinationInExternalPublicDir`.
         // Once we have `WRITE_EXTERNAL_STORAGE` permissions we can use `setDestinationInExternalPublicDir`.
-        downloadRequest.setDestinationInExternalFilesDir(this, "/", fileName);
+        if (Build.VERSION.SDK_INT >= 23) { // If API >= 23, set the download save in the the `DIRECTORY_DOWNLOADS` using `fileName`.
+            downloadRequest.setDestinationInExternalFilesDir(this, "/", fileName);
+        } else { // Only set the title using `fileName`.
+            downloadRequest.setTitle(fileName);
+        }
 
         // Allow `MediaScanner` to index the download if it is a media file.
         downloadRequest.allowScanningByMediaScanner();
 
         // Allow `MediaScanner` to index the download if it is a media file.
         downloadRequest.allowScanningByMediaScanner();
@@ -1047,7 +991,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             drawerLayout.closeDrawer(GravityCompat.START);
         } else {
             // Load the previous URL if available.
             drawerLayout.closeDrawer(GravityCompat.START);
         } else {
             // Load the previous URL if available.
-            assert mainWebView != null; //This assert removes the incorrect warning in Android Studio on the following line that mainWebView might be null.
             if (mainWebView.canGoBack()) {
                 mainWebView.goBack();
             } else {
             if (mainWebView.canGoBack()) {
                 mainWebView.goBack();
             } else {
@@ -1073,6 +1016,18 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         BannerAd.resumeAd(adView);
     }
 
         BannerAd.resumeAd(adView);
     }
 
+    @Override
+    public void onRestart() {
+        super.onRestart();
+
+        // Apply the settings from shared preferences, which might have been changed in `SettingsActivity`.
+        applySettings();
+
+        // Update the privacy icon.  `true` runs `invalidateOptionsMenu` as the last step.
+        updatePrivacyIcons(true);
+
+    }
+
     private void loadUrlFromTextBox() throws UnsupportedEncodingException {
         // Get the text from urlTextBox and convert it to a string.  trim() removes white spaces from the beginning and end of the string.
         String unformattedUrlString = urlTextBox.getText().toString().trim();
     private void loadUrlFromTextBox() throws UnsupportedEncodingException {
         // Get the text from urlTextBox and convert it to a string.  trim() removes white spaces from the beginning and end of the string.
         String unformattedUrlString = urlTextBox.getText().toString().trim();
@@ -1107,8 +1062,8 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             // Sanitize the search input and convert it to a DuckDuckGo search.
             final String encodedUrlString = URLEncoder.encode(unformattedUrlString, "UTF-8");
 
             // Sanitize the search input and convert it to a DuckDuckGo search.
             final String encodedUrlString = URLEncoder.encode(unformattedUrlString, "UTF-8");
 
-            // Use the correct search URL based on javaScriptEnabled.
-            if (javaScriptEnabled) {
+            // Use the correct search URL.
+            if (javaScriptEnabled) {  // JavaScript is enabled.
                 formattedUrlString = javaScriptEnabledSearchURL + encodedUrlString;
             } else { // JavaScript is disabled.
                 formattedUrlString = javaScriptDisabledSearchURL + encodedUrlString;
                 formattedUrlString = javaScriptEnabledSearchURL + encodedUrlString;
             } else { // JavaScript is disabled.
                 formattedUrlString = javaScriptDisabledSearchURL + encodedUrlString;
@@ -1122,7 +1077,98 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
     }
 
         inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
     }
 
-    public static void updatePrivacyIcons(Activity activity) {
+    private void applySettings() {
+        // Get the shared preference values.  `this` references the current context.
+        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+
+        // Store the values from `sharedPreferences` in variables.
+        String userAgentString = sharedPreferences.getString("user_agent", "Default user agent");
+        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", "");
+        String javaScriptEnabledSearchString = sharedPreferences.getString("javascript_enabled_search", "https://duckduckgo.com/?q=");
+        String javaScriptEnabledCustomSearchString = sharedPreferences.getString("javascript_enabled_search_custom_url", "");
+        String homepageString = sharedPreferences.getString("homepage", "https://www.duckduckgo.com");
+        String defaultFontSizeString = sharedPreferences.getString("default_font_size", "100");
+        swipeToRefreshEnabled = sharedPreferences.getBoolean("swipe_to_refresh_enabled", false);
+        boolean doNotTrackEnabled = sharedPreferences.getBoolean("do_not_track", true);
+        boolean proxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
+
+        // 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.
+            // Get the values from `sharedPreferences`.
+            javaScriptEnabled = sharedPreferences.getBoolean("javascript_enabled", false);
+            firstPartyCookiesEnabled = sharedPreferences.getBoolean("first_party_cookies_enabled", false);
+            thirdPartyCookiesEnabled = sharedPreferences.getBoolean("third_party_cookies_enabled", false);
+            domStorageEnabled = sharedPreferences.getBoolean("dom_storage_enabled", false);
+            saveFormDataEnabled = sharedPreferences.getBoolean("save_form_data_enabled", false);
+
+            // Apply the default settings.
+            mainWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
+            cookieManager.setAcceptCookie(firstPartyCookiesEnabled);
+            mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
+            mainWebView.getSettings().setSaveFormData(saveFormDataEnabled);
+            mainWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString));
+
+            // Set third-party cookies status if API >= 21.
+            if (Build.VERSION.SDK_INT >= 21) {
+                cookieManager.setAcceptThirdPartyCookies(mainWebView, thirdPartyCookiesEnabled);
+            }
+        }
+
+        // Apply the other settings from `sharedPreferences`.
+        homepage = homepageString;
+        swipeRefreshLayout.setEnabled(swipeToRefreshEnabled);
+
+        // Set the user agent initial status.
+        switch (userAgentString) {
+            case "Default user agent":
+                // Set the user agent to `""`, which uses the default value.
+                mainWebView.getSettings().setUserAgentString("");
+                break;
+
+            case "Custom user agent":
+                // Set the custom user agent.
+                mainWebView.getSettings().setUserAgentString(customUserAgentString);
+                break;
+
+            default:
+                // Use the selected user agent.
+                mainWebView.getSettings().setUserAgentString(userAgentString);
+                break;
+        }
+
+        // Set JavaScript disabled search.
+        if (javaScriptDisabledSearchString.equals("Custom URL")) {  // Get the custom URL string.
+            javaScriptDisabledSearchURL = javaScriptDisabledCustomSearchString;
+        } else {  // Use the string from the pre-built list.
+            javaScriptDisabledSearchURL = javaScriptDisabledSearchString;
+        }
+
+        // Set JavaScript enabled search.
+        if (javaScriptEnabledSearchString.equals("Custom URL")) {  // Get the custom URL string.
+            javaScriptEnabledSearchURL = javaScriptEnabledCustomSearchString;
+        } else {  // Use the string from the pre-built list.
+            javaScriptEnabledSearchURL = javaScriptEnabledSearchString;
+        }
+
+        // Set Do Not Track status.
+        if (doNotTrackEnabled) {
+            customHeaders.put("DNT", "1");
+        } else {
+            customHeaders.remove("DNT");
+        }
+
+        // Set Orbot proxy status.
+        if (proxyThroughOrbot) {
+            // Set the proxy.  `this` refers to the current activity where an `AlertDialog` might be displayed.
+            OrbotProxyHelper.setProxy(getApplicationContext(), this, "localhost", "8118");
+        } else {  // Reset the proxy to default.  The host is `""` and the port is `"0"`.
+            OrbotProxyHelper.setProxy(getApplicationContext(), this, "", "0");
+        }
+    }
+
+    private void updatePrivacyIcons(boolean runInvalidateOptionsMenu) {
         // Get handles for the icons.
         MenuItem privacyIcon = mainMenu.findItem(R.id.toggleJavaScript);
         MenuItem firstPartyCookiesIcon = mainMenu.findItem(R.id.toggleFirstPartyCookies);
         // Get handles for the icons.
         MenuItem privacyIcon = mainMenu.findItem(R.id.toggleJavaScript);
         MenuItem firstPartyCookiesIcon = mainMenu.findItem(R.id.toggleFirstPartyCookies);
@@ -1146,9 +1192,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         }
 
         // Update `domStorageIcon`.
         }
 
         // Update `domStorageIcon`.
-        if (javaScriptEnabled && domStorageEnabled) {  // Both JavaScript and DOM storage is enabled.
+        if (javaScriptEnabled && domStorageEnabled) {  // Both JavaScript and DOM storage are enabled.
             domStorageIcon.setIcon(R.drawable.dom_storage_enabled);
             domStorageIcon.setIcon(R.drawable.dom_storage_enabled);
-        } else if (javaScriptEnabled){  // JavaScript is enabled but DOM storage is disabled.
+        } else if (javaScriptEnabled) {  // JavaScript is enabled but DOM storage is disabled.
             domStorageIcon.setIcon(R.drawable.dom_storage_disabled);
         } else {  // JavaScript is disabled, so DOM storage is ghosted.
             domStorageIcon.setIcon(R.drawable.dom_storage_ghosted);
             domStorageIcon.setIcon(R.drawable.dom_storage_disabled);
         } else {  // JavaScript is disabled, so DOM storage is ghosted.
             domStorageIcon.setIcon(R.drawable.dom_storage_ghosted);
@@ -1161,7 +1207,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             formDataIcon.setIcon(R.drawable.form_data_disabled);
         }
 
             formDataIcon.setIcon(R.drawable.form_data_disabled);
         }
 
-        // `invalidateOptionsMenu` calls `onPrepareOptionsMenu()` and redraws the icons in the `AppBar`.
-        ActivityCompat.invalidateOptionsMenu(activity);
+        // `invalidateOptionsMenu` calls `onPrepareOptionsMenu()` and redraws the icons in the `AppBar`.  `this` references the current activity.
+        if (runInvalidateOptionsMenu) {
+            ActivityCompat.invalidateOptionsMenu(this);
+        }
     }
 }
     }
 }