import android.Manifest;
import android.annotation.SuppressLint;
+import android.app.Activity;
import android.app.DialogFragment;
import android.app.DownloadManager;
import android.content.ActivityNotFoundException;
// 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;
// `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;
// `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;
// `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()`.
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) {
@Override
public void onDrawerStateChanged(int newState) {
- if ((newState == DrawerLayout.STATE_SETTLING) || (newState == DrawerLayout.STATE_DRAGGING)) { // The drawer is opening or closing.
- // Calculate the total blocked requests counter.
- int totalBlockedRequests = easyListBlockedRequests + easyPrivacyBlockedRequests + fanboysAnnoyanceListBlockedRequests + fanboysSocialBlockingListBlockedRequests +
- ultraPrivacyBlockedRequests + thirdPartyBlockedRequests;
-
+ 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) + " - " + totalBlockedRequests);
+ 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();
}
}
@Override
public void onHideCustomView() {
// Unset the full screen video flag.
- displayingFullScreenVideo = true;
+ displayingFullScreenVideo = false;
// Hide `fullScreenVideoFrameLayout`.
fullScreenVideoFrameLayout.removeAllViews();
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.
// Block third-party requests if enabled.
if (isThirdPartyRequest && blockAllThirdPartyRequests) {
- // Increment the third-party blocked requests counter.
+ // 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});
// Check UltraPrivacy if it is enabled.
if (ultraPrivacyEnabled) {
if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, ultraPrivacy)) {
- // Increment the UltraPrivacy blocked requests counter.
+ // 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;
}
// Check EasyList if it is enabled.
if (easyListEnabled) {
if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, easyList)) {
- // Increment the EasyList blocked requests counter.
+ // 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;
// Check EasyPrivacy if it is enabled.
if (easyPrivacyEnabled) {
if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, easyPrivacy)) {
- // Increment the EasyPrivacy blocked requests counter.
+ // 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;
// Check Fanboy’s Annoyance List if it is enabled.
if (fanboysAnnoyanceListEnabled) {
if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, fanboysAnnoyanceList)) {
- // Increment the Fanboy's Annoyance List blocked requests counter.
+ // 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;
}
} 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 Fanboy's Social Blocking List blocked requests counter.
+ // 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;
resourceRequests.clear();
// Initialize the counters for requests blocked by each blocklist.
+ blockedRequests = 0;
easyListBlockedRequests = 0;
easyPrivacyBlockedRequests = 0;
fanboysAnnoyanceListBlockedRequests = 0;
// 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);
+ }
+ }
+ }
}
}
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;
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
// 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);
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;
}
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);
// Enable Clear Data if any of the submenu items are enabled.
clearDataMenuItem.setEnabled(clearCookiesMenuItem.isEnabled() || clearDOMStorageMenuItem.isEnabled() || clearFormDataMenuItem.isEnabled());
- // Update the display names for the blocklists with the number of blocked requests.
+ // 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));
ultraPrivacyMenuItem.setTitle(ultraPrivacyBlockedRequests + " - " + getString(R.string.ultraprivacy));
blockAllThirdParyRequestsMenuItem.setTitle(thirdPartyBlockedRequests + " - " + getString(R.string.block_all_third_party_requests));
- // Disable Fanboy's Social Blocking List if Fanboy's Annoyance List is checked.
- fanboysSocialBlockingListMenuItem.setEnabled(!fanboysAnnoyanceListEnabled);
-
// Initialize font size variables.
int fontSize = mainWebView.getSettings().getTextZoom();
String fontSizeTitle;
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:
// 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);