/*
- * Copyright 2015-2017 Soren Stoutner <soren@stoutner.com>.
+ * Copyright © 2015-2017 Soren Stoutner <soren@stoutner.com>.
*
* Download cookie code contributed 2017 Hendrik Knackstedt. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
*
// 'homepage' is used in `onCreate()`, `onNavigationItemSelected()`, and `applyAppSettings()`.
private String homepage;
- // `javaScriptDisabledSearchURL` is used in `loadURLFromTextBox()` and `applyAppSettings()`.
- private String javaScriptDisabledSearchURL;
-
- // `javaScriptEnabledSearchURL` is used in `loadURLFromTextBox()` and `applyAppSettings()`.
- private String javaScriptEnabledSearchURL;
+ // `searchURL` is used in `loadURLFromTextBox()` and `applyAppSettings()`.
+ private String searchURL;
// `adBlockerEnabled` is used in `onCreate()` and `applyAppSettings()`.
private boolean adBlockerEnabled;
// `translucentNavigationBarOnFullscreen` is used in `onCreate()` and `applyAppSettings()`.
private boolean translucentNavigationBarOnFullscreen;
- // `proxyThroughOrbot` is used in `onCreate()` and `applyAppSettings()`.
- private boolean proxyThroughOrbot;
-
// `currentDomainName` is used in `onCreate(), `onNavigationItemSelected()`, and `applyDomainSettings()`.
private String currentDomainName;
- // `pendingUrl` is used in `onCreate()` and `applyAppSettings()`.
- private static String pendingUrl;
+ // `waitingForOrbot` is used in `onCreate()` and `applyAppSettings()`.
+ private boolean waitingForOrbot;
// `waitingForOrbotData` is used in `onCreate()` and `applyAppSettings()`.
private String waitingForOrbotHTMLString;
// Set `waitingForOrbotHTMLString`.
waitingForOrbotHTMLString = "<html><body><br/><center><h1>" + getString(R.string.waiting_for_orbot) + "</h1></center></body></html>";
- // Initialize `currentDomainName`, `pendingUrl`, and `orbotStatus`.
+ // Initialize `currentDomainName`, `orbotStatus`, and `waitingForOrbot`.
currentDomainName = "";
- pendingUrl = "";
orbotStatus = "unknown";
+ waitingForOrbot = false;
// Create an Orbot status `BroadcastReceiver`.
BroadcastReceiver orbotStatusBroadcastReceiver = new BroadcastReceiver() {
// 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 = "";
+ // If we are waiting on Orbot, load the website now that Orbot is connected.
+ if (orbotStatus.equals("ON") && waitingForOrbot) {
+ // Reset `waitingForOrbot`.
+ waitingForOrbot = false;
// Load `formattedUrlString
loadUrl(formattedUrlString);
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
- // Use an external email program if the link begins with `mailto:`.
- if (url.startsWith("mailto:")) {
+ if (url.startsWith("mailto:")) { // Load the URL in an external email program because it begins with `mailto:`.
// We use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched.
Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
// Make it so.
startActivity(emailIntent);
+
+ // Returning `true` indicates the application is handling the URL.
return true;
} else { // Load the URL in Privacy Browser.
- loadUrl(url);
- return true;
+ // Apply the domain settings for the new URL.
+ applyDomainSettings(url);
+
+ // Returning `false` causes the current `WebView` to handle the URL and prevents it from adding redirects to the history list.
+ return false;
}
}
webViewTitle = getString(R.string.no_title);
// 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.
+ 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.
formattedUrlString = url;
privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/cache");
// Delete the `app_webview` folder, which contains an additional `WebView` cache. See `https://code.google.com/p/android/issues/detail?id=233826&thanks=233826&ts=1486670530`.
- privacyBrowserRuntime.exec("rm -rf " + privacyBrowserRuntime + "/app_webview");
+ privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview");
} catch (IOException e) {
// Do nothing if an error is thrown.
}
}
// Update `urlTextBox` and apply domain settings if not waiting on Orbot.
- if (pendingUrl.isEmpty()) { // We are not waiting on Orbot, so we need to process the URL.
+ if (!waitingForOrbot) {
// Check to see if `WebView` has set `url` to be `about:blank`.
if (url.equals("about:blank")) { // `WebView` is blank, so `formattedUrlString` should be `""` and `urlTextBox` should display a hint.
// Set `formattedUrlString` to `""`.
// Hide zoom controls.
mainWebView.getSettings().setDisplayZoomControls(false);
+ // Set `mainWebView` to use a wide viewport. Otherwise, some web pages will be scrunched and some content will render outside the screen.
+ mainWebView.getSettings().setUseWideViewPort(true);
+
+ // Set `mainWebView` to load in overview mode (zoomed out to the maximum width).
+ mainWebView.getSettings().setLoadWithOverviewMode(true);
+
// Initialize cookieManager.
cookieManager = CookieManager.getInstance();
// Initialize `webViewTitle`.
webViewTitle = getString(R.string.no_title);
- // Apply the app settings from the shared preferences.
- applyAppSettings();
-
// Initialize `favoriteIconBitmap`. We have to use `ContextCompat` until API >= 21.
Drawable favoriteIconDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.world);
BitmapDrawable favoriteIconBitmapDrawable = (BitmapDrawable) favoriteIconDrawable;
// If the favorite icon is null, load the default.
if (favoriteIconBitmap == null) {
favoriteIconBitmap = favoriteIconDefaultBitmap;
+ }
+
+ // Apply the app settings from the shared preferences.
+ applyAppSettings();
- // Load `formattedUrlString` if we are not proxying through Orbot and waiting for Orbot to connect.
- if (!(proxyThroughOrbot && !orbotStatus.equals("ON"))) {
+ // Load `formattedUrlString` if we are not waiting for Orbot to connect.
+ if (!waitingForOrbot) {
loadUrl(formattedUrlString);
}
- }
}
// Prepare the font size title and current size menu item.
switch (fontSize) {
+ case 25:
+ fontSizeTitle = getResources().getString(R.string.font_size) + " - " + getResources().getString(R.string.twenty_five_percent);
+ selectedFontSizeMenuItem = menu.findItem(R.id.fontSizeTwentyFivePercent);
+ break;
+
case 50:
fontSizeTitle = getResources().getString(R.string.font_size) + " - " + getResources().getString(R.string.fifty_percent);
selectedFontSizeMenuItem = menu.findItem(R.id.fontSizeFiftyPercent);
Snackbar.make(findViewById(R.id.main_webview), R.string.form_data_deleted, Snackbar.LENGTH_SHORT).show();
return true;
+ case R.id.fontSizeTwentyFivePercent:
+ mainWebView.getSettings().setTextZoom(25);
+ return true;
+
case R.id.fontSizeFiftyPercent:
mainWebView.getSettings().setTextZoom(50);
return true;
return true;
case R.id.share:
+ // Setup the share string.
+ String shareString;
+ if (webViewTitle != null) {
+ shareString = webViewTitle + " – " + urlTextBox.getText().toString();
+ } else {
+ shareString = urlTextBox.getText().toString();
+ }
+
+ // Create the share intent.
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
- shareIntent.putExtra(Intent.EXTRA_TEXT, urlTextBox.getText().toString());
+ shareIntent.putExtra(Intent.EXTRA_TEXT, shareString);
shareIntent.setType("text/plain");
+
+ // Make it so.
startActivity(Intent.createChooser(shareIntent, "Share URL"));
return true;
privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/cache");
// Delete the `app_webview` folder, which contains an additional `WebView` cache. See `https://code.google.com/p/android/issues/detail?id=233826&thanks=233826&ts=1486670530`.
- privacyBrowserRuntime.exec("rm -rf " + privacyBrowserRuntime + "/app_webview");
+ privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview");
} catch (IOException e) {
// Do nothing if an error is thrown.
}
}
@Override
- public void onResume() {
+ public void onResume() { // `onResume()` also runs every time the app starts after `onCreate()` and `onStart()`.
super.onResume();
// Resume JavaScript (if enabled).
String unformattedUrlString = urlTextBox.getText().toString().trim();
// Check to see if `unformattedUrlString` is a valid URL. Otherwise, convert it into a search.
- if ((Patterns.WEB_URL.matcher(unformattedUrlString).matches()) || (unformattedUrlString.contains("localhost"))) {
+ if ((Patterns.WEB_URL.matcher(unformattedUrlString).matches()) || (unformattedUrlString.startsWith("http://")) || (unformattedUrlString.startsWith("https://"))) {
// Add `http://` at the beginning if it is missing. Otherwise the app will segfault.
if (!unformattedUrlString.startsWith("http")) {
unformattedUrlString = "http://" + unformattedUrlString;
// Sanitize the search input and convert it to a search.
final String encodedUrlString = URLEncoder.encode(unformattedUrlString, "UTF-8");
- // Use the correct search URL.
- if (javaScriptEnabled) { // JavaScript is enabled.
- formattedUrlString = javaScriptEnabledSearchURL + encodedUrlString;
- } else { // JavaScript is disabled.
- formattedUrlString = javaScriptDisabledSearchURL + encodedUrlString;
- }
+ // Add the base search URL.
+ formattedUrlString = searchURL + encodedUrlString;
}
loadUrl(formattedUrlString);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// Store the values from `sharedPreferences` in variables.
- String javaScriptDisabledSearchString = sharedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=");
- String javaScriptDisabledSearchCustomURLString = sharedPreferences.getString("javascript_disabled_search_custom_url", "");
- String javaScriptEnabledSearchString = sharedPreferences.getString("javascript_enabled_search", "https://duckduckgo.com/?q=");
- String javaScriptEnabledSearchCustomURLString = sharedPreferences.getString("javascript_enabled_search_custom_url", "");
String homepageString = sharedPreferences.getString("homepage", "https://duckduckgo.com");
String torHomepageString = sharedPreferences.getString("tor_homepage", "https://3g2upl4pq6kufc4m.onion");
- String torJavaScriptDisabledSearchString = sharedPreferences.getString("tor_javascript_disabled_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
- String torJavaScriptDisabledSearchCustomURLString = sharedPreferences.getString("tor_javascript_disabled_search_custom_url", "");
- String torJavaScriptEnabledSearchString = sharedPreferences.getString("tor_javascript_enabled_search", "https://3g2upl4pq6kufc4m.onion/?q=");
- String torJavaScriptEnabledSearchCustomURLString = sharedPreferences.getString("tor_javascript_enabled_search_custom_url", "");
+ String torSearchString = sharedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
+ String torSearchCustomURLString = sharedPreferences.getString("tor_search_custom_url", "");
+ String searchString = sharedPreferences.getString("search", "https://duckduckgo.com/html/?q=");
+ String searchCustomURLString = sharedPreferences.getString("search_custom_url", "");
adBlockerEnabled = sharedPreferences.getBoolean("block_ads", true);
incognitoModeEnabled = sharedPreferences.getBoolean("incognito_mode", false);
boolean doNotTrackEnabled = sharedPreferences.getBoolean("do_not_track", false);
- proxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
+ boolean 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);
formattedUrlString = homepage;
}
- // Set JavaScript disabled search.
- if (torJavaScriptDisabledSearchString.equals("Custom URL")) { // Get the custom URL string.
- javaScriptDisabledSearchURL = torJavaScriptDisabledSearchCustomURLString;
+ // Set the search URL.
+ if (torSearchString.equals("Custom URL")) { // Get the custom URL string.
+ searchURL = torSearchCustomURLString;
} else { // Use the string from the pre-built list.
- javaScriptDisabledSearchURL = torJavaScriptDisabledSearchString;
- }
-
- // Set JavaScript enabled search.
- if (torJavaScriptEnabledSearchString.equals("Custom URL")) { // Get the custom URL string.
- javaScriptEnabledSearchURL = torJavaScriptEnabledSearchCustomURLString;
- } else { // Use the string from the pre-built list.
- javaScriptEnabledSearchURL = torJavaScriptEnabledSearchString;
+ searchURL = torSearchString;
}
// Set the proxy. `this` refers to the current activity where an `AlertDialog` might be displayed.
// Display a message to the user if we are waiting on Orbot.
if (!orbotStatus.equals("ON")) {
- // Save `formattedUrlString` in `pendingUrl`.
- pendingUrl = formattedUrlString;
+ // Set `waitingForOrbot`.
+ waitingForOrbot = true;
// Load a waiting page. `null` specifies no encoding, which defaults to ASCII.
mainWebView.loadData(waitingForOrbotHTMLString, "text/html", null);
formattedUrlString = homepage;
}
- // Set JavaScript disabled search.
- if (javaScriptDisabledSearchString.equals("Custom URL")) { // Get the custom URL string.
- javaScriptDisabledSearchURL = javaScriptDisabledSearchCustomURLString;
+ // Set the search URL.
+ if (searchString.equals("Custom URL")) { // Get the custom URL string.
+ searchURL = searchCustomURLString;
} else { // Use the string from the pre-built list.
- javaScriptDisabledSearchURL = javaScriptDisabledSearchString;
- }
-
- // Set JavaScript enabled search.
- if (javaScriptEnabledSearchString.equals("Custom URL")) { // Get the custom URL string.
- javaScriptEnabledSearchURL = javaScriptEnabledSearchCustomURLString;
- } else { // Use the string from the pre-built list.
- javaScriptEnabledSearchURL = javaScriptEnabledSearchString;
+ searchURL = searchString;
}
// 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 = "";
- }
+ // Reset `waitingForOrbot.
+ waitingForOrbot = false;
}
// Set swipe to refresh.
// Reset `inFullScreenBrowsingMode` to `false`.
inFullScreenBrowsingMode = false;
- // Show the `appBar`.
- appBar.show();
+ // Show the `appBar` if `findOnPageLinearLayout` is not visible.
+ if (findOnPageLinearLayout.getVisibility() == View.GONE) {
+ appBar.show();
+ }
// Show the `BannerAd` in the free flavor.
if (BuildConfig.FLAVOR.contentEquals("free")) {