+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.wide_viewport) { // Wide viewport.
+ // Toggle the viewport.
+ currentWebView.getSettings().setUseWideViewPort(!currentWebView.getSettings().getUseWideViewPort());
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.display_images) { // Display images.
+ // Toggle the displaying of images.
+ if (currentWebView.getSettings().getLoadsImagesAutomatically()) { // Images are currently loaded automatically.
+ // Disable loading of images.
+ currentWebView.getSettings().setLoadsImagesAutomatically(false);
+
+ // Reload the website to remove existing images.
+ currentWebView.reload();
+ } else { // Images are not currently loaded automatically.
+ // Enable loading of images. Missing images will be loaded without the need for a reload.
+ currentWebView.getSettings().setLoadsImagesAutomatically(true);
+ }
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.dark_webview) { // Dark WebView.
+ // Check to see if dark WebView is supported by this WebView.
+ if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
+ // Toggle the dark WebView setting.
+ if (WebSettingsCompat.getForceDark(currentWebView.getSettings()) == WebSettingsCompat.FORCE_DARK_ON) { // Dark WebView is currently enabled.
+ // Turn off dark WebView.
+ WebSettingsCompat.setForceDark(currentWebView.getSettings(), WebSettingsCompat.FORCE_DARK_OFF);
+ } else { // Dark WebView is currently disabled.
+ // Turn on dark WebView.
+ WebSettingsCompat.setForceDark(currentWebView.getSettings(), WebSettingsCompat.FORCE_DARK_ON);
+ }
+ }
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.find_on_page) { // Find on page.
+ // Get a handle for the views.
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ LinearLayout findOnPageLinearLayout = findViewById(R.id.find_on_page_linearlayout);
+ EditText findOnPageEditText = findViewById(R.id.find_on_page_edittext);
+
+ // Set the minimum height of the find on page linear layout to match the toolbar.
+ findOnPageLinearLayout.setMinimumHeight(toolbar.getHeight());
+
+ // Hide the toolbar.
+ toolbar.setVisibility(View.GONE);
+
+ // Show the find on page linear layout.
+ findOnPageLinearLayout.setVisibility(View.VISIBLE);
+
+ // Display the keyboard. The app must wait 200 ms before running the command to work around a bug in Android.
+ // http://stackoverflow.com/questions/5520085/android-show-softkeyboard-with-showsoftinput-is-not-working
+ findOnPageEditText.postDelayed(() -> {
+ // Set the focus on the find on page edit text.
+ findOnPageEditText.requestFocus();
+
+ // Get a handle for the input method manager.
+ InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ // Remove the lint warning below that the input method manager might be null.
+ assert inputMethodManager != null;
+
+ // Display the keyboard. `0` sets no input flags.
+ inputMethodManager.showSoftInput(findOnPageEditText, 0);
+ }, 200);
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.print) { // Print.
+ // Get a print manager instance.
+ PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
+
+ // Remove the lint error below that print manager might be null.
+ assert printManager != null;
+
+ // Create a print document adapter from the current WebView.
+ PrintDocumentAdapter printDocumentAdapter = currentWebView.createPrintDocumentAdapter(getString(R.string.print));
+
+ // Print the document.
+ printManager.print(getString(R.string.privacy_browser_webpage), printDocumentAdapter, null);
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.save_url) { // Save URL.
+ // Check the download preference.
+ if (downloadWithExternalApp) { // Download with an external app.
+ downloadUrlWithExternalApp(currentWebView.getCurrentUrl());
+ } else { // Handle the download inside of Privacy Browser.
+ // Prepare the save dialog. The dialog will be displayed once the file size and the content disposition have been acquired.
+ new PrepareSaveDialog(this, this, getSupportFragmentManager(), currentWebView.getSettings().getUserAgentString(),
+ currentWebView.getAcceptCookies()).execute(currentWebView.getCurrentUrl());
+ }
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.save_archive) {
+ // Open the file picker with a default file name built from the current domain name.
+ saveWebpageArchiveActivityResultLauncher.launch(currentWebView.getCurrentDomainName() + ".mht");
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.save_image) { // Save image.
+ // Open the file picker with a default file name built from the current domain name.
+ saveWebpageImageActivityResultLauncher.launch(currentWebView.getCurrentDomainName() + ".png");
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.add_to_homescreen) { // Add to homescreen.
+ // Instantiate the create home screen shortcut dialog.
+ DialogFragment createHomeScreenShortcutDialogFragment = CreateHomeScreenShortcutDialog.createDialog(currentWebView.getTitle(), currentWebView.getUrl(),
+ currentWebView.getFavoriteOrDefaultIcon());
+
+ // Show the create home screen shortcut dialog.
+ createHomeScreenShortcutDialogFragment.show(getSupportFragmentManager(), getString(R.string.create_shortcut));
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.view_source) { // View source.
+ // Create an intent to launch the view source activity.
+ Intent viewSourceIntent = new Intent(this, ViewSourceActivity.class);
+
+ // Add the variables to the intent.
+ viewSourceIntent.putExtra(ViewSourceActivityKt.CURRENT_URL, currentWebView.getUrl());
+ viewSourceIntent.putExtra(ViewSourceActivityKt.USER_AGENT, currentWebView.getSettings().getUserAgentString());
+
+ // Make it so.
+ startActivity(viewSourceIntent);
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.share_message) { // Share a message.
+ // Prepare the share string.
+ String shareString = currentWebView.getTitle() + " – " + currentWebView.getUrl();
+
+ // Create the share intent.
+ Intent shareMessageIntent = new Intent(Intent.ACTION_SEND);
+
+ // Add the share string to the intent.
+ shareMessageIntent.putExtra(Intent.EXTRA_TEXT, shareString);
+
+ // Set the MIME type.
+ shareMessageIntent.setType("text/plain");
+
+ // Set the intent to open in a new task.
+ shareMessageIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Make it so.
+ startActivity(Intent.createChooser(shareMessageIntent, getString(R.string.share_message)));
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.share_url) { // Share URL.
+ // Create the share intent.
+ Intent shareUrlIntent = new Intent(Intent.ACTION_SEND);
+
+ // Add the URL to the intent.
+ shareUrlIntent.putExtra(Intent.EXTRA_TEXT, currentWebView.getUrl());
+
+ // Add the title to the intent.
+ shareUrlIntent.putExtra(Intent.EXTRA_SUBJECT, currentWebView.getTitle());
+
+ // Set the MIME type.
+ shareUrlIntent.setType("text/plain");
+
+ // Set the intent to open in a new task.
+ shareUrlIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ //Make it so.
+ startActivity(Intent.createChooser(shareUrlIntent, getString(R.string.share_url)));
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.open_with_app) { // Open with app.
+ // Open the URL with an outside app.
+ openWithApp(currentWebView.getUrl());
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.open_with_browser) { // Open with browser.
+ // Open the URL with an outside browser.
+ openWithBrowser(currentWebView.getUrl());
+
+ // Consume the event.
+ return true;
+ } else if (menuItemId == R.id.add_or_edit_domain) { // Add or edit domain.
+ // Check if domain settings currently exist.
+ 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());
+ domainsIntent.putExtra("current_ip_addresses", currentWebView.getCurrentIpAddresses());
+
+ // 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);
+ }
+
+ // Make it so.
+ startActivity(domainsIntent);
+ } else { // Add a new domain.
+ // Apply the new domain settings on returning to `MainWebViewActivity`.
+ reapplyDomainSettingsOnRestart = true;
+
+ // Get the current domain
+ Uri currentUri = Uri.parse(currentWebView.getUrl());
+ String currentDomain = currentUri.getHost();
+
+ // Create the domain and store the database ID.
+ int newDomainDatabaseId = domainsDatabaseHelper.addDomain(currentDomain);
+
+ // 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", newDomainDatabaseId);
+ domainsIntent.putExtra("close_on_back", true);
+ domainsIntent.putExtra("current_url", currentWebView.getUrl());
+ domainsIntent.putExtra("current_ip_addresses", currentWebView.getCurrentIpAddresses());
+
+ // 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);
+ }
+
+ // Make it so.
+ startActivity(domainsIntent);
+ }
+
+ // Consume the event.
+ return true;
+ } else { // There is no match with the options menu. Pass the event up to the parent method.
+ // Don't consume the event.
+ return super.onOptionsItemSelected(menuItem);
+ }
+ }
+
+ // removeAllCookies is deprecated, but it is required for API < 21.
+ @Override
+ public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
+ // Get a handle for the shared preferences.
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+
+ // Get the menu item ID.
+ int menuItemId = menuItem.getItemId();
+
+ // Run the commands that correspond to the selected menu item.
+ if (menuItemId == R.id.clear_and_exit) { // Clear and exit.
+ // Clear and exit Privacy Browser.
+ clearAndExit();
+ } else if (menuItemId == R.id.home) { // Home.
+ // Load the homepage.
+ loadUrl(currentWebView, sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
+ } else if (menuItemId == R.id.back) { // Back.
+ // Check if the WebView can go back.
+ if (currentWebView.canGoBack()) {
+ // Get the current web back forward list.
+ WebBackForwardList webBackForwardList = currentWebView.copyBackForwardList();
+
+ // Get the previous entry URL.
+ String previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.getCurrentIndex() - 1).getUrl();
+
+ // Apply the domain settings.
+ applyDomainSettings(currentWebView, previousUrl, false, false, false);
+
+ // Load the previous website in the history.
+ currentWebView.goBack();
+ }
+ } else if (menuItemId == R.id.forward) { // Forward.
+ // Check if the WebView can go forward.
+ if (currentWebView.canGoForward()) {
+ // Get the current web back forward list.
+ WebBackForwardList webBackForwardList = currentWebView.copyBackForwardList();
+
+ // Get the next entry URL.
+ String nextUrl = webBackForwardList.getItemAtIndex(webBackForwardList.getCurrentIndex() + 1).getUrl();
+
+ // Apply the domain settings.
+ applyDomainSettings(currentWebView, nextUrl, false, false, false);
+
+ // Load the next website in the history.
+ currentWebView.goForward();
+ }
+ } else if (menuItemId == R.id.history) { // History.
+ // Instantiate the URL history dialog.
+ DialogFragment urlHistoryDialogFragment = UrlHistoryDialog.loadBackForwardList(currentWebView.getWebViewFragmentId());