-/**
+/*
* Copyright 2015-2017 Soren Stoutner <soren@stoutner.com>.
*
* Download cookie code contributed 2017 Hendrik Knackstedt. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
import android.annotation.SuppressLint;
import android.app.DialogFragment;
import android.app.DownloadManager;
+import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Bitmap;
// `sslCertificate` is public static so it can be accessed from `ViewSslCertificate`. It is also used in `onCreate()`.
public static SslCertificate sslCertificate;
+ // `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`. It is also used in `onCreate()`.
+ public static String orbotStatus;
+
// `drawerLayout` is used in `onCreate()`, `onNewIntent()`, and `onBackPressed()`.
private DrawerLayout drawerLayout;
// `fullScreenBrowsingModeEnabled` is used in `onCreate()` and `applySettings()`.
private boolean fullScreenBrowsingModeEnabled;
- // `inFullScreenBrowsingMode` is used in `onCreate()` and `applySettings()`.
+ // `inFullScreenBrowsingMode` is used in `onCreate()`, `onConfigurationChanged()`, and `applySettings()`.
private boolean inFullScreenBrowsingMode;
// `hideSystemBarsOnFullscreen` is used in `onCreate()` and `applySettings()`.
// `translucentNavigationBarOnFullscreen` is used in `onCreate()` and `applySettings()`.
private boolean translucentNavigationBarOnFullscreen;
+ // `proxyThroughOrbot` is used in `onCreate()` and `applySettings()`
+ private boolean proxyThroughOrbot;
+
+ // `pendingUrl` is used in `onCreate()` and `applySettings()`
+ private static String pendingUrl;
+
+ // `waitingForOrbotData` is used in `onCreate()` and `applySettings()`.
+ private String waitingForOrbotHTMLString;
+
// `findOnPageLinearLayout` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
private LinearLayout findOnPageLinearLayout;
}
});
+ // Set `waitingForOrbotHTMLString`.
+ waitingForOrbotHTMLString = "<html><body><br/><center><h1>" + getString(R.string.waiting_for_orbot) + "</h1></center></body></html>";
+
+ // Initialize `pendingUrl`.
+ pendingUrl = "";
+
+ // Set the initial Orbot status.
+ orbotStatus = "unknown";
+
+ // Create an Orbot status `BroadcastReceiver`.
+ BroadcastReceiver orbotStatusBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Store the content of the status message in `orbotStatus`.
+ orbotStatus = intent.getStringExtra("org.torproject.android.intent.extra.STATUS");
+
+ // If we are waiting on `pendingUrl`, load it now that Orbot is connected.
+ if (orbotStatus.equals("ON") && !pendingUrl.isEmpty()) {
+
+ // Wait 500 milliseconds, because Orbot isn't really ready yet.
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException exception) {
+ // Do nothing.
+ }
+
+ // Copy `pendingUrl` to `formattedUrlString` and reset `pendingUrl` to be empty.
+ formattedUrlString = pendingUrl;
+ pendingUrl = "";
+
+ // Load `formattedUrlString
+ mainWebView.loadUrl(formattedUrlString, customHeaders);
+ }
+ }
+ };
+
+ // Register `orbotStatusBroadcastReceiver` on `this` context.
+ this.registerReceiver(orbotStatusBroadcastReceiver, new IntentFilter("org.torproject.android.intent.action.STATUS"));
+
// Get handles for views that need to be accessed.
drawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout);
rootCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.root_coordinatorlayout);
// Update the URL in urlTextBox when the page starts to load.
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
- // 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.
- formattedUrlString = url;
+ // Check to see if we are waiting on Orbot.
+ if (pendingUrl.isEmpty()) { // 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.
+ formattedUrlString = url;
- // Display the loading URL is the URL text box.
- urlTextBox.setText(url);
+ // Display the loading URL is the URL text box.
+ urlTextBox.setText(url);
+ }
}
// Update formattedUrlString and urlTextBox. It is necessary to do this after the page finishes loading because the final URL can change during load.
@Override
public void onPageFinished(WebView view, String url) {
- formattedUrlString = url;
+ // Check to see if we are waiting on Orbot.
+ if (pendingUrl.isEmpty()) { // we are not waiting on Orbot, so we need to process the URL.
+ formattedUrlString = url;
- // Only update urlTextBox if the user is not typing in it.
- if (!urlTextBox.hasFocus()) {
- urlTextBox.setText(formattedUrlString);
- }
+ // Only update urlTextBox if the user is not typing in it.
+ if (!urlTextBox.hasFocus()) {
+ urlTextBox.setText(formattedUrlString);
+ }
- // Store the SSL certificate so it can be accessed from `ViewSslCertificate`.
- sslCertificate = mainWebView.getCertificate();
+ // Store the SSL certificate so it can be accessed from `ViewSslCertificate`.
+ sslCertificate = mainWebView.getCertificate();
+ }
}
// Handle SSL Certificate errors.
// Initialize the default preference values the first time the program is run. `this` is the context. `false` keeps this command from resetting any current preferences back to default.
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
- // Apply the settings from the shared preferences.
- applySettings();
-
// Get the intent information that started the app.
final Intent intent = getIntent();
formattedUrlString = intentUriData.toString();
}
- // If formattedUrlString is null assign the homepage to it.
- if (formattedUrlString == null) {
- formattedUrlString = homepage;
- }
+ // Initialize `inFullScreenBrowsingMode`, which is always false at this point because Privacy Browser never starts in full screen browsing mode.
+ inFullScreenBrowsingMode = false;
- // Load the initial website.
- mainWebView.loadUrl(formattedUrlString, customHeaders);
+ // Initialize AdView for the free flavor.
+ adView = findViewById(R.id.adView);
+
+ // Apply the settings from the shared preferences.
+ applySettings();
+
+ // Load `formattedUrlString` if we are not proxying through Orbot and waiting for Orbot to connect.
+ if (!(proxyThroughOrbot && !orbotStatus.equals("ON"))) {
+ mainWebView.loadUrl(formattedUrlString, customHeaders);
+ }
// If the favorite icon is null, load the default.
if (favoriteIcon == null) {
BitmapDrawable favoriteIconBitmapDrawable = (BitmapDrawable) favoriteIconDrawable;
favoriteIcon = favoriteIconBitmapDrawable.getBitmap();
}
-
- // Initialize `inFullScreenBrowsingMode`, which is always false at this point because Privacy Browser never starts in full screen browsing mode.
- inFullScreenBrowsingMode = false;
-
- // Initialize AdView for the free flavor and request an ad. If this is not the free flavor BannerAd.requestAd() does nothing.
- adView = findViewById(R.id.adView);
- BannerAd.requestAd(adView);
}
startActivity(settingsIntent);
break;
- /*
case R.id.domains:
// Launch `DomainsList`.
Intent domainsIntent = new Intent(this, DomainsList.class);
startActivity(domainsIntent);
break;
- */
case R.id.guide:
// Launch `Guide`.
super.onConfigurationChanged(newConfig);
// Reload the ad for the free flavor if we are not in full screen mode.
- if (BuildConfig.FLAVOR.contentEquals("free") && adView.isShown() && !fullScreenVideoFrameLayout.isShown()) {
+ if (BuildConfig.FLAVOR.contentEquals("free") && !inFullScreenBrowsingMode) {
// Reload the ad.
BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
swipeToRefreshEnabled = sharedPreferences.getBoolean("swipe_to_refresh_enabled", false);
adBlockerEnabled = sharedPreferences.getBoolean("block_ads", true);
boolean doNotTrackEnabled = sharedPreferences.getBoolean("do_not_track", false);
- boolean proxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
+ proxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
fullScreenBrowsingModeEnabled = sharedPreferences.getBoolean("enable_full_screen_browsing_mode", false);
hideSystemBarsOnFullscreen = sharedPreferences.getBoolean("hide_system_bars", false);
translucentNavigationBarOnFullscreen = sharedPreferences.getBoolean("translucent_navigation_bar", true);
// Set `torHomepageString` as `homepage`.
homepage = torHomepageString;
+ // If formattedUrlString is null assign the homepage to it.
+ if (formattedUrlString == null) {
+ formattedUrlString = homepage;
+ }
+
// Set JavaScript disabled search.
if (torJavaScriptDisabledSearchString.equals("Custom URL")) { // Get the custom URL string.
javaScriptDisabledSearchURL = torJavaScriptDisabledSearchCustomURLString;
// Set the proxy. `this` refers to the current activity where an `AlertDialog` might be displayed.
OrbotProxyHelper.setProxy(getApplicationContext(), this, "localhost", "8118");
+
+ // Display a message to the user if we are waiting on Orbot.
+ if (!orbotStatus.equals("ON")) {
+ // Save `formattedUrlString` in `pendingUrl`.
+ pendingUrl = formattedUrlString;
+
+ // Load a waiting page. `null` specifies no encoding, which defaults to ASCII.
+ mainWebView.loadData(waitingForOrbotHTMLString, "text/html", null);
+ }
} else { // Set the non-Tor options.
// Set `homepageString` as `homepage`.
homepage = homepageString;
+ // If formattedUrlString is null assign the homepage to it.
+ if (formattedUrlString == null) {
+ formattedUrlString = homepage;
+ }
+
// Set JavaScript disabled search.
if (javaScriptDisabledSearchString.equals("Custom URL")) { // Get the custom URL string.
javaScriptDisabledSearchURL = javaScriptDisabledSearchCustomURLString;
// Reset the proxy to default. The host is `""` and the port is `"0"`.
OrbotProxyHelper.setProxy(getApplicationContext(), this, "", "0");
+
+ // Reset `pendingUrl` if we are currently waiting for Orbot to connect.
+ if (!pendingUrl.isEmpty()) {
+ formattedUrlString = pendingUrl;
+ pendingUrl = "";
+ }
}
// Set swipe to refresh.
customHeaders.remove("DNT");
}
- // If we are in full screen mode update the `SYSTEM_UI` flags.
- if (inFullScreenBrowsingMode) {
+ // Apply the appropriate full screen mode the `SYSTEM_UI` flags.
+ if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) {
if (hideSystemBarsOnFullscreen) { // Hide everything.
// Remove the translucent navigation setting if it is currently flagged.
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
+ } else { // Switch to normal viewing mode.
+ // Reset `inFullScreenBrowsingMode` to `false`.
+ inFullScreenBrowsingMode = false;
+
+ // Show the `appBar`.
+ appBar.show();
+
+ // Show the `BannerAd` in the free flavor.
+ if (BuildConfig.FLAVOR.contentEquals("free")) {
+ // Reload the ad. Because the screen may have rotated, we need to use `reloadAfterRotate`.
+ BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
+
+ // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
+ adView = findViewById(R.id.adView);
+ }
+
+ // Remove the translucent navigation bar flag if it is set.
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+
+ // Add the translucent status flag if it is unset. This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+ // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+ rootCoordinatorLayout.setSystemUiVisibility(0);
+
+ // Constrain `rootCoordinatorLayout` inside the status and navigation bars.
+ rootCoordinatorLayout.setFitsSystemWindows(true);
}
}