- // Only display the form data menu items if the API < 26.
- toggleSaveFormDataMenuItem.setVisible(Build.VERSION.SDK_INT < 26);
- clearFormDataMenuItem.setVisible(Build.VERSION.SDK_INT < 26);
-
- // Disable the clear form data menu item if the API >= 26 so that the status of the main Clear Data is calculated correctly.
- clearFormDataMenuItem.setEnabled(Build.VERSION.SDK_INT < 26);
-
- // Only show Ad Consent if this is the free flavor.
- adConsentMenuItem.setVisible(BuildConfig.FLAVOR.contentEquals("free"));
-
- // Get the shared preferences.
- SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
-
- // Get the dark theme and app bar preferences..
- boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean("display_additional_app_bar_icons", false);
- boolean darkTheme = sharedPreferences.getBoolean("dark_theme", 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 (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);
- }
- }
- }
-
- 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 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 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.EASY_LIST));
- easyPrivacyMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_PRIVACY));
- fanboysAnnoyanceListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST));
- fanboysSocialBlockingListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST));
- ultraPrivacyMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRA_PRIVACY));
- blockAllThirdPartyRequestsMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.THIRD_PARTY_REQUESTS));
- swipeToRefreshMenuItem.setChecked(currentWebView.getSwipeToRefresh());
- 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.EASY_LIST) + " - " + getString(R.string.easylist));
- easyPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASY_PRIVACY) + " - " + 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));
- ultraPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.ULTRA_PRIVACY) + " - " + 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) {
- // Reenter full screen browsing mode if it was interrupted by the options menu. <https://redmine.stoutner.com/issues/389>
- if (inFullScreenBrowsingMode) {
- // Remove the translucent status flag. This is necessary so the root frame layout can fill the entire screen.
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
-
- FrameLayout rootFrameLayout = findViewById(R.id.root_framelayout);
-
- /* Hide the system bars.
- * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
- * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
- * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
- * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
- */
- rootFrameLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
- }
-
- // 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();
- return true;
-
- case R.id.add_or_edit_domain:
- if (currentWebView.getDomainSettingsApplied()) { // Edit the current domain settings.
- // Reapply the domain settings on returning to `MainWebViewActivity`.
- reapplyDomainSettingsOnRestart = true;
-
- // Create an intent to launch the domains activity.
- Intent domainsIntent = new Intent(this, DomainsActivity.class);
-
- // Add the extra information to the intent.
- domainsIntent.putExtra("load_domain", currentWebView.getDomainSettingsDatabaseId());
- domainsIntent.putExtra("close_on_back", true);
- domainsIntent.putExtra("current_url", currentWebView.getUrl());
-
- // Get the current certificate.
- SslCertificate sslCertificate = currentWebView.getCertificate();
-
- // Check to see if the SSL certificate is populated.
- if (sslCertificate != null) {
- // Extract the certificate to strings.
- String issuedToCName = sslCertificate.getIssuedTo().getCName();
- String issuedToOName = sslCertificate.getIssuedTo().getOName();
- String issuedToUName = sslCertificate.getIssuedTo().getUName();
- String issuedByCName = sslCertificate.getIssuedBy().getCName();
- String issuedByOName = sslCertificate.getIssuedBy().getOName();
- String issuedByUName = sslCertificate.getIssuedBy().getUName();
- long startDateLong = sslCertificate.getValidNotBeforeDate().getTime();
- long endDateLong = sslCertificate.getValidNotAfterDate().getTime();
-
- // Add the certificate to the intent.
- domainsIntent.putExtra("ssl_issued_to_cname", issuedToCName);
- domainsIntent.putExtra("ssl_issued_to_oname", issuedToOName);
- domainsIntent.putExtra("ssl_issued_to_uname", issuedToUName);
- domainsIntent.putExtra("ssl_issued_by_cname", issuedByCName);
- domainsIntent.putExtra("ssl_issued_by_oname", issuedByOName);
- domainsIntent.putExtra("ssl_issued_by_uname", issuedByUName);
- domainsIntent.putExtra("ssl_start_date", startDateLong);
- domainsIntent.putExtra("ssl_end_date", endDateLong);
- }
-
- // Check to see if the current IP addresses have been received.
- if (currentWebView.hasCurrentIpAddresses()) {
- // Add the current IP addresses to the intent.
- domainsIntent.putExtra("current_ip_addresses", currentWebView.getCurrentIpAddresses());
- }
-
- // Make it so.
- startActivity(domainsIntent);
- } else { // Add a new domain.
- // Apply the new domain settings on returning to `MainWebViewActivity`.
- reapplyDomainSettingsOnRestart = true;