+ // 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 (displayAdditionalAppBarIcons) {
+ toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ toggleDomStorageMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ refreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ } else { //Do not display the additional icons.
+ toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ toggleDomStorageMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ refreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ }
+
+ // Replace Refresh with Stop if a URL is already loading.
+ if (currentWebView != null && currentWebView.getProgress() != 100) {
+ // 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);
+ }
+ }
+ }
+
+ // Done.
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ // Get handles for the menu items.
+ MenuItem addOrEditDomain = menu.findItem(R.id.add_or_edit_domain);
+ MenuItem firstPartyCookiesMenuItem = menu.findItem(R.id.toggle_first_party_cookies);
+ MenuItem thirdPartyCookiesMenuItem = menu.findItem(R.id.toggle_third_party_cookies);
+ MenuItem domStorageMenuItem = menu.findItem(R.id.toggle_dom_storage);
+ MenuItem saveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data); // Form data can be removed once the minimum API >= 26.
+ MenuItem clearDataMenuItem = menu.findItem(R.id.clear_data);
+ 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 blocklistsMenuItem = menu.findItem(R.id.blocklists);
+ 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 ultraListMenuItem = menu.findItem(R.id.ultralist);
+ MenuItem ultraPrivacyMenuItem = menu.findItem(R.id.ultraprivacy);
+ MenuItem blockAllThirdPartyRequestsMenuItem = 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 wideViewportMenuItem = menu.findItem(R.id.wide_viewport);
+ MenuItem displayImagesMenuItem = menu.findItem(R.id.display_images);
+ MenuItem nightModeMenuItem = menu.findItem(R.id.night_mode);
+ MenuItem proxyThroughOrbotMenuItem = menu.findItem(R.id.proxy_through_orbot);
+
+ // Get a handle for the cookie manager.
+ CookieManager cookieManager = CookieManager.getInstance();
+
+ // Initialize the current user agent string and the font size.
+ String currentUserAgent = getString(R.string.user_agent_privacy_browser);
+ int fontSize = 100;
+
+ // Set items that require the current web view to be populated. It will be null when the program is first opened, as `onPrepareOptionsMenu()` is called before the first WebView is initialized.
+ if (currentWebView != null) {
+ // Set the add or edit domain text.
+ if (currentWebView.getDomainSettingsApplied()) {
+ addOrEditDomain.setTitle(R.string.edit_domain_settings);
+ } else {
+ addOrEditDomain.setTitle(R.string.add_domain_settings);
+ }
+
+ // Get the current user agent from the WebView.
+ currentUserAgent = currentWebView.getSettings().getUserAgentString();
+
+ // Get the current font size from the
+ fontSize = currentWebView.getSettings().getTextZoom();
+
+ // Set the status of the menu item checkboxes.
+ domStorageMenuItem.setChecked(currentWebView.getSettings().getDomStorageEnabled());
+ saveFormDataMenuItem.setChecked(currentWebView.getSettings().getSaveFormData()); // Form data can be removed once the minimum API >= 26.
+ easyListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASYLIST));
+ easyPrivacyMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASYPRIVACY));
+ fanboysAnnoyanceListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST));
+ fanboysSocialBlockingListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST));
+ ultraListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRALIST));
+ ultraPrivacyMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRAPRIVACY));
+ blockAllThirdPartyRequestsMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.THIRD_PARTY_REQUESTS));
+ swipeToRefreshMenuItem.setChecked(currentWebView.getSwipeToRefresh());
+ wideViewportMenuItem.setChecked(currentWebView.getSettings().getUseWideViewPort());
+ displayImagesMenuItem.setChecked(currentWebView.getSettings().getLoadsImagesAutomatically());
+ nightModeMenuItem.setChecked(currentWebView.getNightMode());
+
+ // Initialize the display names for the blocklists with the number of blocked requests.
+ blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + currentWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
+ easyListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASYLIST) + " - " + getString(R.string.easylist));
+ easyPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASYPRIVACY) + " - " + getString(R.string.easyprivacy));
+ fanboysAnnoyanceListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST) + " - " + getString(R.string.fanboys_annoyance_list));
+ fanboysSocialBlockingListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST) + " - " + getString(R.string.fanboys_social_blocking_list));
+ ultraListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.ULTRALIST) + " - " + getString(R.string.ultralist));
+ ultraPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.ULTRAPRIVACY) + " - " + getString(R.string.ultraprivacy));
+ blockAllThirdPartyRequestsMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.THIRD_PARTY_REQUESTS) + " - " + getString(R.string.block_all_third_party_requests));
+
+ // Only modify third-party cookies if the API >= 21.
+ if (Build.VERSION.SDK_INT >= 21) {
+ // Set the status of the third-party cookies checkbox.
+ thirdPartyCookiesMenuItem.setChecked(cookieManager.acceptThirdPartyCookies(currentWebView));
+
+ // Enable third-party cookies if first-party cookies are enabled.
+ thirdPartyCookiesMenuItem.setEnabled(cookieManager.acceptCookie());
+ }
+
+ // Enable DOM Storage if JavaScript is enabled.
+ domStorageMenuItem.setEnabled(currentWebView.getSettings().getJavaScriptEnabled());
+ }
+
+ // Set the status of the menu item checkboxes.
+ firstPartyCookiesMenuItem.setChecked(cookieManager.acceptCookie());
+ proxyThroughOrbotMenuItem.setChecked(proxyThroughOrbot);
+
+ // Enable Clear Cookies if there are any.
+ clearCookiesMenuItem.setEnabled(cookieManager.hasCookies());
+
+ // Get the application's private data directory, which will be something like `/data/user/0/com.stoutner.privacybrowser.standard`, which links to `/data/data/com.stoutner.privacybrowser.standard`.
+ String privateDataDirectoryString = getApplicationInfo().dataDir;
+
+ // Get a count of the number of files in the Local Storage directory.
+ File localStorageDirectory = new File (privateDataDirectoryString + "/app_webview/Local Storage/");
+ int localStorageDirectoryNumberOfFiles = 0;
+ if (localStorageDirectory.exists()) {
+ localStorageDirectoryNumberOfFiles = localStorageDirectory.list().length;
+ }
+
+ // Get a count of the number of files in the IndexedDB directory.
+ File indexedDBDirectory = new File (privateDataDirectoryString + "/app_webview/IndexedDB");
+ int indexedDBDirectoryNumberOfFiles = 0;
+ if (indexedDBDirectory.exists()) {
+ indexedDBDirectoryNumberOfFiles = indexedDBDirectory.list().length;
+ }
+
+ // Enable Clear DOM Storage if there is any.
+ clearDOMStorageMenuItem.setEnabled(localStorageDirectoryNumberOfFiles > 0 || indexedDBDirectoryNumberOfFiles > 0);
+
+ // Enable Clear Form Data is there is any. This can be removed once the minimum API >= 26.
+ if (Build.VERSION.SDK_INT < 26) {
+ // Get the WebView database.
+ WebViewDatabase webViewDatabase = WebViewDatabase.getInstance(this);
+
+ // Enable the clear form data menu item if there is anything to clear.
+ clearFormDataMenuItem.setEnabled(webViewDatabase.hasFormData());
+ }
+
+ // Enable Clear Data if any of the submenu items are enabled.
+ clearDataMenuItem.setEnabled(clearCookiesMenuItem.isEnabled() || clearDOMStorageMenuItem.isEnabled() || clearFormDataMenuItem.isEnabled());
+
+ // Disable Fanboy's Social Blocking List menu item if Fanboy's Annoyance List is checked.
+ fanboysSocialBlockingListMenuItem.setEnabled(!fanboysAnnoyanceListMenuItem.isChecked());
+
+ // Select the current user agent menu item. A switch statement cannot be used because the user agents are not compile time constants.
+ if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[0])) { // Privacy Browser.
+ menu.findItem(R.id.user_agent_privacy_browser).setChecked(true);
+ } else if (currentUserAgent.equals(webViewDefaultUserAgent)) { // WebView Default.
+ menu.findItem(R.id.user_agent_webview_default).setChecked(true);
+ } else if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[2])) { // Firefox on Android.
+ menu.findItem(R.id.user_agent_firefox_on_android).setChecked(true);
+ } else if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[3])) { // Chrome on Android.
+ menu.findItem(R.id.user_agent_chrome_on_android).setChecked(true);
+ } else if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[4])) { // Safari on iOS.
+ menu.findItem(R.id.user_agent_safari_on_ios).setChecked(true);
+ } else if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[5])) { // Firefox on Linux.
+ menu.findItem(R.id.user_agent_firefox_on_linux).setChecked(true);
+ } else if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[6])) { // Chromium on Linux.
+ menu.findItem(R.id.user_agent_chromium_on_linux).setChecked(true);
+ } else if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[7])) { // Firefox on Windows.
+ menu.findItem(R.id.user_agent_firefox_on_windows).setChecked(true);
+ } else if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[8])) { // Chrome on Windows.
+ menu.findItem(R.id.user_agent_chrome_on_windows).setChecked(true);
+ } else if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[9])) { // Edge on Windows.
+ menu.findItem(R.id.user_agent_edge_on_windows).setChecked(true);
+ } else if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[10])) { // Internet Explorer on Windows.
+ menu.findItem(R.id.user_agent_internet_explorer_on_windows).setChecked(true);
+ } else if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[11])) { // Safari on macOS.
+ menu.findItem(R.id.user_agent_safari_on_macos).setChecked(true);
+ } else { // Custom user agent.
+ menu.findItem(R.id.user_agent_custom).setChecked(true);
+ }
+
+ // Instantiate the font size title and the selected font size menu item.
+ String fontSizeTitle;
+ MenuItem selectedFontSizeMenuItem;
+
+ // Prepare the font size title and current size menu item.
+ switch (fontSize) {
+ case 25:
+ fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.twenty_five_percent);
+ selectedFontSizeMenuItem = menu.findItem(R.id.font_size_twenty_five_percent);
+ break;
+
+ case 50:
+ fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.fifty_percent);
+ selectedFontSizeMenuItem = menu.findItem(R.id.font_size_fifty_percent);
+ break;
+
+ case 75:
+ fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.seventy_five_percent);
+ selectedFontSizeMenuItem = menu.findItem(R.id.font_size_seventy_five_percent);
+ break;
+
+ case 100:
+ fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.one_hundred_percent);
+ selectedFontSizeMenuItem = menu.findItem(R.id.font_size_one_hundred_percent);
+ break;
+
+ case 125:
+ fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.one_hundred_twenty_five_percent);
+ selectedFontSizeMenuItem = menu.findItem(R.id.font_size_one_hundred_twenty_five_percent);
+ break;
+
+ case 150:
+ fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.one_hundred_fifty_percent);
+ selectedFontSizeMenuItem = menu.findItem(R.id.font_size_one_hundred_fifty_percent);
+ break;
+
+ case 175:
+ fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.one_hundred_seventy_five_percent);
+ selectedFontSizeMenuItem = menu.findItem(R.id.font_size_one_hundred_seventy_five_percent);
+ break;
+
+ case 200:
+ fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.two_hundred_percent);
+ selectedFontSizeMenuItem = menu.findItem(R.id.font_size_two_hundred_percent);
+ break;
+
+ default:
+ fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.one_hundred_percent);
+ selectedFontSizeMenuItem = menu.findItem(R.id.font_size_one_hundred_percent);
+ break;
+ }
+
+ // Set the font size title and select the current size menu item.
+ fontSizeMenuItem.setTitle(fontSizeTitle);
+ selectedFontSizeMenuItem.setChecked(true);
+
+ // Run all the other default commands.
+ super.onPrepareOptionsMenu(menu);
+
+ // Display the menu.
+ return true;
+ }
+
+ @Override
+ // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.
+ @SuppressLint("SetJavaScriptEnabled")
+ public boolean onOptionsItemSelected(MenuItem menuItem) {
+ // Get the selected menu item ID.
+ int menuItemId = menuItem.getItemId();
+
+ // Get a handle for the shared preferences.
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+
+ // Get a handle for the cookie manager.
+ CookieManager cookieManager = CookieManager.getInstance();
+
+ // Run the commands that correlate to the selected menu item.
+ switch (menuItemId) {
+ case R.id.toggle_javascript:
+ // Toggle the JavaScript status.
+ currentWebView.getSettings().setJavaScriptEnabled(!currentWebView.getSettings().getJavaScriptEnabled());
+
+ // Update the privacy icon. `true` runs `invalidateOptionsMenu` as the last step.
+ updatePrivacyIcons(true);
+
+ // Display a `Snackbar`.
+ if (currentWebView.getSettings().getJavaScriptEnabled()) { // JavaScrip is enabled.
+ Snackbar.make(findViewById(R.id.webviewpager), R.string.javascript_enabled, Snackbar.LENGTH_SHORT).show();
+ } else if (cookieManager.acceptCookie()) { // JavaScript is disabled, but first-party cookies are enabled.
+ Snackbar.make(findViewById(R.id.webviewpager), R.string.javascript_disabled, Snackbar.LENGTH_SHORT).show();
+ } else { // Privacy mode.
+ Snackbar.make(findViewById(R.id.webviewpager), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
+ }
+
+ // Reload the current WebView.
+ currentWebView.reload();