Mark which strings cannot be translated because they are used in code.
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / MainWebViewActivity.java
index 61b208a84b589b13e7142d7911050aeaa9d73aa8..2edbfdfeea2efd2f6eb21176b37f4bb986f311c9 100644 (file)
 package com.stoutner.privacybrowser;
 
 import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.DownloadManager;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
+import android.support.design.widget.NavigationView;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.DialogFragment;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
 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.AppCompatDialogFragment;
 import android.support.v7.widget.Toolbar;
@@ -53,7 +57,6 @@ import android.widget.EditText;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.ProgressBar;
-import android.widget.Toast;
 
 import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
@@ -61,32 +64,41 @@ import java.net.URL;
 import java.net.URLEncoder;
 
 // 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 CreateHomeScreenShortcut.CreateHomeScreenSchortcutListener {
+public class MainWebViewActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, CreateHomeScreenShortcut.CreateHomeScreenSchortcutListener {
     // favoriteIcon is public static so it can be accessed from CreateHomeScreenShortcut.
     public static Bitmap favoriteIcon;
-    // mainWebView is public static so it can be accessed from AboutDialog.  It is also used in onCreate(), onOptionsItemSelected(), and loadUrlFromTextBox().
+    // mainWebView is public static so it can be accessed from AboutDialog and SettingsFragment.  It is also used in onCreate(), onOptionsItemSelected(), onNavigationItemSelected(), and loadUrlFromTextBox().
     public static WebView mainWebView;
 
-    // mainMenu is used in onCreateOptionsMenu() and onOptionsItemSelected().
-    private Menu mainMenu;
+    // mainMenu is public static so it can be accessed from SettingsFragment.  It is also used in onCreateOptionsMenu() and onOptionsItemSelected().
+    public static Menu mainMenu;
+    // cookieManager is public static so it can be accessed from SettingsFragment.  It is also used in onCreate(), onOptionsItemSelected(), and onNavigationItemSelected().
+    public static CookieManager cookieManager;
+    // 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;
+    // 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;
+    // thirdPartyCookiesEnabled is uesd in onCreate(), onCreateOptionsMenu(), onPrepareOptionsMenu(), and onOptionsItemSelected().
+    public static boolean thirdPartyCookiesEnabled;
+    // domStorageEnabled is public static so it can be accessed from SettingsFragment.  It is also used in onCreate(), onCreateOptionsMenu(), and onOptionsItemSelected().
+    public static boolean domStorageEnabled;
+    // javaScriptDisabledSearchURL is public static so it can be accessed from SettingsFragment.  It is also used in onCreate() and loadURLFromTextBox().
+    public static String javaScriptDisabledSearchURL;
+    // javaScriptEnabledSearchURL is public static so it can be accessed from SettingsFragment.  It is also used in onCreate() and loadURLFromTextBox().
+    public static String javaScriptEnabledSearchURL;
+    // homepage is public static so it can be accessed from  SettingsFragment.  It is also used in onCreate() and onOptionsItemSelected().
+    public static String homepage;
+    // swipeToRefresh is public static so it can be accessed from SettingsFragment.  It is also used in onCreate().
+    public static SwipeRefreshLayout swipeToRefresh;
+    // swipeToRefreshEnabled is public static so it can be accessed from SettingsFragment.  It is also used in onCreate().
+    public static boolean swipeToRefreshEnabled;
+
+    // drawerToggle is used in onCreate(), onPostCreate(), onConfigurationChanged(), onNewIntent(), and onNavigationItemSelected().
+    private ActionBarDrawerToggle drawerToggle;
+    // drawerLayout is used in onCreate(), onNewIntent(), and onBackPressed().
+    private DrawerLayout drawerLayout;
     // formattedUrlString is used in onCreate(), onOptionsItemSelected(), onCreateHomeScreenShortcutCreate(), and loadUrlFromTextBox().
     private String formattedUrlString;
-    // homepage is used in onCreate() and onOptionsItemSelected().
-    private String homepage;
-    // javaScriptEnabled is used in onCreate(), onCreateOptionsMenu(), onOptionsItemSelected(), and loadUrlFromTextBox().
-    private boolean javaScriptEnabled;
-    // domStorageEnabled is used in onCreate(), onCreateOptionsMenu(), and onOptionsItemSelected().
-    private boolean domStorageEnabled;
-
-    /* saveFormDataEnabled does nothing until database storage is implemented.
-    // saveFormDataEnabled is used in onCreate(), onCreateOptionsMenu(), and onOptionsItemSelected().
-    private boolean saveFormDataEnabled;
-    */
-
-    // cookieManager is used in onCreate() and onOptionsItemSelected().
-    private CookieManager cookieManager;
-    // cookiesEnabled is used in onCreate(), onCreateOptionsMenu(), and onOptionsItemSelected().
-    private boolean cookiesEnabled;
 
     // urlTextBox is used in onCreate(), onOptionsItemSelected(), and loadUrlFromTextBox().
     private EditText urlTextBox;
@@ -96,7 +108,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
     @SuppressLint("SetJavaScriptEnabled")
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_webview);
+        setContentView(R.layout.coordinator_layout);
 
         // 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);
