Fix a status and navigation bar problem after viewing full-screen videos. https...
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebViewActivity.java
index 0871151183fc075d74271b1251fa296d951d5b9c..076f4145b83cc2d4ab84a5d3ce0e795374f9c8ce 100644 (file)
@@ -23,6 +23,7 @@ package com.stoutner.privacybrowser.activities;
 
 import android.Manifest;
 import android.annotation.SuppressLint;
+import android.app.Activity;
 import android.app.DialogFragment;
 import android.app.DownloadManager;
 import android.content.ActivityNotFoundException;
@@ -198,9 +199,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     public static String fanboysSocialVersion;
     public static String ultraPrivacyVersion;
 
-    // The request items are public static so they can be accessed by `BlockListHelper`, `RequestsArrayAdapter`, and `ViewRequestsDialog`.  They are also used in `onCreate()`.
+    // The request items are public static so they can be accessed by `BlockListHelper`, `RequestsArrayAdapter`, and `ViewRequestsDialog`.  They are also used in `onCreate()` and `onPrepareOptionsMenu()`.
     public static List<String[]> resourceRequests;
     public static String[] whiteListResultStringArray;
+    int blockedRequests;
+    int easyListBlockedRequests;
+    int easyPrivacyBlockedRequests;
+    int fanboysAnnoyanceListBlockedRequests;
+    int fanboysSocialBlockingListBlockedRequests;
+    int ultraPrivacyBlockedRequests;
+    int thirdPartyBlockedRequests;
+
     public final static int REQUEST_DISPOSITION = 0;
     public final static int REQUEST_URL = 1;
     public final static int REQUEST_BLOCKLIST = 2;
@@ -331,7 +340,22 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `searchURL` is used in `loadURLFromTextBox()` and `applyAppSettings()`.
     private String searchURL;
 
-    // The block list variables are used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyAppSettings()`.
+    // `mainMenu` is used in `onCreateOptionsMenu()` and `updatePrivacyIcons()`.
+    private Menu mainMenu;
+
+    // `refreshMenuItem` is used in `onCreate()` and `onCreateOptionsMenu()`.
+    private MenuItem refreshMenuItem;
+
+    // The blocklist menu items are used in `onCreate()`, `onCreateOptionsMenu()`, and `onPrepareOptionsMenu()`.
+    private MenuItem blocklistsMenuItem;
+    private MenuItem easyListMenuItem;
+    private MenuItem easyPrivacyMenuItem;
+    private MenuItem fanboysAnnoyanceListMenuItem;
+    private MenuItem fanboysSocialBlockingListMenuItem;
+    private MenuItem ultraPrivacyMenuItem;
+    private MenuItem blockAllThirdParyRequestsMenuItem;
+
+    // The blocklist variables are used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyAppSettings()`.
     private boolean easyListEnabled;
     private boolean easyPrivacyEnabled;
     private boolean fanboysAnnoyanceListEnabled;
@@ -374,6 +398,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `ignorePinnedSslCertificateForDomain` is used in `onCreate()`, `onSslMismatchProceed()`, and `applyDomainSettings()`.
     private boolean ignorePinnedSslCertificate;
 
+    // `orbotStatusBroadcastReciever` is used in `onCreate()` and `onDestroy()`.
+    private BroadcastReceiver orbotStatusBroadcastReceiver;
+
     // `waitingForOrbot` is used in `onCreate()`, `onResume()`, and `applyAppSettings()`.
     private boolean waitingForOrbot;
 
@@ -398,8 +425,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `findOnPageEditText` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
     private EditText findOnPageEditText;
 
-    // `mainMenu` is used in `onCreateOptionsMenu()` and `updatePrivacyIcons()`.
-    private Menu mainMenu;
+    // `displayAdditionalAppBarIcons` is used in `onCreate()` and `onCreateOptionsMenu()`.
+    private boolean displayAdditionalAppBarIcons;
 
     // `drawerToggle` is used in `onCreate()`, `onPostCreate()`, `onConfigurationChanged()`, `onNewIntent()`, and `onNavigationItemSelected()`.
     private ActionBarDrawerToggle drawerToggle;
@@ -427,7 +454,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `mainWebViewRelativeLayout` is used in `onCreate()` and `onNavigationItemSelected()`.
     private RelativeLayout mainWebViewRelativeLayout;
 
