// and `ViewSslCertificateDialog`. 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()`.
+ // `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`. It is also used in `onCreate()` and `onResume()`.
public static String orbotStatus;
// `webViewTitle` is public static so it can be accessed from `CreateBookmarkDialog` and `CreateHomeScreenShortcutDialog`. It is also used in `onCreate()`.
public static String easyPrivacyVersion;
public static String fanboysAnnoyanceVersion;
public static String fanboysSocialVersion;
+ public static String ultraPrivacyVersion;
// The request items are public static so they can be accessed by `BlockListHelper`, `RequestsArrayAdapter`, and `ViewRequestsDialog`. They are also used in `onCreate()`.
public static List<String[]> resourceRequests;
private boolean easyPrivacyEnabled;
private boolean fanboysAnnoyanceListEnabled;
private boolean fanboysSocialBlockingListEnabled;
+ private boolean ultraPrivacyEnabled;
// `privacyBrowserRuntime` is used in `onCreate()`, `onOptionsItemSelected()`, and `applyAppSettings()`.
private Runtime privacyBrowserRuntime;
// `reapplyAppSettingsOnRestart` is used in `onNavigationItemSelected()` and `onRestart()`.
private boolean reapplyAppSettingsOnRestart;
+ // `displayingFullScreenVideo` is used in `onCreate()` and `onResume()`.
+ private boolean displayingFullScreenVideo;
+
// `currentDomainName` is used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onAddDomain()`, and `applyDomainSettings()`.
private String currentDomainName;
// `ignorePinnedSslCertificateForDomain` is used in `onCreate()`, `onSslMismatchProceed()`, and `applyDomainSettings()`.
private boolean ignorePinnedSslCertificate;
- // `waitingForOrbot` is used in `onCreate()` and `applyAppSettings()`.
+ // `waitingForOrbot` is used in `onCreate()`, `onResume()`, and `applyAppSettings()`.
private boolean waitingForOrbot;
// `domainSettingsApplied` is used in `prepareOptionsMenu()`, `applyDomainSettings()`, and `setDisplayWebpageImages()`.
// Enter full screen video.
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
+ // Set the full screen video flag.
+ displayingFullScreenVideo = true;
+
// Pause the ad if this is the free flavor.
if (BuildConfig.FLAVOR.contentEquals("free")) {
// The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
// Exit full screen video.
@Override
public void onHideCustomView() {
+ // Unset the full screen video flag.
+ displayingFullScreenVideo = true;
+
// Hide `fullScreenVideoFrameLayout`.
fullScreenVideoFrameLayout.removeAllViews();
fullScreenVideoFrameLayout.setVisibility(View.GONE);
// Enable the sliding drawers.
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
- // Add the translucent status flag. This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ // Apply the appropriate full screen mode the `SYSTEM_UI` flags.
+ if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode.
+ if (hideSystemBarsOnFullscreen) { // Hide everything.
+ // Remove the translucent navigation setting if it is currently flagged.
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+
+ // Remove the translucent status bar overlay.
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+ // Remove the translucent status bar overlay on the `Drawer Layout`, which is special and needs its own command.
+ drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+
+ /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+ * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+ * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+ */
+ rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ } else { // Hide everything except the status and navigation bars.
+ // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+ rootCoordinatorLayout.setSystemUiVisibility(0);
+
+ // Add the translucent status flag if it is unset.
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+ if (translucentNavigationBarOnFullscreen) {
+ // Set the navigation bar to be translucent. This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ } else {
+ // Set the navigation bar to be black.
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ }
+ }
+ } else { // Switch to normal viewing mode.
+ // 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")) {
+ // Initialize the ad. The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
+ AdHelper.initializeAds(findViewById(R.id.adview), getApplicationContext(), getFragmentManager(), getString(R.string.ad_id));
+ }
+
+ // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+ rootCoordinatorLayout.setSystemUiVisibility(0);
- // Set `rootCoordinatorLayout` to fit inside the status and navigation bars. This also clears the `SYSTEM_UI` flags.
- rootCoordinatorLayout.setFitsSystemWindows(true);
+ // 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);
+
+ // Constrain `rootCoordinatorLayout` inside the status and navigation bars.
+ rootCoordinatorLayout.setFitsSystemWindows(true);
+ }
// Show the ad if this is the free flavor.
if (BuildConfig.FLAVOR.contentEquals("free")) {
final ArrayList<List<String[]>> easyPrivacy = blockListHelper.parseBlockList(getAssets(), "blocklists/easyprivacy.txt");
final ArrayList<List<String[]>> fanboysAnnoyanceList = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-annoyance.txt");
final ArrayList<List<String[]>> fanboysSocialList = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-social.txt");
+ final ArrayList<List<String[]>> ultraPrivacy = blockListHelper.parseBlockList(getAssets(), "blocklists/ultraprivacy.txt");
// Store the list versions.
easyListVersion = easyList.get(0).get(0)[0];
easyPrivacyVersion = easyPrivacy.get(0).get(0)[0];
fanboysAnnoyanceVersion = fanboysAnnoyanceList.get(0).get(0)[0];
fanboysSocialVersion = fanboysSocialList.get(0).get(0)[0];
+ ultraPrivacyVersion = ultraPrivacy.get(0).get(0)[0];
mainWebView.setWebViewClient(new WebViewClient() {
// `shouldOverrideUrlLoading` makes this `WebView` the default handler for URLs inside the app, so that links are not kicked out to other apps.
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("http")) { // Load the URL in Privacy Browser.
+ // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
+ formattedUrlString = "";
+
// Apply the domain settings for the new URL. `applyDomainSettings` doesn't do anything if the domain has not changed.
applyDomainSettings(url, true, false);
// Create an empty web resource response to be used if the resource request is blocked.
WebResourceResponse emptyWebResourceResponse = new WebResourceResponse("text/plain", "utf8", new ByteArrayInputStream("".getBytes()));
- // Reset `whiteListResultStringArray`.
+ // Reset the whitelist results tracker.
whiteListResultStringArray = null;
// Initialize the third party request tracker.
boolean isThirdPartyRequest = false;
- //
+ // Initialize the current domain string.
String currentDomain = "";
// Nobody is happy when comparing null strings.
return emptyWebResourceResponse;
}
+ // Check UltraPrivacy if it is enabled.
+ if (ultraPrivacyEnabled) {
+ if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, ultraPrivacy)) {
+ // The resource request was blocked. Return an empty web resource response.
+ return emptyWebResourceResponse;
+ }
+
+ // If the whitelist result is not null, the request has been allowed by UltraPrivacy.
+ if (whiteListResultStringArray != null) {
+ // Add a whitelist entry to the resource requests array.
+ resourceRequests.add(whiteListResultStringArray);
+
+ // The resource request has been allowed by UltraPrivacy. `return null` loads the requested resource.
+ return null;
+ }
+ }
+
// Check EasyList if it is enabled.
if (easyListEnabled) {
if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, easyList)) {
+ // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
+ whiteListResultStringArray = null;
+
// The resource request was blocked. Return an empty web resource response.
return emptyWebResourceResponse;
}
// Check EasyPrivacy if it is enabled.
if (easyPrivacyEnabled) {
if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, easyPrivacy)) {
+ // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
+ whiteListResultStringArray = null;
+
// The resource request was blocked. Return an empty web resource response.
return emptyWebResourceResponse;
}
// Check Fanboy’s Annoyance List if it is enabled.
if (fanboysAnnoyanceListEnabled) {
if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, fanboysAnnoyanceList)) {
+ // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
+ whiteListResultStringArray = null;
+
// The resource request was blocked. Return an empty web resource response.
return emptyWebResourceResponse;
}
} else if (fanboysSocialBlockingListEnabled){ // Only check Fanboy’s Social Blocking List if Fanboy’s Annoyance List is disabled.
if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, fanboysSocialList)) {
+ // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
+ whiteListResultStringArray = null;
+
// The resource request was blocked. Return an empty web resource response.
return emptyWebResourceResponse;
}
// Resume the adView for the free flavor.
if (BuildConfig.FLAVOR.contentEquals("free")) {
- // The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
+ // Resume the ad.
AdHelper.resumeAd(findViewById(R.id.adview));
}
+
+ // Display a message to the user if waiting for Orbot.
+ if (waitingForOrbot && !orbotStatus.equals("ON")) {
+ // Load a waiting page. `null` specifies no encoding, which defaults to ASCII.
+ mainWebView.loadData(waitingForOrbotHTMLString, "text/html", null);
+ }
+
+ if (displayingFullScreenVideo) {
+ // Remove the translucent overlays.
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+ // Remove the translucent status bar overlay on the `Drawer Layout`, which is special and needs its own command.
+ drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+
+ /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+ * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+ * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+ */
+ rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ }
}
@Override
public void onPause() {
+ super.onPause();
+
// Pause `mainWebView`.
mainWebView.onPause();
// Stop all JavaScript.
mainWebView.pauseTimers();
- // Pause the adView or it will continue to consume resources in the background on the free flavor.
+ // Pause the ad or it will continue to consume resources in the background on the free flavor.
if (BuildConfig.FLAVOR.contentEquals("free")) {
- // The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
+ // Pause the ad.
AdHelper.pauseAd(findViewById(R.id.adview));
}
-
- super.onPause();
}
@Override
MenuItem easyPrivacyMenuItem = menu.findItem(R.id.easyprivacy);
MenuItem fanboysAnnoyanceListMenuItem = menu.findItem(R.id.fanboys_annoyance_list);
MenuItem fanboysSocialBlockingListMenuItem = menu.findItem(R.id.fanboys_social_blocking_list);
+ MenuItem ultraPrivacyMenuItem = menu.findItem(R.id.ultraprivacy);
MenuItem blockAllThirdParyRequestsMenuItem = menu.findItem(R.id.block_all_third_party_requests);
MenuItem fontSizeMenuItem = menu.findItem(R.id.font_size);
MenuItem swipeToRefreshMenuItem = menu.findItem(R.id.swipe_to_refresh);
easyPrivacyMenuItem.setChecked(easyPrivacyEnabled);
fanboysAnnoyanceListMenuItem.setChecked(fanboysAnnoyanceListEnabled);
fanboysSocialBlockingListMenuItem.setChecked(fanboysSocialBlockingListEnabled);
+ ultraPrivacyMenuItem.setChecked(ultraPrivacyEnabled);
blockAllThirdParyRequestsMenuItem.setChecked(blockAllThirdPartyRequests);
swipeToRefreshMenuItem.setChecked(swipeRefreshLayout.isEnabled());
displayImagesMenuItem.setChecked(mainWebView.getSettings().getLoadsImagesAutomatically());
mainWebView.reload();
return true;
+ case R.id.ultraprivacy:
+ // Toggle the UltraPrivacy status.
+ ultraPrivacyEnabled = !ultraPrivacyEnabled;
+
+ // Update the menu checkbox.
+ menuItem.setChecked(ultraPrivacyEnabled);
+
+ // Reload the main WebView.
+ mainWebView.reload();
+ return true;
+
case R.id.block_all_third_party_requests:
//Toggle the third-party requests blocker status.
blockAllThirdPartyRequests = !blockAllThirdPartyRequests;
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- // Reload the ad for the free flavor if we are not in full screen mode.
+ // Reload the ad for the free flavor if we 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_id));
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// Store the values from the shared preferences in variables.
- String homepageString = sharedPreferences.getString("homepage", "https://start.duckduckgo.com");
- String torHomepageString = sharedPreferences.getString("tor_homepage", "https://3g2upl4pq6kufc4m.onion");
- String torSearchString = sharedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
+ String homepageString = sharedPreferences.getString("homepage", "https://searx.me/");
+ String torHomepageString = sharedPreferences.getString("tor_homepage", "http://ulrn6sryqaifefld.onion/");
+ String torSearchString = sharedPreferences.getString("tor_search", "http://ulrn6sryqaifefld.onion/?q=");
String torSearchCustomURLString = sharedPreferences.getString("tor_search_custom_url", "");
- String searchString = sharedPreferences.getString("search", "https://duckduckgo.com/html/?q=");
+ String searchString = sharedPreferences.getString("search", "https://searx.me/?q=");
String searchCustomURLString = sharedPreferences.getString("search_custom_url", "");
incognitoModeEnabled = sharedPreferences.getBoolean("incognito_mode", false);
boolean doNotTrackEnabled = sharedPreferences.getBoolean("do_not_track", false);
appBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.blue_50));
}
- // Display a message to the user if we are waiting on Orbot.
+ // Display a message to the user if waiting for Orbot.
if (!orbotStatus.equals("ON")) {
// Set `waitingForOrbot`.
waitingForOrbot = true;
}
// Apply the appropriate full screen mode the `SYSTEM_UI` flags.
- if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) {
+ if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode.
if (hideSystemBarsOnFullscreen) { // Hide everything.
// Remove the translucent navigation setting if it is currently flagged.
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
*/
rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
} else { // Hide everything except the status and navigation bars.
+ // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+ rootCoordinatorLayout.setSystemUiVisibility(0);
+
// Add the translucent status flag if it is unset.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
- } else { // Switch to normal viewing mode.
- // Reset `inFullScreenBrowsingMode` to `false`.
+ } else { // Privacy Browser is not in full screen browsing mode.
+ // Reset the full screen tracker, which could be true if Privacy Browser was in full screen mode before entering settings and full screen browsing was disabled.
inFullScreenBrowsingMode = false;
// Show the `appBar` if `findOnPageLinearLayout` is not visible.
AdHelper.initializeAds(findViewById(R.id.adview), getApplicationContext(), getFragmentManager(), getString(R.string.ad_id));
}
+ // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+ rootCoordinatorLayout.setSystemUiVisibility(0);
+
// 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);
}
easyPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);
fanboysAnnoyanceListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);
fanboysSocialBlockingListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1);
+ ultraPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1);
blockAllThirdPartyRequests = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1);
String userAgentName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
int fontSize = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true);
fanboysAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboy_annoyance_list", true);
fanboysSocialBlockingListEnabled = sharedPreferences.getBoolean("fanboy_social_blocking_list", true);
+ ultraPrivacyEnabled = sharedPreferences.getBoolean("ultraprivacy", true);
blockAllThirdPartyRequests = sharedPreferences.getBoolean("block_all_third_party_requests", false);
// Set `javaScriptEnabled` to be `true` if `night_mode` is `true`.