@@ -111,7 +123,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
         final View adView = findViewById(R.id.adView);
 
         // Implement swipe to refresh
-        final SwipeRefreshLayout swipeToRefresh = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
+        swipeToRefresh = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
         swipeToRefresh.setColorSchemeResources(R.color.blue);
         swipeToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
             @Override
@@ -149,6 +161,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
             });
         }
 
+        // Create the navigation drawer.
+        drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
+        // The DrawerTitle identifies the drawer 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);
+        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.
             @Override
@@ -167,7 +191,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
             @Override
             public void onPageFinished(WebView view, String url) {
                 formattedUrlString = url;
-                urlTextBox.setText(formattedUrlString);
+
+                // Only update urlTextBox if the user is not typing in it.
+                if (!urlTextBox.hasFocus()) {
+                    urlTextBox.setText(formattedUrlString);
+                }
             }
         });
 
@@ -226,9 +254,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
                 */
 
                 // Set the one flag supported by API >= 14.
-                if (Build.VERSION.SDK_INT >= 14) {
-                    view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
-                }
+                view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
 
                 // Set the two flags that are supported by API >= 16.
                 if (Build.VERSION.SDK_INT >= 16) {
@@ -270,11 +296,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
                 // Add the URL as the description for the download.
                 requestUri.setDescription(url);
 
-                // Show the download notification after the download is completed if the API is 11 or greater.
-                if (Build.VERSION.SDK_INT >= 11) {
-                    requestUri.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
-                }
+                // Show the download notification after the download is completed.
+                requestUri.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
 
+                // Initiate the download and display a Snackbar.
                 downloadManager.enqueue(requestUri);
                 Snackbar.make(findViewById(R.id.mainWebView), R.string.download_started, Snackbar.LENGTH_SHORT).show();
             }
@@ -283,10 +308,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
         // Allow pinch to zoom.
         mainWebView.getSettings().setBuiltInZoomControls(true);
 
-        // Hide zoom controls if the API is 11 or greater.
-        if (Build.VERSION.SDK_INT >= 11) {
-            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);
@@ -294,28 +318,72 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
         // Get the shared preference values.
         SharedPreferences savedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
-        // Set JavaScript initial status.
+        // Set JavaScript initial status.  The default value is false.
         javaScriptEnabled = savedPreferences.getBoolean("javascript_enabled", false);
         mainWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
 