-    // `urlIsLoading` is used in `onCreate()`, `loadUrl()`, and `applyDomainSettings()`.
+    // `urlIsLoading` is used in `onCreate()`, `onCreateOptionsMenu()`, `loadUrl()`, and `applyDomainSettings()`.
     private boolean urlIsLoading;
 
     // `pinnedDomainSslCertificate` is used in `onCreate()` and `applyDomainSettings()`.
@@ -565,7 +592,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         waitingForOrbot = false;
 
         // Create an Orbot status `BroadcastReceiver`.
-        BroadcastReceiver orbotStatusBroadcastReceiver = new BroadcastReceiver() {
+        orbotStatusBroadcastReceiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 // Store the content of the status message in `orbotStatus`.
@@ -862,7 +889,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             return true;
         });
 
-        // The `DrawerListener` is used to update the Navigation Menu.
+        // The drawer listener is used to update the navigation menu.
         drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
             @Override
             public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
@@ -878,33 +905,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             @Override
             public void onDrawerStateChanged(int newState) {
-                if ((newState == DrawerLayout.STATE_SETTLING) || (newState == DrawerLayout.STATE_DRAGGING)) {  // The drawer is opening or closing.
-                    // Initialize a the blocked requests counter.
-                    int blockedRequests = 0;
-
-                    // Count the number of blocked requests.
-                    for (int i = 0; i < resourceRequests.size(); i++) {
-                        // Add the blocked requests.
-                        if (Integer.valueOf(resourceRequests.get(i)[REQUEST_DISPOSITION]) == REQUEST_BLOCKED) {
-                            blockedRequests++;
-                        }
-
-                        // Add the third-party requests if they are blocked.
-                        if (blockAllThirdPartyRequests && (Integer.valueOf(resourceRequests.get(i)[REQUEST_DISPOSITION]) == REQUEST_THIRD_PARTY)) {
-                            blockedRequests++;
-                        }
-                    }
-
+                if ((newState == DrawerLayout.STATE_SETTLING) || (newState == DrawerLayout.STATE_DRAGGING)) {  // A drawer is opening or closing.
                     // Update the back, forward, history, and requests menu items.
                     navigationBackMenuItem.setEnabled(mainWebView.canGoBack());
                     navigationForwardMenuItem.setEnabled(mainWebView.canGoForward());
                     navigationHistoryMenuItem.setEnabled((mainWebView.canGoBack() || mainWebView.canGoForward()));
-                    navigationRequestsMenuItem.setTitle(getResources().getString(R.string.requests) + " - " + blockedRequests);
+                    navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
 
-                    // Hide the keyboard (if displayed) so we can see the navigation menu.  `0` indicates no additional flags.
+                    // Hide the keyboard (if displayed).
                     inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
 
-                    // Clear the focus from `urlTextBox` if it has it.
+                    // Clear the focus from from the URL text box.
                     urlTextBox.clearFocus();
                 }
             }
@@ -1027,7 +1038,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             @Override
             public void onHideCustomView() {
                 // Unset the full screen video flag.
-                displayingFullScreenVideo = true;
+                displayingFullScreenVideo = false;
 
                 // Hide `fullScreenVideoFrameLayout`.
                 fullScreenVideoFrameLayout.removeAllViews();
@@ -1173,7 +1184,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Replace the header that `WebView` creates for `X-Requested-With` with a null value.  The default value is the application ID (com.stoutner.privacybrowser.standard).
         customHeaders.put("X-Requested-With", "");
 
-        // Initialize the default preference values the first time the program is run.  `this` is the context.  `false` keeps this command from resetting any current preferences back to default.
+        // Initialize the default preference values the first time the program is run.  `false` keeps this command from resetting any current preferences back to default.
         PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
 
         // Get the intent that started the app.
@@ -1246,6 +1257,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         fanboysSocialVersion = fanboysSocialList.get(0).get(0)[0];
         ultraPrivacyVersion = ultraPrivacy.get(0).get(0)[0];
 
+        // Get a handle for the activity.  This is used to update the requests counter while the navigation menu is open.
+        Activity activity = this;
+
         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.
             // The deprecated `shouldOverrideUrlLoading` must be used until API >= 24.
@@ -1366,6 +1380,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // Block third-party requests if enabled.
                 if (isThirdPartyRequest && blockAllThirdPartyRequests) {
+                    // Increment the blocked requests counters.
+                    blockedRequests++;
+                    thirdPartyBlockedRequests++;
+
+                    // Update the titles of the blocklist menu items.  This must be run from the UI thread.
+                    activity.runOnUiThread(() -> {
+                        navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                        blocklistsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                        blockAllThirdParyRequestsMenuItem.setTitle(thirdPartyBlockedRequests + " - " + getString(R.string.block_all_third_party_requests));
+                    });
+
                     // Add the request to the log.
                     resourceRequests.add(new String[]{String.valueOf(REQUEST_THIRD_PARTY), url});
 
@@ -1376,6 +1401,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Check UltraPrivacy if it is enabled.
                 if (ultraPrivacyEnabled) {
                     if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, ultraPrivacy)) {
+                        // Increment the blocked requests counters.
+                        blockedRequests++;
+                        ultraPrivacyBlockedRequests++;
+
+                        // Update the titles of the blocklist menu items.  This must be run from the UI thread.
+                        activity.runOnUiThread(() -> {
+                            navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                            blocklistsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                            ultraPrivacyMenuItem.setTitle(ultraPrivacyBlockedRequests + " - " + getString(R.string.ultraprivacy));
+                        });
+
                         // The resource request was blocked.  Return an empty web resource response.
                         return emptyWebResourceResponse;
                     }
@@ -1393,6 +1429,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Check EasyList if it is enabled.
                 if (easyListEnabled) {
                     if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, easyList)) {
+                        // Increment the blocked requests counters.
+                        blockedRequests++;
+                        easyListBlockedRequests++;
+
+                        // Update the titles of the blocklist menu items.  This must be run from the UI thread.
+                        activity.runOnUiThread(() -> {
+                            navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                            blocklistsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                            easyListMenuItem.setTitle(easyListBlockedRequests + " - " + getString(R.string.easylist));
+                        });
+
                         // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
                         whiteListResultStringArray = null;
 
@@ -1404,6 +1451,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Check EasyPrivacy if it is enabled.
                 if (easyPrivacyEnabled) {
                     if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, easyPrivacy)) {
+                        // Increment the blocked requests counters.
+                        blockedRequests++;
+                        easyPrivacyBlockedRequests++;
+
+                        // Update the titles of the blocklist menu items.  This must be run from the UI thread.
+                        activity.runOnUiThread(() -> {
+                            navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                            blocklistsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                            easyPrivacyMenuItem.setTitle(easyPrivacyBlockedRequests + " - " + getString(R.string.easyprivacy));
+                        });
+
                         // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
                         whiteListResultStringArray = null;
 
@@ -1415,6 +1473,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Check Fanboy’s Annoyance List if it is enabled.
                 if (fanboysAnnoyanceListEnabled) {
                     if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, fanboysAnnoyanceList)) {
+                        // Increment the blocked requests counters.
+                        blockedRequests++;
+                        fanboysAnnoyanceListBlockedRequests++;
+
+                        // Update the titles of the blocklist menu items.  This must be run from the UI thread.
+                        activity.runOnUiThread(() -> {
+                            navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                            blocklistsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                            fanboysAnnoyanceListMenuItem.setTitle(fanboysAnnoyanceListBlockedRequests + " - " + getString(R.string.fanboys_annoyance_list));
+                        });
+
                         // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
                         whiteListResultStringArray = null;
 
@@ -1423,6 +1492,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     }
                 } else if (fanboysSocialBlockingListEnabled){  // Only check Fanboy’s Social Blocking List if Fanboy’s Annoyance List is disabled.
                     if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, fanboysSocialList)) {
+                        // Increment the blocked requests counters.
+                        blockedRequests++;
+                        fanboysSocialBlockingListBlockedRequests++;
+
+                        // Update the titles of the blocklist menu items.  This must be run from the UI thread.
+                        activity.runOnUiThread(() -> {
+                            navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                            blocklistsMenuItem.setTitle(getString(R.string.requests) + " - " + blockedRequests);
+                            fanboysSocialBlockingListMenuItem.setTitle(fanboysSocialBlockingListBlockedRequests + " - " + getString(R.string.fanboys_social_blocking_list));
+                        });
+
                         // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
                         whiteListResultStringArray = null;
 
@@ -1459,6 +1539,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Reset the list of resource requests.
                 resourceRequests.clear();
 
+                // Initialize the counters for requests blocked by each blocklist.
+                blockedRequests = 0;
+                easyListBlockedRequests = 0;
+                easyPrivacyBlockedRequests = 0;
+                fanboysAnnoyanceListBlockedRequests = 0;
+                fanboysSocialBlockingListBlockedRequests = 0;
+                ultraPrivacyBlockedRequests = 0;
+                thirdPartyBlockedRequests = 0;
+
                 // If night mode is enabled, hide `mainWebView` until after the night mode CSS is applied.
                 if (nightMode) {
                     mainWebView.setVisibility(View.INVISIBLE);
@@ -1489,6 +1578,21 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                     // Set `urlIsLoading` to `true`, so that redirects while loading do not trigger changes in the user agent, which forces another reload of the existing page.
                     urlIsLoading = true;
+
+                    // Replace Refresh with Stop if the menu item has been created.  (The WebView typically begins loading before the menu items are instantiated.)
+                    if (refreshMenuItem != null) {
+                        // Set the title.
+                        refreshMenuItem.setTitle(R.string.stop);
+
+                        // If the icon is displayed in the AppBar, set it according to the theme.
+                        if (displayAdditionalAppBarIcons) {
+                            if (darkTheme) {
+                                refreshMenuItem.setIcon(R.drawable.close_dark);
+                            } else {
+                                refreshMenuItem.setIcon(R.drawable.close_light);
+                            }
+                        }
+                    }
                 }
             }
 
