- // Load the next website in the history.
- currentWebView.goForward();
- }
- break;
-
- case R.id.history:
- // Get the `WebBackForwardList`.
- WebBackForwardList webBackForwardList = currentWebView.copyBackForwardList();
-
- // Show the URL history dialog and name this instance `R.string.history`.
- DialogFragment urlHistoryDialogFragment = UrlHistoryDialog.loadBackForwardList(this, webBackForwardList);
- urlHistoryDialogFragment.show(getSupportFragmentManager(), getString(R.string.history));
- break;
-
- case R.id.requests:
- // Populate the resource requests.
- RequestsActivity.resourceRequests = currentWebView.getResourceRequests();
-
- // Create an intent to launch the Requests activity.
- Intent requestsIntent = new Intent(this, RequestsActivity.class);
-
- // Add the block third-party requests status to the intent.
- requestsIntent.putExtra("block_all_third_party_requests", currentWebView.isBlocklistEnabled(NestedScrollWebView.THIRD_PARTY_REQUESTS));
-
- // Make it so.
- startActivity(requestsIntent);
- break;
-
- case R.id.downloads:
- // Launch the system Download Manager.
- Intent downloadManagerIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
-
- // Launch as a new task so that Download Manager and Privacy Browser show as separate windows in the recent tasks list.
- downloadManagerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- startActivity(downloadManagerIntent);
- break;
-
- case R.id.domains:
- // Set the flag to reapply the domain settings on restart when returning from Domain Settings.
- reapplyDomainSettingsOnRestart = true;
-
- // TODO. Move these to `putExtra`. The certificate can be stored as strings.
- // Store the current SSL certificate and IP addresses in the domains activity.
- DomainsActivity.currentSslCertificate = currentWebView.getCertificate();
- DomainsActivity.currentIpAddresses = currentWebView.getCurrentIpAddresses();
-
- // Launch the domains activity.
- Intent domainsIntent = new Intent(this, DomainsActivity.class);
-
- // Add the extra information to the intent.
- domainsIntent.putExtra("current_url", currentWebView.getUrl());
-
- // Make it so.
- startActivity(domainsIntent);
- break;
-
- case R.id.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);
- break;
-
- case R.id.import_export:
- // Launch the import/export activity.
- Intent importExportIntent = new Intent (this, ImportExportActivity.class);
- startActivity(importExportIntent);
- break;
-
- case R.id.logcat:
- // Launch the logcat activity.
- Intent logcatIntent = new Intent(this, LogcatActivity.class);
- startActivity(logcatIntent);
- break;
-
- case R.id.guide:
- // Launch `GuideActivity`.
- Intent guideIntent = new Intent(this, GuideActivity.class);
- startActivity(guideIntent);
- break;
-
- case R.id.about:
- // Launch `AboutActivity`.
- Intent aboutIntent = new Intent(this, AboutActivity.class);
- startActivity(aboutIntent);
- break;
- }
-
- // Get a handle for the drawer layout.
- DrawerLayout drawerLayout = findViewById(R.id.drawerlayout);
-
- // 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 onConfigurationChanged(Configuration newConfig) {
- // Run the default commands.
- super.onConfigurationChanged(newConfig);
-
- // Get the status bar pixel size.
- int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
- int statusBarPixelSize = getResources().getDimensionPixelSize(statusBarResourceId);
-
- // Get the resource density.
- float screenDensity = getResources().getDisplayMetrics().density;
-
- // Recalculate the drawer header padding.
- drawerHeaderPaddingLeftAndRight = (int) (15 * screenDensity);
- drawerHeaderPaddingTop = statusBarPixelSize + (int) (4 * screenDensity);
- drawerHeaderPaddingBottom = (int) (8 * screenDensity);
-
- // Reload the ad for the free flavor if not in full screen mode.
- if (BuildConfig.FLAVOR.contentEquals("free") && !inFullScreenBrowsingMode) {
- // Reload the ad. The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
- AdHelper.loadAd(findViewById(R.id.adview), getApplicationContext(), getString(R.string.ad_unit_id));
- }
-
- // `invalidateOptionsMenu` should recalculate the number of action buttons from the menu to display on the app bar, but it doesn't because of the this bug:
- // https://code.google.com/p/android/issues/detail?id=20493#c8
- // ActivityCompat.invalidateOptionsMenu(this);
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
- // Store the hit test result.
- final WebView.HitTestResult hitTestResult = currentWebView.getHitTestResult();
-
- // Create the URL strings.
- final String imageUrl;
- final String linkUrl;
-
- // Get handles for the the clipboard and fragment managers.
- final ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
- FragmentManager fragmentManager = getSupportFragmentManager();
-
- // 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 a Load URL entry.
- menu.add(R.string.open_in_new_tab).setOnMenuItemClickListener((MenuItem item) -> {
- // Add a new tab.
- addTab(null);
-
- // Load the URL.
- loadUrl(linkUrl);
- return false;
- });
-
- // Add an Open with App entry.
- menu.add(R.string.open_with_app).setOnMenuItemClickListener((MenuItem item) -> {
- openWithApp(linkUrl);
- return false;
- });
-
- // Add an Open with Browser entry.
- menu.add(R.string.open_with_browser).setOnMenuItemClickListener((MenuItem item) -> {
- openWithBrowser(linkUrl);
- return false;
- });
-
- // 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);
- return false;
- });
-
- // Add a Download URL entry.
- menu.add(R.string.download_url).setOnMenuItemClickListener((MenuItem item) -> {
- // Check if the download should be processed by an external app.
- if (downloadWithExternalApp) { // Download with an external app.
- openUrlWithExternalApp(linkUrl);
- } else { // Download with Android's download manager.
- // Check to see if the storage permission has already been granted.
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { // The storage permission needs to be requested.
- // Store the variables for future use by `onRequestPermissionsResult()`.
- downloadUrl = linkUrl;
- downloadContentDisposition = "none";
- downloadContentLength = -1;
-
- // Show a dialog if the user has previously denied the permission.
- if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { // Show a dialog explaining the request first.
- // Instantiate the download location permission alert dialog and set the download type to DOWNLOAD_FILE.
- DialogFragment downloadLocationPermissionDialogFragment = DownloadLocationPermissionDialog.downloadType(DownloadLocationPermissionDialog.DOWNLOAD_FILE);
-
- // Show the download location permission alert dialog. The permission will be requested when the the dialog is closed.
- downloadLocationPermissionDialogFragment.show(fragmentManager, getString(R.string.download_location));
- } else { // Show the permission request directly.
- // Request the permission. The download dialog will be launched by `onRequestPermissionResult()`.
- ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, DOWNLOAD_FILE_REQUEST_CODE);
- }
- } else { // The storage permission has already been granted.
- // Get a handle for the download file alert dialog.
- DialogFragment downloadFileDialogFragment = DownloadFileDialog.fromUrl(linkUrl, "none", -1);
-
- // Show the download file alert dialog.
- downloadFileDialogFragment.show(fragmentManager, getString(R.string.download));
- }
- }
- return false;
- });
-
- // Add a Cancel entry, which by default closes the context menu.
- menu.add(R.string.cancel);
- break;
-
- case WebView.HitTestResult.EMAIL_TYPE:
- // Get the target URL.
- linkUrl = hitTestResult.getExtra();
-
- // Set the target URL as the title of the `ContextMenu`.
- menu.setHeaderTitle(linkUrl);
-
- // Add a Write Email entry.
- menu.add(R.string.write_email).setOnMenuItemClickListener(item -> {
- // Use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched.
- Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
-
- // Parse the url and set it as the data for the `Intent`.
- emailIntent.setData(Uri.parse("mailto:" + linkUrl));
-
- // `FLAG_ACTIVITY_NEW_TASK` opens the email program in a new task instead as part of Privacy Browser.
- emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- // Make it so.
- startActivity(emailIntent);
- return false;
- });
-
- // Add a Copy Email Address entry.
- menu.add(R.string.copy_email_address).setOnMenuItemClickListener(item -> {
- // Save the email address in a `ClipData`.
- ClipData srcEmailTypeClipData = ClipData.newPlainText(getString(R.string.email_address), linkUrl);
-
- // Set the `ClipData` as the clipboard's primary clip.
- clipboardManager.setPrimaryClip(srcEmailTypeClipData);
- return false;
- });
-
- // Add a `Cancel` entry, which by default closes the `ContextMenu`.
- menu.add(R.string.cancel);
- break;
-
- // `IMAGE_TYPE` is an image.
- case WebView.HitTestResult.IMAGE_TYPE:
- // Get the image URL.
- imageUrl = hitTestResult.getExtra();
-
- // Set the image URL as the title of the `ContextMenu`.
- menu.setHeaderTitle(imageUrl);
-
- // Add a View Image entry.
- menu.add(R.string.view_image).setOnMenuItemClickListener(item -> {
- loadUrl(imageUrl);
- return false;
- });
-
- // Add a Download Image entry.
- menu.add(R.string.download_image).setOnMenuItemClickListener((MenuItem item) -> {
- // Check if the download should be processed by an external app.
- if (downloadWithExternalApp) { // Download with an external app.
- openUrlWithExternalApp(imageUrl);
- } else { // Download with Android's download manager.
- // Check to see if the storage permission has already been granted.
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { // The storage permission needs to be requested.
- // Store the image URL for use by `onRequestPermissionResult()`.
- downloadImageUrl = imageUrl;
-
- // Show a dialog if the user has previously denied the permission.
- if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { // Show a dialog explaining the request first.
- // Instantiate the download location permission alert dialog and set the download type to DOWNLOAD_IMAGE.
- DialogFragment downloadLocationPermissionDialogFragment = DownloadLocationPermissionDialog.downloadType(DownloadLocationPermissionDialog.DOWNLOAD_IMAGE);
-
- // Show the download location permission alert dialog. The permission will be requested when the dialog is closed.
- downloadLocationPermissionDialogFragment.show(fragmentManager, getString(R.string.download_location));
- } else { // Show the permission request directly.
- // Request the permission. The download dialog will be launched by `onRequestPermissionResult().
- ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, DOWNLOAD_IMAGE_REQUEST_CODE);
- }
- } else { // The storage permission has already been granted.
- // Get a handle for the download image alert dialog.
- DialogFragment downloadImageDialogFragment = DownloadImageDialog.imageUrl(imageUrl);
-
- // Show the download image alert dialog.
- downloadImageDialogFragment.show(fragmentManager, getString(R.string.download));
- }
- }
- return false;
- });
-
- // Add a Copy URL entry.
- menu.add(R.string.copy_url).setOnMenuItemClickListener(item -> {
- // Save the image URL in a `ClipData`.
- ClipData srcImageTypeClipData = ClipData.newPlainText(getString(R.string.url), imageUrl);
-
- // Set the `ClipData` as the clipboard's primary clip.
- clipboardManager.setPrimaryClip(srcImageTypeClipData);
- return false;
- });
-
- // Add an Open with App entry.
- menu.add(R.string.open_with_app).setOnMenuItemClickListener((MenuItem item) -> {
- openWithApp(imageUrl);
- return false;
- });
-
- // Add an Open with Browser entry.
- menu.add(R.string.open_with_browser).setOnMenuItemClickListener((MenuItem item) -> {
- openWithBrowser(imageUrl);
- return false;
- });
-
- // Add a `Cancel` entry, which by default closes the `ContextMenu`.
- menu.add(R.string.cancel);
- break;
-
-
- // `SRC_IMAGE_ANCHOR_TYPE` is an image that is also a link.
- case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
- // Get the image URL.
- imageUrl = hitTestResult.getExtra();
-
- // Set the image URL as the title of the `ContextMenu`.
- menu.setHeaderTitle(imageUrl);
-
- // Add a `View Image` entry.
- menu.add(R.string.view_image).setOnMenuItemClickListener(item -> {
- loadUrl(imageUrl);
- return false;
- });
-
- // Add a `Download Image` entry.
- menu.add(R.string.download_image).setOnMenuItemClickListener((MenuItem item) -> {
- // Check if the download should be processed by an external app.
- if (downloadWithExternalApp) { // Download with an external app.
- openUrlWithExternalApp(imageUrl);
- } else { // Download with Android's download manager.
- // Check to see if the storage permission has already been granted.
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { // The storage permission needs to be requested.
- // Store the image URL for use by `onRequestPermissionResult()`.
- downloadImageUrl = imageUrl;
-
- // Show a dialog if the user has previously denied the permission.
- if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { // Show a dialog explaining the request first.
- // Instantiate the download location permission alert dialog and set the download type to DOWNLOAD_IMAGE.
- DialogFragment downloadLocationPermissionDialogFragment = DownloadLocationPermissionDialog.downloadType(DownloadLocationPermissionDialog.DOWNLOAD_IMAGE);
-
- // Show the download location permission alert dialog. The permission will be requested when the dialog is closed.
- downloadLocationPermissionDialogFragment.show(fragmentManager, getString(R.string.download_location));
- } else { // Show the permission request directly.
- // Request the permission. The download dialog will be launched by `onRequestPermissionResult().
- ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, DOWNLOAD_IMAGE_REQUEST_CODE);
- }
- } else { // The storage permission has already been granted.
- // Get a handle for the download image alert dialog.
- DialogFragment downloadImageDialogFragment = DownloadImageDialog.imageUrl(imageUrl);
-
- // Show the download image alert dialog.
- downloadImageDialogFragment.show(fragmentManager, getString(R.string.download));
- }
- }
- return false;
- });
-
- // Add a `Copy URL` entry.
- menu.add(R.string.copy_url).setOnMenuItemClickListener(item -> {
- // Save the image URL in a `ClipData`.
- ClipData srcImageAnchorTypeClipData = ClipData.newPlainText(getString(R.string.url), imageUrl);
-
- // Set the `ClipData` as the clipboard's primary clip.
- clipboardManager.setPrimaryClip(srcImageAnchorTypeClipData);
- return false;
- });
-
- // Add an Open with App entry.
- menu.add(R.string.open_with_app).setOnMenuItemClickListener((MenuItem item) -> {
- openWithApp(imageUrl);
- return false;
- });
-
- // Add an Open with Browser entry.
- menu.add(R.string.open_with_browser).setOnMenuItemClickListener((MenuItem item) -> {
- openWithBrowser(imageUrl);
- return false;