-        // Set DOM storage initial status.
+        // Initialize cookieManager.
+        cookieManager = CookieManager.getInstance();
+
+        // Set cookies initial status.  The default value is false.
+        firstPartyCookiesEnabled = savedPreferences.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 = savedPreferences.getBoolean("third_party_cookies_enabled", false);
+            cookieManager.setAcceptThirdPartyCookies(mainWebView, thirdPartyCookiesEnabled);
+        }
+
+        // Set DOM storage initial status.  The default value is false.
         domStorageEnabled = savedPreferences.getBoolean("dom_storage_enabled", false);
         mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
 
-        /* Save Form Data does nothing until database storage is implemented.
-        // Set Save Form Data initial status.
-        saveFormDataEnabled = true;
-        mainWebView.getSettings().setSaveFormData(saveFormDataEnabled);
-        */
+        // Set the user agent initial status.
+        String userAgentString = savedPreferences.getString("user_agent", "Default user agent");
+        switch (userAgentString) {
+            case "Default user agent":
+                // Do nothing.
+                break;
 
-        // Set cookies initial status.
-        cookiesEnabled = savedPreferences.getBoolean("cookies_enabled", false);
-        cookieManager = CookieManager.getInstance();
-        cookieManager.setAcceptCookie(cookiesEnabled);
+            case "Custom user agent":
+                // Set the custom user agent on mainWebView,  The default is "PrivacyBrowser/1.0".
+                mainWebView.getSettings().setUserAgentString(savedPreferences.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(savedPreferences.getString("user_agent", "PrivacyBrowser/1.0"));
+                break;
+        }
+
+        // Set the initial string for JavaScript disabled search.
+        if (savedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=").equals("Custom URL")) {
+            // Get the custom URL string.  The default is "".
+            javaScriptDisabledSearchURL = savedPreferences.getString("javascript_disabled_search_custom_url", "");
+        } else {
+            // Use the string from javascript_disabled_search.
+            javaScriptDisabledSearchURL = savedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=");
+        }
+
+        // Set the initial string for JavaScript enabled search.
+        if (savedPreferences.getString("javascript_enabled_search", "https://duckduckgo.com/?q=").equals("Custom URL")) {
+            // Get the custom URL string.  The default is "".
+            javaScriptEnabledSearchURL = savedPreferences.getString("javascript_enabled_search_custom_url", "");
+        } else {
+            // Use the string from javascript_enabled_search.
+            javaScriptEnabledSearchURL = savedPreferences.getString("javascript_enabled_search", "https://duckduckgo.com/?q=");
+        }
 
-        // Set homepage initial status.
+
+        // Set homepage initial status.  The default value is "https://www.duckduckgo.com".
         homepage = savedPreferences.getString("homepage", "https://www.duckduckgo.com");
 
+        // Set swipe to refresh initial status.  The default is true.
+        swipeToRefreshEnabled = savedPreferences.getBoolean("swipe_to_refresh_enabled", true);
+        swipeToRefresh.setEnabled(swipeToRefreshEnabled);
+
+
         // Get the intent information that started the app.
         final Intent intent = getIntent();
 
@@ -348,6 +416,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
             formattedUrlString = intentUriData.toString();
         }
 
+        // Close the navigation drawer if it is open.
+        if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
+            drawerLayout.closeDrawer(GravityCompat.START);
+        }
+
         // Load the website.
         mainWebView.loadUrl(formattedUrlString);
 
@@ -358,24 +431,25 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         // Inflate the menu; this adds items to the action bar if it is present.
-        getMenuInflater().inflate(R.menu.menu_webview, menu);
+        getMenuInflater().inflate(R.menu.menu_options, menu);
 
         // Set mainMenu so it can be used by onOptionsItemSelected.
         mainMenu = menu;
 
         // Get MenuItems for checkable menu items.
         MenuItem 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);
         /* toggleSaveFormData does nothing until database storage is implemented.
         MenuItem toggleSaveFormData = menu.findItem(R.id.toggleSaveFormData);
         */