@@ -1500,6 +1604,21 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     cookieManager.flush();
                 }
 
+                // Update the Refresh menu item if it has been created.
+                if (refreshMenuItem != null) {
+                    // Reset the Refresh title.
+                    refreshMenuItem.setTitle(R.string.refresh);
+
+                    // If the icon is displayed in the AppBar, reset it according to the theme.
+                    if (displayAdditionalAppBarIcons) {
+                        if (darkTheme) {
+                            refreshMenuItem.setIcon(R.drawable.refresh_enabled_dark);
+                        } else {
+                            refreshMenuItem.setIcon(R.drawable.refresh_enabled_light);
+                        }
+                    }
+                }
+
                 // Reset `urlIsLoading`, which is used to prevent reloads on redirect if the user agent changes.
                 urlIsLoading = false;
 
@@ -1800,6 +1919,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
     @Override
     public void onPause() {
+        // Run the default commands.
         super.onPause();
 
         // Pause `mainWebView`.
@@ -1815,6 +1935,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         }
     }
 
+    @Override
+    public void onDestroy() {
+        // Unregister the Orbot status broadcast receiver.
+        this.unregisterReceiver(orbotStatusBroadcastReceiver);
+
+        // Run the default commands.
+        super.onDestroy();
+    }
+
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         // Inflate the menu; this adds items to the action bar if it is present.
@@ -1832,7 +1961,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         MenuItem toggleDomStorageMenuItem = menu.findItem(R.id.toggle_dom_storage);
         MenuItem toggleSaveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data);  // Form data can be removed once the minimum API >= 26.
         MenuItem clearFormDataMenuItem = menu.findItem(R.id.clear_form_data);  // Form data can be removed once the minimum API >= 26.
