]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/MainWebViewActivity.java
Trim white spaces from the beginning and end of the URL before loading. Fixes https...
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / MainWebViewActivity.java
index 2edbfdfeea2efd2f6eb21176b37f4bb986f311c9..e4e68c36957255d62865e3dcfb6087cb34722a6e 100644 (file)
@@ -67,7 +67,7 @@ import java.net.URLEncoder;
 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 and SettingsFragment.  It is also used in onCreate(), onOptionsItemSelected(), onNavigationItemSelected(), and loadUrlFromTextBox().
+    // 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;
 
     // mainMenu is public static so it can be accessed from SettingsFragment.  It is also used in onCreateOptionsMenu() and onOptionsItemSelected().
@@ -78,7 +78,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     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().
+    // thirdPartyCookiesEnabled is used 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;
@@ -99,31 +99,58 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     private DrawerLayout drawerLayout;
     // formattedUrlString is used in onCreate(), onOptionsItemSelected(), onCreateHomeScreenShortcutCreate(), and loadUrlFromTextBox().
     private String formattedUrlString;
-
+    // privacyIcon is used in onCreateOptionsMenu() and updatePrivacyIcon().
+    private MenuItem privacyIcon;
     // urlTextBox is used in onCreate(), onOptionsItemSelected(), and loadUrlFromTextBox().
     private EditText urlTextBox;
+    // adView is used in onCreate() and onConfigurationChanged().
+    private View adView;
 
     @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.
     @SuppressLint("SetJavaScriptEnabled")
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.coordinator_layout);
+        setContentView(R.layout.main_coordinatorlayout);
 
         // 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);
-
-        final FrameLayout fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.fullScreenVideoFrameLayout);
-
-        // We need to use the SupportActionBar from android.support.v7.app.ActionBar until the minimum API is >= 21.
         final ActionBar appBar = getSupportActionBar();
 
-        // Setup AdView for the free flavor.
-        final View adView = findViewById(R.id.adView);
+        // 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);
+        appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+
+        // Set the "go" button on the keyboard to load the URL in urlTextBox.
+        urlTextBox = (EditText) appBar.getCustomView().findViewById(R.id.urlTextBox);
+        urlTextBox.setOnKeyListener(new View.OnKeyListener() {
+            public boolean onKey(View v, int keyCode, KeyEvent event) {
+                // If the event is a key-down event on the "enter" button, load the URL.
+                if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
+                    // Load the URL into the mainWebView and consume the event.
+                    try {
+                        loadUrlFromTextBox();
+                    } catch (UnsupportedEncodingException e) {
+                        e.printStackTrace();
+                    }
+                    // If the enter key was pressed, consume the event.
+                    return true;
+                } else {
+                    // If any other key was pressed, do not consume the event.
+                    return false;
+                }
+            }
+        });
+
+        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);
         swipeToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
             @Override
@@ -134,33 +161,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
 
         mainWebView = (WebView) findViewById(R.id.mainWebView);
 
-        if (appBar != null) {
-            // Add the custom url_bar layout, which shows the favoriteIcon, urlTextBar, and progressBar.
-            appBar.setCustomView(R.layout.url_bar);
-            appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
-
-            // Set the "go" button on the keyboard to load the URL in urlTextBox.
-            urlTextBox = (EditText) appBar.getCustomView().findViewById(R.id.urlTextBox);
-            urlTextBox.setOnKeyListener(new View.OnKeyListener() {
-                public boolean onKey(View v, int keyCode, KeyEvent event) {
-                    // If the event is a key-down event on the "enter" button, load the URL.
-                    if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
-                        // Load the URL into the mainWebView and consume the event.
-                        try {
-                            loadUrlFromTextBox();
-                        } catch (UnsupportedEncodingException e) {
-                            e.printStackTrace();
-                        }
-                        // If the enter key was pressed, consume the event.
-                        return true;
-                    } else {
-                        // If any other key was pressed, do not consume the event.
-                        return false;
-                    }
-                }
-            });
-        }
-
         // Create the navigation drawer.
         drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
         // The DrawerTitle identifies the drawer in accessibility mode.
@@ -168,6 +168,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
 
         // 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.