-        MenuItem toggleCookies = menu.findItem(R.id.toggleCookies);
 
         // Set the initial icon for toggleJavaScript
         if (javaScriptEnabled) {
             toggleJavaScript.setIcon(R.drawable.javascript_enabled);
         } else {
-            if (domStorageEnabled || cookiesEnabled) {
+            if (domStorageEnabled || firstPartyCookiesEnabled) {
                 toggleJavaScript.setIcon(R.drawable.warning);
             } else {
                 toggleJavaScript.setIcon(R.drawable.privacy_mode);
@@ -383,29 +457,30 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
         }
 
         // Set the initial status of the menu item checkboxes.
+        toggleFirstPartyCookies.setChecked(firstPartyCookiesEnabled);
+        toggleThirdPartyCookies.setChecked(thirdPartyCookiesEnabled);
         toggleDomStorage.setChecked(domStorageEnabled);
         /* toggleSaveFormData does nothing until database storage is implemented.
         toggleSaveFormData.setChecked(saveFormDataEnabled);
         */
-        toggleCookies.setChecked(cookiesEnabled);
 
         return true;
     }
 
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
+        // Only enable Third-Party Cookies if SDK >= 21 and First-Party Cookies are enabled.
+        MenuItem toggleThirdPartyCookies = menu.findItem(R.id.toggleThirdPartyCookies);
+        if ((Build.VERSION.SDK_INT >= 21) && firstPartyCookiesEnabled) {
+            toggleThirdPartyCookies.setEnabled(true);
+        } else {
+            toggleThirdPartyCookies.setEnabled(false);
+        }
+
         // Enable Clear Cookies if there are any.
         MenuItem clearCookies = menu.findItem(R.id.clearCookies);
         clearCookies.setEnabled(cookieManager.hasCookies());
 
-        // Enable Back if canGoBack().
-        MenuItem back = menu.findItem(R.id.back);
-        back.setEnabled(mainWebView.canGoBack());
-
-        // Enable forward if canGoForward().
-        MenuItem forward = menu.findItem(R.id.forward);
-        forward.setEnabled(mainWebView.canGoForward());
-
         // Run all the other default commands.
         super.onPrepareOptionsMenu(menu);
 
@@ -414,8 +489,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
     }
 
     @Override
-    // @TargetApi(11) turns off the errors regarding copy and paste, which are removed from view in menu_webview.xml for lower version of Android.
-    @TargetApi(11)
     // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.
     @SuppressLint("SetJavaScriptEnabled")
     // removeAllCookies is deprecated, but it is required for API < 21.
@@ -435,17 +508,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
                     mainWebView.reload();
 
                     // Update the toggleJavaScript icon and display a snackbar.
-                    if (domStorageEnabled || cookiesEnabled) {
+                    if (domStorageEnabled || firstPartyCookiesEnabled) {
                         menuItem.setIcon(R.drawable.warning);
-                        if (domStorageEnabled && cookiesEnabled) {
-                            Snackbar.make(findViewById(R.id.mainWebView), R.string.both_still_enabled, Snackbar.LENGTH_SHORT).show();
-                        } else {
-                            if (domStorageEnabled) {
-                                Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_still_enabled, Snackbar.LENGTH_SHORT).show();
-                            } else {
-                                Snackbar.make(findViewById(R.id.mainWebView), R.string.cookies_still_enabled, Snackbar.LENGTH_SHORT).show();
-                            }
-                        }
+                        Snackbar.make(findViewById(R.id.mainWebView), R.string.javascript_disabled, Snackbar.LENGTH_SHORT).show();
                     } else {
                         menuItem.setIcon(R.drawable.privacy_mode);
                         Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
@@ -459,75 +524,83 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
                 }
                 return true;
 