-        MenuItem refreshMenuItem = menu.findItem(R.id.refresh);
+        refreshMenuItem = menu.findItem(R.id.refresh);
+        blocklistsMenuItem = menu.findItem(R.id.blocklists);
+        easyListMenuItem = menu.findItem(R.id.easylist);
+        easyPrivacyMenuItem = menu.findItem(R.id.easyprivacy);
+        fanboysAnnoyanceListMenuItem = menu.findItem(R.id.fanboys_annoyance_list);
+        fanboysSocialBlockingListMenuItem = menu.findItem(R.id.fanboys_social_blocking_list);
+        ultraPrivacyMenuItem = menu.findItem(R.id.ultraprivacy);
+        blockAllThirdParyRequestsMenuItem = menu.findItem(R.id.block_all_third_party_requests);
         MenuItem adConsentMenuItem = menu.findItem(R.id.ad_consent);
 
         // Only display third-party cookies if API >= 21
@@ -1845,11 +1981,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Only show Ad Consent if this is the free flavor.
         adConsentMenuItem.setVisible(BuildConfig.FLAVOR.contentEquals("free"));
 
-        // Get the shared preference values.  `this` references the current context.
+        // Get the shared preference values.
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
+        // Get the status of the additional AppBar icons.
+        displayAdditionalAppBarIcons = sharedPreferences.getBoolean("display_additional_app_bar_icons", false);
+
         // Set the status of the additional app bar icons.  Setting the refresh menu item to `SHOW_AS_ACTION_ALWAYS` makes it appear even on small devices like phones.