@@ -203,18 +204,15 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             // Update the progress bar when a page is loading.
             @Override
             public void onProgressChanged(WebView view, int progress) {
-                // Make sure that appBar is not null.
-                if (appBar != null) {
-                    ProgressBar progressBar = (ProgressBar) appBar.getCustomView().findViewById(R.id.progressBar);
-                    progressBar.setProgress(progress);
-                    if (progress < 100) {
-                        progressBar.setVisibility(View.VISIBLE);
-                    } else {
-                        progressBar.setVisibility(View.GONE);
+                ProgressBar progressBar = (ProgressBar) appBar.getCustomView().findViewById(R.id.progressBar);
+                progressBar.setProgress(progress);
+                if (progress < 100) {
+                    progressBar.setVisibility(View.VISIBLE);
+                } else {
+                    progressBar.setVisibility(View.GONE);
 
-                        //Stop the SwipeToRefresh indicator if it is running
-                        swipeToRefresh.setRefreshing(false);
-                    }
+                    //Stop the SwipeToRefresh indicator if it is running
+                    swipeToRefresh.setRefreshing(false);
                 }
             }
 
@@ -224,21 +222,18 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 // Save a copy of the favorite icon for use if a shortcut is added to the home screen.
                 favoriteIcon = icon;
 
-                // Place the favorite icon in the appBar if it is not null.
-                if (appBar != null) {
-                    ImageView imageViewFavoriteIcon = (ImageView) appBar.getCustomView().findViewById(R.id.favoriteIcon);
-                    imageViewFavoriteIcon.setImageBitmap(Bitmap.createScaledBitmap(icon, 64, 64, true));
-                }
+                // Place the favorite icon in the appBar.
+                ImageView imageViewFavoriteIcon = (ImageView) appBar.getCustomView().findViewById(R.id.favoriteIcon);
+                imageViewFavoriteIcon.setImageBitmap(Bitmap.createScaledBitmap(icon, 64, 64, true));
             }
 
             // Enter full screen video
             @Override
             public void onShowCustomView(View view, CustomViewCallback callback) {
-                if (appBar != null) {
-                    appBar.hide();
-                }
+                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);
 
@@ -249,29 +244,15 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 BannerAd.hideAd(adView);
 
                 /* SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bars on the bottom or right of the screen.
-                ** SYSTEM_UI_FLAG_FULLSCREEN hides the status bar across the top of the screen.
-                ** SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the navigation and status bars ghosted overlays and automatically rehides them.
-                */
-
-                // Set the one flag supported by API >= 14.
-                view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
-
-                // Set the two flags that are supported by API >= 16.
-                if (Build.VERSION.SDK_INT >= 16) {
-                    view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN);
-                }
-
-                // Set all three flags that are supported by API >= 19.
-                if (Build.VERSION.SDK_INT >= 19) {
-                    view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
-                }
+                 * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar across the top of the screen.
+                 * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the navigation and status bars ghosted overlays and automatically rehides them.
+                 */
+                view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
             }
 
             // Exit full screen video
             public void onHideCustomView() {
-                if (appBar != null) {
-                    appBar.show();
-                }
+                appBar.show();
 
                 // Show the mainWebView.
                 mainWebView.setVisibility(View.VISIBLE);
@@ -280,6 +261,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 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);
             }
@@ -401,10 +383,12 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // Load the initial website.
         mainWebView.loadUrl(formattedUrlString);
 
-        // Load the ad if this is the free flavor.
+        // Initialize AdView for the free flavor and request an ad.  If this is not the free flavor BannerAd.requestAd() does nothing.
+        adView = findViewById(R.id.adView);
         BannerAd.requestAd(adView);
     }
 
+
     @Override
     protected void onNewIntent(Intent intent) {
         // Sets the new intent as the activity intent, so that any future getIntent()s pick up this one instead of creating a new activity.
@@ -436,33 +420,21 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // Set mainMenu so it can be used by onOptionsItemSelected.
         mainMenu = menu;
 
+        // Initialize privacyIcon
+        privacyIcon = menu.findItem(R.id.toggleJavaScript);
+
         // 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);
-        */
 
-        // Set the initial icon for toggleJavaScript
-        if (javaScriptEnabled) {
-            toggleJavaScript.setIcon(R.drawable.javascript_enabled);
-        } else {
-            if (domStorageEnabled || firstPartyCookiesEnabled) {
-                toggleJavaScript.setIcon(R.drawable.warning);
-            } else {
-                toggleJavaScript.setIcon(R.drawable.privacy_mode);
-            }
-        }
+        // Set the initial status of the privacy icon.
+        updatePrivacyIcon();
 
         // 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);
-        */
 
         return true;
     }
@@ -481,6 +453,10 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         MenuItem clearCookies = menu.findItem(R.id.clearCookies);
         clearCookies.setEnabled(cookieManager.hasCookies());
 