-            case R.id.toggleDomStorage:
-                if (domStorageEnabled) {
-                    domStorageEnabled = false;
+            case R.id.toggleFirstPartyCookies:
+                if (firstPartyCookiesEnabled) {
+                    firstPartyCookiesEnabled = false;
                     menuItem.setChecked(false);
-                    mainWebView.getSettings().setDomStorageEnabled(false);
+                    cookieManager.setAcceptCookie(false);
                     mainWebView.reload();
 
-                    // Update the toggleJavaScript icon and display a snackbar if appropriate.
-                    if (!javaScriptEnabled && !cookiesEnabled) {
-                        toggleJavaScript.setIcon(R.drawable.privacy_mode);
-                        Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
-                    } else {
-                        if (cookiesEnabled) {
+                    // Update the toggleJavaScript icon if appropriate and display a snackbar.
+                    if (!javaScriptEnabled) {
+                        if (domStorageEnabled) {
                             toggleJavaScript.setIcon(R.drawable.warning);
-                            Snackbar.make(findViewById(R.id.mainWebView), R.string.cookies_still_enabled, Snackbar.LENGTH_SHORT).show();
-                        } // Else Do nothing because JavaScript is enabled.
+                            Snackbar.make(findViewById(R.id.mainWebView), R.string.first_party_cookies_disabled, Snackbar.LENGTH_SHORT).show();
+                        } else {
+                            toggleJavaScript.setIcon(R.drawable.privacy_mode);
+                            Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
+                        }
+                    } else {
+                        Snackbar.make(findViewById(R.id.mainWebView), R.string.first_party_cookies_disabled, Snackbar.LENGTH_SHORT).show();
                     }
                 } else {
-                    domStorageEnabled = true;
+                    firstPartyCookiesEnabled = true;
                     menuItem.setChecked(true);
-                    mainWebView.getSettings().setDomStorageEnabled(true);
+                    cookieManager.setAcceptCookie(true);
                     mainWebView.reload();
 
                     // Update the toggleJavaScript icon if appropriate.
                     if (!javaScriptEnabled) {
                         toggleJavaScript.setIcon(R.drawable.warning);
-                    } // Else Do nothing because JavaScript is enabled.
+                    } // Else do nothing because JavaScript is enabled.
 
-                    Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show();
+                    Snackbar.make(findViewById(R.id.mainWebView), R.string.first_party_cookies_enabled, Snackbar.LENGTH_SHORT).show();
                 }
                 return true;
 
-            /* toggleSaveFormData does nothing until database storage is implemented.
-            case R.id.toggleSaveFormData:
-                if (saveFormDataEnabled) {
-                    saveFormDataEnabled = false;
-                    menuItem.setChecked(false);
-                    mainWebView.getSettings().setSaveFormData(false);
-                    mainWebView.reload();
-                } else {
-                    saveFormDataEnabled = true;
-                    menuItem.setChecked(true);
-                    mainWebView.getSettings().setSaveFormData(true);
-                    mainWebView.reload();
-                }
+            case R.id.toggleThirdPartyCookies:
+                if (Build.VERSION.SDK_INT >= 21) {
+                    if (thirdPartyCookiesEnabled) {
+                        thirdPartyCookiesEnabled = false;
+                        menuItem.setChecked(false);
+                        cookieManager.setAcceptThirdPartyCookies(mainWebView, false);
+                        mainWebView.reload();
+
+                        Snackbar.make(findViewById(R.id.mainWebView), R.string.third_party_cookies_disabled, Snackbar.LENGTH_SHORT).show();
+                    } else {
+                        thirdPartyCookiesEnabled = true;
+                        menuItem.setChecked(true);
+                        cookieManager.setAcceptThirdPartyCookies(mainWebView, true);
+                        mainWebView.reload();
+
+                        Snackbar.make(findViewById(R.id.mainWebView), R.string.third_party_cookies_enabled, Snackbar.LENGTH_SHORT).show();
+                    }
+                } // Else do nothing because SDK < 21.
                 return true;
-            */
 
-            case R.id.toggleCookies:
-                if (cookiesEnabled) {
-                    cookiesEnabled = false;
+            case R.id.toggleDomStorage:
+                if (domStorageEnabled) {
+                    domStorageEnabled = false;
                     menuItem.setChecked(false);
-                    cookieManager.setAcceptCookie(false);
+                    mainWebView.getSettings().setDomStorageEnabled(false);
                     mainWebView.reload();
 
-                    // Update the toggleJavaScript icon and display a snackbar if appropriate.
-                    if (!javaScriptEnabled && !domStorageEnabled) {
-                        toggleJavaScript.setIcon(R.drawable.privacy_mode);
-                        Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
-                    } else {
-                        if (domStorageEnabled) {
+                    // Update the toggleJavaScript icon if appropriate and display a snackbar.
+                    if (!javaScriptEnabled) {
+                        if (firstPartyCookiesEnabled) {
                             toggleJavaScript.setIcon(R.drawable.warning);
-                            Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show();
-                        } // Else Do nothing because JavaScript is enabled.
+                            Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_disabled, Snackbar.LENGTH_SHORT).show();
+                        } else {
+                            toggleJavaScript.setIcon(R.drawable.privacy_mode);
+                            Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
+                        }
+                    }else {
+                        Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_disabled, Snackbar.LENGTH_SHORT).show();
                     }
                 } else {
-                    cookiesEnabled = true;
+                    domStorageEnabled = true;
                     menuItem.setChecked(true);
-                    cookieManager.setAcceptCookie(true);
+                    mainWebView.getSettings().setDomStorageEnabled(true);
                     mainWebView.reload();
 
                     // Update the toggleJavaScript icon if appropriate.
@@ -535,16 +608,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
                         toggleJavaScript.setIcon(R.drawable.warning);
                     } // Else Do nothing because JavaScript is enabled.
 
-                    Snackbar.make(findViewById(R.id.mainWebView), R.string.cookies_enabled, Snackbar.LENGTH_SHORT).show();
+                    Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show();
                 }
                 return true;
 
