+ // Launch as a new task so that the download manager and Privacy Browser show as separate windows in the recent tasks list.
+ defaultDownloadManagerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Make it so.
+ startActivity(defaultDownloadManagerIntent);
+ } catch (Exception defaultDownloadManagerException) {
+ // Try a generic file manager.
+ try {
+ // Create a generic file manager intent.
+ Intent genericFileManagerIntent = new Intent(Intent.ACTION_VIEW);
+
+ // Open the download directory.
+ genericFileManagerIntent.setDataAndType(Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()), DocumentsContract.Document.MIME_TYPE_DIR);
+
+ // Launch as a new task so that the file manager and Privacy Browser show as separate windows in the recent tasks list.
+ genericFileManagerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Make it so.
+ startActivity(genericFileManagerIntent);
+ } catch (Exception genericFileManagerException) {
+ // Try an alternate file manager.
+ try {
+ // Create an alternate file manager intent.
+ Intent alternateFileManagerIntent = new Intent(Intent.ACTION_VIEW);
+
+ // Open the download directory.
+ alternateFileManagerIntent.setDataAndType(Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()), "resource/folder");
+
+ // Launch as a new task so that the file manager and Privacy Browser show as separate windows in the recent tasks list.
+ alternateFileManagerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Open the alternate file manager.
+ startActivity(alternateFileManagerIntent);
+ } catch (Exception alternateFileManagerException) {
+ // Display a snackbar.
+ Snackbar.make(currentWebView, R.string.no_file_manager_detected, Snackbar.LENGTH_INDEFINITE).show();
+ }
+ }
+ }
+ } else if (menuItemId == R.id.domains) { // Domains.
+ // Set the flag to reapply the domain settings on restart when returning from Domain Settings.
+ reapplyDomainSettingsOnRestart = true;
+
+ // Launch the domains activity.
+ Intent domainsIntent = new Intent(this, DomainsActivity.class);
+
+ // Add the extra information to the intent.
+ 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 if (menuItemId == R.id.settings) { // Settings.
+ // Set the flag to reapply app settings on restart when returning from Settings.
+ reapplyAppSettingsOnRestart = true;
+
+ // Set the flag to reapply the domain settings on restart when returning from Settings.
+ reapplyDomainSettingsOnRestart = true;
+
+ // Launch the settings activity.
+ Intent settingsIntent = new Intent(this, SettingsActivity.class);
+ startActivity(settingsIntent);
+ } else if (menuItemId == R.id.import_export) { // Import/Export.
+ // Create an intent to launch the import/export activity.
+ Intent importExportIntent = new Intent(this, ImportExportActivity.class);
+
+ // Make it so.
+ startActivity(importExportIntent);
+ } else if (menuItemId == R.id.logcat) { // Logcat.
+ // Create an intent to launch the logcat activity.
+ Intent logcatIntent = new Intent(this, LogcatActivity.class);
+
+ // Make it so.
+ startActivity(logcatIntent);
+ } else if (menuItemId == R.id.guide) { // Guide.
+ // Create an intent to launch the guide activity.
+ Intent guideIntent = new Intent(this, GuideActivity.class);
+
+ // Make it so.
+ startActivity(guideIntent);
+ } else if (menuItemId == R.id.about) { // About
+ // Create an intent to launch the about activity.
+ Intent aboutIntent = new Intent(this, AboutActivity.class);
+
+ // Create a string array for the blocklist versions.
+ String[] blocklistVersions = new String[]{easyList.get(0).get(0)[0], easyPrivacy.get(0).get(0)[0], fanboysAnnoyanceList.get(0).get(0)[0], fanboysSocialList.get(0).get(0)[0],
+ ultraList.get(0).get(0)[0], ultraPrivacy.get(0).get(0)[0]};
+
+ // Add the blocklist versions to the intent.
+ aboutIntent.putExtra(AboutActivity.BLOCKLIST_VERSIONS, blocklistVersions);
+
+ // Make it so.
+ startActivity(aboutIntent);
+ }
+
+ // Close the navigation drawer.
+ drawerLayout.closeDrawer(GravityCompat.START);
+ return true;
+ }
+
+ @Override
+ public void onPostCreate(Bundle savedInstanceState) {
+ // Run the default commands.
+ super.onPostCreate(savedInstanceState);
+
+ // Sync the state of the DrawerToggle after the default `onRestoreInstanceState()` has finished. This creates the navigation drawer icon.
+ actionBarDrawerToggle.syncState();
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ // Get the hit test result.
+ final WebView.HitTestResult hitTestResult = currentWebView.getHitTestResult();
+
+ // Define the URL strings.
+ final String imageUrl;
+ final String linkUrl;
+
+ // Get handles for the system managers.
+ final ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
+
+ // Remove the lint errors below that the clipboard manager might be null.
+ assert clipboardManager != null;
+
+ // Process the link according to the type.
+ switch (hitTestResult.getType()) {
+ // `SRC_ANCHOR_TYPE` is a link.
+ case WebView.HitTestResult.SRC_ANCHOR_TYPE:
+ // Get the target URL.
+ linkUrl = hitTestResult.getExtra();
+
+ // Set the target URL as the title of the `ContextMenu`.
+ menu.setHeaderTitle(linkUrl);
+
+ // Add an Open in New Tab entry.
+ menu.add(R.string.open_in_new_tab).setOnMenuItemClickListener((MenuItem item) -> {
+ // Load the link URL in a new tab and move to it.
+ addNewTab(linkUrl, true);
+
+ // Consume the event.
+ return true;
+ });
+
+ // Add an Open in Background entry.
+ menu.add(R.string.open_in_background).setOnMenuItemClickListener((MenuItem item) -> {
+ // Load the link URL in a new tab but do not move to it.
+ addNewTab(linkUrl, false);
+
+ // Consume the event.
+ return true;
+ });
+
+ // Add an Open with App entry.
+ menu.add(R.string.open_with_app).setOnMenuItemClickListener((MenuItem item) -> {
+ openWithApp(linkUrl);
+
+ // Consume the event.
+ return true;
+ });
+
+ // Add an Open with Browser entry.
+ menu.add(R.string.open_with_browser).setOnMenuItemClickListener((MenuItem item) -> {
+ openWithBrowser(linkUrl);
+
+ // Consume the event.
+ return true;
+ });
+
+ // Add a Copy URL entry.
+ menu.add(R.string.copy_url).setOnMenuItemClickListener((MenuItem item) -> {
+ // Save the link URL in a `ClipData`.
+ ClipData srcAnchorTypeClipData = ClipData.newPlainText(getString(R.string.url), linkUrl);
+
+ // Set the `ClipData` as the clipboard's primary clip.
+ clipboardManager.setPrimaryClip(srcAnchorTypeClipData);
+
+ // Consume the event.
+ return true;
+ });
+
+ // Add a Save URL entry.
+ menu.add(R.string.save_url).setOnMenuItemClickListener((MenuItem item) -> {
+ // Check the download preference.
+ if (downloadWithExternalApp) { // Download with an external app.
+ downloadUrlWithExternalApp(linkUrl);
+ } 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(linkUrl);
+ }
+
+ // Consume the event.
+ return true;
+ });
+
+ // Add an empty Cancel entry, which by default closes the context menu.
+ menu.add(R.string.cancel);