private ForegroundColorSpan initialGrayColorSpan;
private ForegroundColorSpan finalGrayColorSpan;
+ // The drawer header padding variables are used in `onCreate()` and `onConfigurationChanged()`.
+ private int drawerHeaderPaddingLeftAndRight;
+ private int drawerHeaderPaddingTop;
+ private int drawerHeaderPaddingBottom;
+
// `sslErrorHandler` is used in `onCreate()`, `onSslErrorCancel()`, and `onSslErrorProceed`.
private SslErrorHandler sslErrorHandler;
float screenDensity = resources.getDisplayMetrics().density;
// Calculate the drawer header padding. This is used to move the text in the drawer headers below any cutouts.
- int drawerHeaderPaddingLeftAndRight = (int) (15 * screenDensity);
- int drawerHeaderPaddingTop = statusBarPixelSize + (int) (4 * screenDensity);
- int drawerHeaderPaddingBottom = (int) (8 * screenDensity);
+ drawerHeaderPaddingLeftAndRight = (int) (15 * screenDensity);
+ drawerHeaderPaddingTop = statusBarPixelSize + (int) (4 * screenDensity);
+ drawerHeaderPaddingBottom = (int) (8 * screenDensity);
- // The drawer listener is used to update the navigation menu.
+ // The drawer listener is used to update the navigation menu.`
drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
// Setup a runnable to display `mainWebView` after a delay to allow the CSS to be applied.
Runnable displayWebViewRunnable = () -> {
- // Only display `mainWebView` if the progress bar is one. This prevents the display of the `WebView` while it is still loading.
+ // Only display `mainWebView` if the progress bar is gone. This prevents the display of the `WebView` while it is still loading.
if (progressBar.getVisibility() == View.GONE) {
mainWebView.setVisibility(View.VISIBLE);
}
// Check to see if Privacy Browser is waiting on Orbot.
if (!waitingForOrbot) { // We are not waiting on Orbot, so we need to process the URL.
- // We need to update `formattedUrlString` at the beginning of the load, so that if the user toggles JavaScript during the load the new website is reloaded.
+ // The formatted URL string must be updated at the beginning of the load, so that if the user toggles JavaScript during the load the new website is reloaded.
formattedUrlString = url;
// Display the formatted URL text.
// Apply the domain settings. This clears any settings from the previous domain.
applyDomainSettings(formattedUrlString, true, false);
} else { // `WebView` has loaded a webpage.
- // Set `formattedUrlString`.
- formattedUrlString = url;
+ // Set the formatted URL string. Getting the URL from the WebView instead of using the one provided by `onPageFinished` makes websites like YouTube function correctly.
+ formattedUrlString = mainWebView.getUrl();
- // Only update `urlTextBox` if the user is not typing in it.
+ // Only update the URL text box if the user is not typing in it.
if (!urlTextBox.hasFocus()) {
// Display the formatted URL text.
urlTextBox.setText(formattedUrlString);
printManager.print(getString(R.string.privacy_browser_web_page), printDocumentAdapter, null);
return true;
+ case R.id.find_on_page:
+ // Hide the URL app bar.
+ supportAppBar.setVisibility(View.GONE);
+
+ // Show the Find on Page `RelativeLayout`.
+ findOnPageLinearLayout.setVisibility(View.VISIBLE);
+
+ // Display the keyboard. We have to 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 `findOnPageEditText`.
+ findOnPageEditText.requestFocus();
+
+ // Display the keyboard. `0` sets no input flags.
+ inputMethodManager.showSoftInput(findOnPageEditText, 0);
+ }, 200);
+ return true;
+
+ case R.id.add_to_homescreen:
+ // Show the alert dialog.
+ AppCompatDialogFragment createHomeScreenShortcutDialogFragment = new CreateHomeScreenShortcutDialog();
+ createHomeScreenShortcutDialogFragment.show(getSupportFragmentManager(), getString(R.string.create_shortcut));
+
+ //Everything else will be handled by the alert dialog and the associated listener below.
+ return true;
+
case R.id.view_source:
// Launch the View Source activity.
Intent viewSourceIntent = new Intent(this, ViewSourceActivity.class);
startActivity(viewSourceIntent);
return true;
- case R.id.proxy_through_orbot:
- // Toggle the proxy through Orbot variable.
- proxyThroughOrbot = !proxyThroughOrbot;
-
- // Apply the proxy through Orbot settings.
- applyProxyThroughOrbot(true);
- return true;
-
- case R.id.share:
+ case R.id.share_url:
// Setup the share string.
String shareString = webViewTitle + " – " + urlTextBox.getText().toString();
shareIntent.setType("text/plain");
// Make it so.
- startActivity(Intent.createChooser(shareIntent, "Share URL"));
+ startActivity(Intent.createChooser(shareIntent, getString(R.string.share_url)));
return true;
- case R.id.find_on_page:
- // Hide the URL app bar.
- supportAppBar.setVisibility(View.GONE);
+ case R.id.open_with_app:
+ // Create the open with intent with `ACTION_VIEW`.
+ Intent openWithAppIntent = new Intent(Intent.ACTION_VIEW);
- // Show the Find on Page `RelativeLayout`.
- findOnPageLinearLayout.setVisibility(View.VISIBLE);
+ // Set the URI but not the MIME type. This should open all available apps.
+ openWithAppIntent.setData(Uri.parse(formattedUrlString));
- // Display the keyboard. We have to 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 `findOnPageEditText`.
- findOnPageEditText.requestFocus();
+ // Flag the intent to open in a new task.
+ openWithAppIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- // Display the keyboard. `0` sets no input flags.
- inputMethodManager.showSoftInput(findOnPageEditText, 0);
- }, 200);
+ // Show the chooser.
+ startActivity(Intent.createChooser(openWithAppIntent, getString(R.string.open_with)));
return true;
- case R.id.add_to_homescreen:
- // Show the `CreateHomeScreenShortcutDialog` `AlertDialog` and name this instance `R.string.create_shortcut`.
- AppCompatDialogFragment createHomeScreenShortcutDialogFragment = new CreateHomeScreenShortcutDialog();
- createHomeScreenShortcutDialogFragment.show(getSupportFragmentManager(), getString(R.string.create_shortcut));
+ case R.id.open_with_browser:
+ // Create the open with intent with `ACTION_VIEW`.
+ Intent openWithBrowserIntent = new Intent(Intent.ACTION_VIEW);
+
+ // Set the URI and the MIME type. `"text/html"` should load browser options.
+ openWithBrowserIntent.setDataAndType(Uri.parse(formattedUrlString), "text/html");
+
+ // Flag the intent to open in a new task.
+ openWithBrowserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Show the chooser.
+ startActivity(Intent.createChooser(openWithBrowserIntent, getString(R.string.open_with)));
+ return true;
+
+ case R.id.proxy_through_orbot:
+ // Toggle the proxy through Orbot variable.
+ proxyThroughOrbot = !proxyThroughOrbot;
- //Everything else will be handled by `CreateHomeScreenShortcutDialog` and the associated listener below.
+ // Apply the proxy through Orbot settings.
+ applyProxyThroughOrbot(true);
return true;
case R.id.refresh:
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- // Reload the ad for the free flavor if we not in full screen mode.
+ // 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));
// Create a download intent. Not specifying the action type will display the maximum number of options.
Intent downloadIntent = new Intent();
- // Set the URI and the mime type. `"*/*"` will display the maximum number of options.
+ // Set the URI and the MIME type. Specifying `text/html` displays a good number of options.
downloadIntent.setDataAndType(Uri.parse(url), "text/html");
// Flag the intent to open in a new task.