-            case R.id.clearDomStorage:
-                WebStorage webStorage = WebStorage.getInstance();
-                webStorage.deleteAllData();
-                Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_deleted, Snackbar.LENGTH_SHORT).show();
-                return true;
-
             case R.id.clearCookies:
                 if (Build.VERSION.SDK_INT < 21) {
                     cookieManager.removeAllCookie();
@@ -554,6 +621,20 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
                 Snackbar.make(findViewById(R.id.mainWebView), R.string.cookies_deleted, Snackbar.LENGTH_SHORT).show();
                 return true;
 
+            case R.id.clearDomStorage:
+                WebStorage webStorage = WebStorage.getInstance();
+                webStorage.deleteAllData();
+                Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_deleted, Snackbar.LENGTH_SHORT).show();
+                return true;
+
+            case R.id.share:
+                Intent shareIntent = new Intent();
+                shareIntent.setAction(Intent.ACTION_SEND);
+                shareIntent.putExtra(Intent.EXTRA_TEXT, urlTextBox.getText().toString());
+                shareIntent.setType("text/plain");
+                startActivity(Intent.createChooser(shareIntent, "Share URL"));
+                return true;
+
             case R.id.addToHomescreen:
                 // Show the CreateHomeScreenShortcut AlertDialog and name this instance createShortcut.
                 AppCompatDialogFragment shortcutDialog = new CreateHomeScreenShortcut();
@@ -562,47 +643,60 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
                 //Everything else will be handled by CreateHomeScreenShortcut and the associated listeners below.
                 return true;
 
-            case R.id.downloads:
-                // Launch the system Download Manager.
-                Intent downloadManagerIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
+            case R.id.refresh:
+                mainWebView.reload();
+                return true;
 
-                // Launch as a new task so that Download Manager and Privacy Browser show as separate windows in the recent tasks list.
-                downloadManagerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            default:
+                // Don't consume the event.
+                return super.onOptionsItemSelected(menuItem);
+        }
+    }
 