+        // Enable DOM Storage if JavaScript is enabled.
+        MenuItem toggleDomStorage = menu.findItem(R.id.toggleDomStorage);
+        toggleDomStorage.setEnabled(javaScriptEnabled);
+
         // Run all the other default commands.
         super.onPrepareOptionsMenu(menu);
 
@@ -496,120 +472,78 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     public boolean onOptionsItemSelected(MenuItem menuItem) {
         int menuItemId = menuItem.getItemId();
 
-        // Some options need to update the drawable for toggleJavaScript.
-        MenuItem toggleJavaScript = mainMenu.findItem(R.id.toggleJavaScript);
-
         // Set the commands that relate to the menu entries.
         switch (menuItemId) {
             case R.id.toggleJavaScript:
-                if (javaScriptEnabled) {
-                    javaScriptEnabled = false;
-                    mainWebView.getSettings().setJavaScriptEnabled(false);
-                    mainWebView.reload();
+                // Switch the status of javaScriptEnabled.
+                javaScriptEnabled = !javaScriptEnabled;
 
-                    // Update the toggleJavaScript icon and display a snackbar.
-                    if (domStorageEnabled || firstPartyCookiesEnabled) {
-                        menuItem.setIcon(R.drawable.warning);
+                // Apply the new JavaScript status.
+                mainWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
+
+                // Update the privacy icon.
+                updatePrivacyIcon();
+
+                // Display a Snackbar.
+                if (javaScriptEnabled) {
+                    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 {
-                        menuItem.setIcon(R.drawable.privacy_mode);
                         Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
                     }
-                } else {
-                    javaScriptEnabled = true;
-                    menuItem.setIcon(R.drawable.javascript_enabled);
-                    mainWebView.getSettings().setJavaScriptEnabled(true);
-                    mainWebView.reload();
-                    Snackbar.make(findViewById(R.id.mainWebView), R.string.javascript_enabled, Snackbar.LENGTH_SHORT).show();
                 }
+
+                // Reload the WebView.
+                mainWebView.reload();
                 return true;
 
             case R.id.toggleFirstPartyCookies:
-                if (firstPartyCookiesEnabled) {
-                    firstPartyCookiesEnabled = false;
-                    menuItem.setChecked(false);
-                    cookieManager.setAcceptCookie(false);
-                    mainWebView.reload();
+                // Switch the status of firstPartyCookiesEnabled.
+                firstPartyCookiesEnabled = !firstPartyCookiesEnabled;
 
-                    // 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.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 {
-                    firstPartyCookiesEnabled = true;
-                    menuItem.setChecked(true);
-                    cookieManager.setAcceptCookie(true);
-                    mainWebView.reload();
+                // Update the menu checkbox.
+                menuItem.setChecked(firstPartyCookiesEnabled);
 
-                    // Update the toggleJavaScript icon if appropriate.
-                    if (!javaScriptEnabled) {
-                        toggleJavaScript.setIcon(R.drawable.warning);
-                    } // Else do nothing because JavaScript is enabled.
+                // Apply the new cookie status.
+                cookieManager.setAcceptCookie(firstPartyCookiesEnabled);
 
-                    Snackbar.make(findViewById(R.id.mainWebView), R.string.first_party_cookies_enabled, Snackbar.LENGTH_SHORT).show();
-                }
+                // Update the privacy icon.
+                updatePrivacyIcon();
+
+                // Reload the WebView.
+                mainWebView.reload();
                 return true;
 
             case R.id.toggleThirdPartyCookies:
                 if (Build.VERSION.SDK_INT >= 21) {
-                    if (thirdPartyCookiesEnabled) {
-                        thirdPartyCookiesEnabled = false;
-                        menuItem.setChecked(false);
-                        cookieManager.setAcceptThirdPartyCookies(mainWebView, false);
-                        mainWebView.reload();
+                    // Switch the status of thirdPartyCookiesEnabled.
+                    thirdPartyCookiesEnabled = !thirdPartyCookiesEnabled;
 
-                        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();
+                    // Update the menu checkbox.
+                    menuItem.setChecked(thirdPartyCookiesEnabled);
 
-                        Snackbar.make(findViewById(R.id.mainWebView), R.string.third_party_cookies_enabled, Snackbar.LENGTH_SHORT).show();
-                    }
+                    // Apply the new cookie status.
+                    cookieManager.setAcceptThirdPartyCookies(mainWebView, thirdPartyCookiesEnabled);
+
+                    // Reload the WebView.
+                    mainWebView.reload();
                 } // Else do nothing because SDK < 21.
                 return true;
 
             case R.id.toggleDomStorage:
-                if (domStorageEnabled) {
-                    domStorageEnabled = false;
-                    menuItem.setChecked(false);
-                    mainWebView.getSettings().setDomStorageEnabled(false);
-                    mainWebView.reload();
+                // Switch the status of domStorageEnabled.
+                domStorageEnabled = !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_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 {
-                    domStorageEnabled = true;
-                    menuItem.setChecked(true);
-                    mainWebView.getSettings().setDomStorageEnabled(true);
-                    mainWebView.reload();
+                // Update the menu checkbox.
+                menuItem.setChecked(domStorageEnabled);
 
-                    // Update the toggleJavaScript icon if appropriate.
-                    if (!javaScriptEnabled) {
-                        toggleJavaScript.setIcon(R.drawable.warning);
-                    } // Else Do nothing because JavaScript is enabled.
+                // Apply the new DOM Storage status.
+                mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
 
-                    Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show();
-                }
+                // Reload the WebView.
+                mainWebView.reload();
                 return true;
 
             case R.id.clearCookies:
@@ -686,23 +620,25 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 startActivity(downloadManagerIntent);
                 break;
 
+            case R.id.guide:
+                // Launch GuideActivity.
+                Intent guideIntent = new Intent(this, GuideActivity.class);
+                startActivity(guideIntent);
+                break;
+
             case R.id.settings:
-                // Launch PreferenceFragment.
-                Intent intent = new Intent(this, SettingsActivity.class);
-                startActivity(intent);
+                // Launch SettingsActivity.
+                Intent settingsIntent = new Intent(this, SettingsActivity.class);
+                startActivity(settingsIntent);
                 break;
 
             case R.id.about:
-                // Show the AboutDialog AlertDialog and name this instance aboutDialog.
-                AppCompatDialogFragment aboutDialog = new AboutDialog();
-                aboutDialog.show(getSupportFragmentManager(), "aboutDialog");
+                // Launch AboutActivity.
+                Intent aboutIntent = new Intent(this, AboutActivity.class);
+                startActivity(aboutIntent);
                 break;
 
             case R.id.clearAndExit:
-                // Clear DOM storage.
-                WebStorage domStorage = WebStorage.getInstance();
-                domStorage.deleteAllData();
-
                 // Clear cookies.  The commands changed slightly in API 21.
                 if (Build.VERSION.SDK_INT >= 21) {
                     cookieManager.removeAllCookies(null);
@@ -710,6 +646,16 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                     cookieManager.removeAllCookie();
                 }
 
+                // Clear DOM storage.
+                WebStorage domStorage = WebStorage.getInstance();
+                domStorage.deleteAllData();
+
+                // Clear cache.  The argument of "true" includes disk files.
+                mainWebView.clearCache(true);
+
+                // Clear the back/forward history.
+                mainWebView.clearHistory();
+
                 // Destroy the internal state of the webview.
                 mainWebView.destroy();
 
@@ -742,8 +688,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
-        // Update the status of the drawerToggle icon.
-        drawerToggle.onConfigurationChanged(newConfig);
+        // Reload the ad if this is the free flavor.
+        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);
     }
 
     @Override
@@ -780,6 +729,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             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 {
@@ -789,9 +739,26 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         }
     }
 
+    @Override
+    public void onPause() {
+        // We need to pause the adView or it will continue to consume resources in the background on the free flavor.
+        BannerAd.pauseAd(adView);
+
+        super.onPause();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        // We need to resume the adView for the free flavor.
+        BannerAd.resumeAd(adView);
+    }
+
     private void loadUrlFromTextBox() throws UnsupportedEncodingException {
-        // Get the text from urlTextBox and convert it to a string.
-        String unformattedUrlString = urlTextBox.getText().toString();
+        // 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();
+
         URL unformattedUrl = null;
         Uri.Builder formattedUri = new Uri.Builder();
 
@@ -836,4 +803,16 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
         inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
     }
+
+    private void updatePrivacyIcon() {
+        if (javaScriptEnabled) {
+            privacyIcon.setIcon(R.drawable.javascript_enabled);
+        } else {
+            if (firstPartyCookiesEnabled) {
+                privacyIcon.setIcon(R.drawable.warning);
+            } else {
+                privacyIcon.setIcon(R.drawable.privacy_mode);
+            }
+        }
+    }
 }