-        if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
+        if (displayAdditionalAppBarIcons) {
             toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
             toggleDomStorageMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
             refreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
@@ -1859,6 +1998,21 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             refreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
         }
 
+        // Replace Refresh with Stop if a URL is already loading.
+        if (urlIsLoading) {
+            // Set the title.
+            refreshMenuItem.setTitle(R.string.stop);
+
+            // If the icon is displayed in the AppBar, set it according to the theme.
+            if (displayAdditionalAppBarIcons) {
+                if (darkTheme) {
+                    refreshMenuItem.setIcon(R.drawable.close_dark);
+                } else {
+                    refreshMenuItem.setIcon(R.drawable.close_light);
+                }
+            }
+        }
+
         return true;
     }
 
@@ -1874,12 +2028,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         MenuItem clearCookiesMenuItem = menu.findItem(R.id.clear_cookies);
         MenuItem clearDOMStorageMenuItem = menu.findItem(R.id.clear_dom_storage);
         MenuItem clearFormDataMenuItem = menu.findItem(R.id.clear_form_data);  // Form data can be removed once the minimum API >= 26.
-        MenuItem easyListMenuItem = menu.findItem(R.id.easylist);
-        MenuItem easyPrivacyMenuItem = menu.findItem(R.id.easyprivacy);
-        MenuItem fanboysAnnoyanceListMenuItem = menu.findItem(R.id.fanboys_annoyance_list);
-        MenuItem fanboysSocialBlockingListMenuItem = menu.findItem(R.id.fanboys_social_blocking_list);
-        MenuItem ultraPrivacyMenuItem = menu.findItem(R.id.ultraprivacy);
-        MenuItem blockAllThirdParyRequestsMenuItem = menu.findItem(R.id.block_all_third_party_requests);
         MenuItem fontSizeMenuItem = menu.findItem(R.id.font_size);
         MenuItem swipeToRefreshMenuItem = menu.findItem(R.id.swipe_to_refresh);
         MenuItem displayImagesMenuItem = menu.findItem(R.id.display_images);
@@ -1946,6 +2094,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Disable Fanboy's Social Blocking List if Fanboy's Annoyance List is checked.
         fanboysSocialBlockingListMenuItem.setEnabled(!fanboysAnnoyanceListEnabled);
 
+        // Initialize the display names for the blocklists with the number of blocked requests.
+        blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + blockedRequests);
+        easyListMenuItem.setTitle(easyListBlockedRequests + " - " + getString(R.string.easylist));
+        easyPrivacyMenuItem.setTitle(easyPrivacyBlockedRequests + " - " + getString(R.string.easyprivacy));
+        fanboysAnnoyanceListMenuItem.setTitle(fanboysAnnoyanceListBlockedRequests + " - " + getString(R.string.fanboys_annoyance_list));
+        fanboysSocialBlockingListMenuItem.setTitle(fanboysSocialBlockingListBlockedRequests + " - " + getString(R.string.fanboys_social_blocking_list));
+        ultraPrivacyMenuItem.setTitle(ultraPrivacyBlockedRequests + " - " + getString(R.string.ultraprivacy));
+        blockAllThirdParyRequestsMenuItem.setTitle(thirdPartyBlockedRequests + " - " + getString(R.string.block_all_third_party_requests));
+
         // Initialize font size variables.
         int fontSize = mainWebView.getSettings().getTextZoom();
         String fontSizeTitle;
@@ -2458,7 +2615,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 return true;
 
             case R.id.refresh:
-                mainWebView.reload();
+                if (menuItem.getTitle().equals(getString(R.string.refresh))) {  // The refresh button was pushed.
+                    // Reload the WebView.
+                    mainWebView.reload();
+                } else {  // The stop button was pushed.
+                    // Stop the loading of the WebView.
+                    mainWebView.stopLoading();
+                }
                 return true;
 
             case R.id.ad_consent:
@@ -3475,8 +3638,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Apply the domain settings.
         applyDomainSettings(url, true, false);
 
-        // Set `urlIsLoading` to prevent changes in the user agent on websites with redirects from reloading the current website.
-        urlIsLoading = true;
+        // If loading a website, set `urlIsLoading` to prevent changes in the user agent on websites with redirects from reloading the current website.
+        urlIsLoading = !url.equals("");
 
         // Load the URL.
         mainWebView.loadUrl(url, customHeaders);