-                startActivity(downloadManagerIntent);
-                return true;
+    @Override
+    // removeAllCookies is deprecated, but it is required for API < 21.
+    @SuppressWarnings("deprecation")
+    public boolean onNavigationItemSelected(MenuItem menuItem) {
+        int menuItemId = menuItem.getItemId();
 
+        switch (menuItemId) {
             case R.id.home:
                 mainWebView.loadUrl(homepage);
-                return true;
+                break;
 
             case R.id.back:
-                mainWebView.goBack();
-                return true;
+                if (mainWebView.canGoBack()) {
+                    mainWebView.goBack();
+                }
+                break;
 
             case R.id.forward:
-                mainWebView.goForward();
-                return true;
+                if (mainWebView.canGoForward()) {
+                    mainWebView.goForward();
+                }
+                break;
 
-            case R.id.share:
-                Intent shareIntent = new Intent();
-                shareIntent.setAction(Intent.ACTION_SEND);
-                shareIntent.putExtra(Intent.EXTRA_TEXT, urlTextBox.getText().toString());
-                shareIntent.setType("text/plain");
-                startActivity(Intent.createChooser(shareIntent, "Share URL"));
-                return true;
+            case R.id.downloads:
+                // Launch the system Download Manager.
+                Intent downloadManagerIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
+
+                // Launch as a new task so that Download Manager and Privacy Browser show as separate windows in the recent tasks list.
+                downloadManagerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+                startActivity(downloadManagerIntent);
+                break;
 
             case R.id.settings:
-                // Launch SettingsActivity.
+                // Launch PreferenceFragment.
                 Intent intent = new Intent(this, SettingsActivity.class);
                 startActivity(intent);
-                return true;
+                break;
 
             case R.id.about:
                 // Show the AboutDialog AlertDialog and name this instance aboutDialog.
                 AppCompatDialogFragment aboutDialog = new AboutDialog();
                 aboutDialog.show(getSupportFragmentManager(), "aboutDialog");
-                return true;
+                break;
 
             case R.id.clearAndExit:
                 // Clear DOM storage.
@@ -625,11 +719,31 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
                 } else {
                     finish();
                 }
-                return true;
+                break;
 
             default:
-                return super.onOptionsItemSelected(menuItem);
+                break;
         }
+
+        // Close the navigation drawer.
+        drawerLayout.closeDrawer(GravityCompat.START);
+        return true;
+    }
+
+    @Override
+    public void onPostCreate(Bundle savedInstanceState) {
+        super.onPostCreate(savedInstanceState);
+
+        // Sync the state of the DrawerToggle after onRestoreInstanceState has finished.
+        drawerToggle.syncState();
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        // Update the status of the drawerToggle icon.
+        drawerToggle.onConfigurationChanged(newConfig);
     }
 
     @Override
@@ -656,15 +770,22 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
         sendBroadcast(placeBookmarkShortcut);
     }
 
-    // Override onBackPressed so that if mainWebView can go back it does when the system back button is pressed.
+    // Override onBackPressed to handle the navigation drawer and mainWebView.
     @Override
     public void onBackPressed() {
         final WebView mainWebView = (WebView) findViewById(R.id.mainWebView);
 
-        if (mainWebView.canGoBack()) {
-            mainWebView.goBack();
+        // 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);
         } else {
-            super.onBackPressed();
+            // Load the previous URL if available.
+            if (mainWebView.canGoBack()) {
+                mainWebView.goBack();
+            } else {
+                // Pass onBackPressed to the system.
+                super.onBackPressed();
+            }
         }
     }
 
@@ -703,9 +824,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateHome
 
             // Use the correct search URL based on javaScriptEnabled.
             if (javaScriptEnabled) {
-                formattedUrlString = "https://duckduckgo.com/?q=" + encodedUrlString;
-            } else {
-                formattedUrlString = "https://duckduckgo.com/html/?q=" + encodedUrlString;
+                formattedUrlString = javaScriptEnabledSearchURL + encodedUrlString;
+            } else { // JavaScript is disabled.
+                formattedUrlString = javaScriptDisabledSearchURL + encodedUrlString;
             }
         }