HttpAuthenticationDialog.HttpAuthenticationListener, NavigationView.OnNavigationItemSelectedListener, PinnedSslCertificateMismatchDialog.PinnedSslCertificateMismatchListener,
SslCertificateErrorDialog.SslCertificateErrorListener, UrlHistoryDialog.UrlHistoryListener {
- // `darkTheme` is public static so it can be accessed from `AboutActivity`, `GuideActivity`, `AddDomainDialog`, `SettingsActivity`, `DomainsActivity`, `DomainsListFragment`, `BookmarksActivity`,
- // `BookmarksDatabaseViewActivity`, `CreateBookmarkDialog`, `CreateBookmarkFolderDialog`, `DownloadFileDialog`, `DownloadImageDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog`,
- // `EditBookmarkDatabaseViewDialog`, `HttpAuthenticationDialog`, `MoveToFolderDialog`, `SslCertificateErrorDialog`, `UrlHistoryDialog`, `ViewSslCertificateDialog`, `CreateHomeScreenShortcutDialog`,
- // and `OrbotProxyHelper`. It is also used in `onCreate()`, `applyAppSettings()`, `applyDomainSettings()`, and `updatePrivacyIcons()`.
+ // `darkTheme` is public static so it can be accessed from everywhere.
public static boolean darkTheme;
// `allowScreenshots` is public static so it can be accessed from everywhere. It is also used in `onCreate()`.
public static String fanboyAnnoyanceVersion;
public static String fanboySocialVersion;
+ // 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;
+ public static String[] whiteListResultStringArray;
+ public final static int REQUEST_DISPOSITION = 0;
+ public final static int REQUEST_URL = 1;
+ public final static int REQUEST_BLOCKLIST = 2;
+ public final static int REQUEST_SUBLIST = 3;
+ public final static int REQUEST_BLOCKLIST_ENTRIES = 4;
+ public final static int REQUEST_BLOCKLIST_ORIGINAL_ENTRY = 5;
+
+ public final static int REQUEST_DEFAULT = 0;
+ public final static int REQUEST_ALLOWED = 1;
+ public final static int REQUEST_BLOCKED = 2;
+
+ public final static int MAIN_WHITELIST = 1;
+ public final static int FINAL_WHITELIST = 2;
+ public final static int DOMAIN_WHITELIST = 3;
+ public final static int DOMAIN_INITIAL_WHITELIST = 4;
+ public final static int DOMAIN_FINAL_WHITELIST = 5;
+ public final static int THIRD_PARTY_WHITELIST = 6;
+ public final static int THIRD_PARTY_DOMAIN_WHITELIST = 7;
+ public final static int THIRD_PARTY_DOMAIN_INITIAL_WHITELIST = 8;
+
+ public final static int MAIN_BLACKLIST = 9;
+ public final static int INITIAL_BLACKLIST = 10;
+ public final static int FINAL_BLACKLIST = 11;
+ public final static int DOMAIN_BLACKLIST = 12;
+ public final static int DOMAIN_INITIAL_BLACKLIST = 13;
+ public final static int DOMAIN_FINAL_BLACKLIST = 14;
+ public final static int DOMAIN_REGULAR_EXPRESSION_BLACKLIST = 15;
+ public final static int THIRD_PARTY_BLACKLIST = 16;
+ public final static int THIRD_PARTY_INITIAL_BLACKLIST = 17;
+ public final static int THIRD_PARTY_DOMAIN_BLACKLIST = 18;
+ public final static int THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST = 19;
+ public final static int THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST = 20;
+ public final static int THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST = 21;
+ public final static int REGULAR_EXPRESSION_BLACKLIST = 22;
+
// `currentBookmarksFolder` is public static so it can be accessed from `BookmarksActivity`. It is also used in `onCreate()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`,
// `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`.
public static String currentBookmarksFolder;
// `fullScreenVideoFrameLayout` is used in `onCreate()` and `onConfigurationChanged()`.
private FrameLayout fullScreenVideoFrameLayout;
- // `swipeRefreshLayout` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsMenuSelected()`, and `onRestart()`.
+ // `swipeRefreshLayout` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `onRestart()`.
private SwipeRefreshLayout swipeRefreshLayout;
// `urlAppBarRelativeLayout` is used in `onCreate()` and `applyDomainSettings()`.
// `domStorageEnabled` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyDomainSettings()`.
private boolean domStorageEnabled;
- // `saveFormDataEnabled` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyDomainSettings()`.
+ // `saveFormDataEnabled` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyDomainSettings()`. It can be removed once the minimum API >= 26.
private boolean saveFormDataEnabled;
// `nightMode` is used in `onCreate()` and `applyDomainSettings()`.
// `searchURL` is used in `loadURLFromTextBox()` and `applyAppSettings()`.
private String searchURL;
- // The block list variables are used in `onCreate()` and `applyAppSettings()`.
+ // The block list variables are used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyAppSettings()`.
private boolean easyListEnabled;
private boolean easyPrivacyEnabled;
private boolean fanboysAnnoyanceListEnabled;
final MenuItem navigationBackMenuItem = navigationMenu.getItem(1);
final MenuItem navigationForwardMenuItem = navigationMenu.getItem(2);
final MenuItem navigationHistoryMenuItem = navigationMenu.getItem(3);
+ final MenuItem navigationRequestsMenuItem = navigationMenu.getItem(4);
// Initialize the bookmarks database helper. `this` specifies the context. The two `nulls` do not specify the database name or a `CursorFactory`.
// The `0` specifies a database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`.
return true;
});
- // The `DrawerListener` allows us to update the Navigation Menu.
+ // The `DrawerListener` is used to update the Navigation Menu.
drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
@Override
public void onDrawerStateChanged(int newState) {
if ((newState == DrawerLayout.STATE_SETTLING) || (newState == DrawerLayout.STATE_DRAGGING)) { // The drawer is opening or closing.
- // Update the `Back`, `Forward`, and `History` menu items.
+ // Initialize a the blocked requests counter.
+ int blockedRequests = 0;
+
+ // Count the number of blocked requests.
+ for (int i = 0; i < resourceRequests.size(); i++) {
+ if (Integer.valueOf(resourceRequests.get(i)[REQUEST_DISPOSITION]) == REQUEST_BLOCKED) {
+ blockedRequests++;
+ }
+ }
+
+ // Update the back, forward, history, and requests menu items.
navigationBackMenuItem.setEnabled(mainWebView.canGoBack());
navigationForwardMenuItem.setEnabled(mainWebView.canGoForward());
navigationHistoryMenuItem.setEnabled((mainWebView.canGoBack() || mainWebView.canGoForward()));
+ navigationRequestsMenuItem.setTitle(getResources().getString(R.string.requests) + " - " + blockedRequests);
// Hide the keyboard (if displayed) so we can see the navigation menu. `0` indicates no additional flags.
inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
firstPartyCookiesEnabled = false;
thirdPartyCookiesEnabled = false;
domStorageEnabled = false;
- saveFormDataEnabled = false;
+ saveFormDataEnabled = false; // Form data can be removed once the minimum API >= 26.
nightMode = false;
// Initialize the WebView title.
// Instantiate the block list helper.
BlockListHelper blockListHelper = new BlockListHelper();
+ // Initialize the list of resource requests.
+ resourceRequests = new ArrayList<>();
+
// Parse the block lists.
final ArrayList<List<String[]>> easyList = blockListHelper.parseBlockList(getAssets(), "blocklists/easylist.txt");
final ArrayList<List<String[]>> easyPrivacy = blockListHelper.parseBlockList(getAssets(), "blocklists/easyprivacy.txt");
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("http")) { // Load the URL in Privacy Browser.
- // Apply the domain settings for the new URL.
+ // Apply the domain settings for the new URL. `applyDomainSettings` doesn't do anything if the domain has not changed.
applyDomainSettings(url, true, false);
- // Returning false causes the current `WebView` to handle the URL and prevents it from adding redirects to the history list.
+ // Returning false causes the current WebView to handle the URL and prevents it from adding redirects to the history list.
return false;
} else if (url.startsWith("mailto:")) { // Load the email address in an external email program.
// Use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched.
}
}
- // Check requests against the block lists. The deprecated `shouldInterceptRequest` must be used until minimum API >= 21.
+ // Check requests against the block lists. The deprecated `shouldInterceptRequest()` must be used until minimum API >= 21.
@SuppressWarnings("deprecation")
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url){
// 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`.
+ whiteListResultStringArray = null;
+
// Check EasyList if it is enabled.
if (easyListEnabled) {
if (blockListHelper.isBlocked(formattedUrlString, url, easyList)) {
}
}
+ // Add the request to the log.
+ if (whiteListResultStringArray != null ) { // The request was processed by a whitelist.
+ resourceRequests.add(whiteListResultStringArray);
+ } else { // The request didn't match any blocklist entry. Log it as a defult request.
+ resourceRequests.add(new String[]{String.valueOf(REQUEST_DEFAULT), url});
+ }
+
// The resource request has not been blocked. `return null` loads the requested resource.
return null;
}
// Update the URL in urlTextBox when the page starts to load.
@Override
- public void onPageStarted(WebView view, String url, Bitmap favicon) {// If night mode is enabled, hide `mainWebView` until after the night mode CSS is applied.
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ // Reset the list of resource requests.
+ resourceRequests.clear();
+
+ // If night mode is enabled, hide `mainWebView` until after the night mode CSS is applied.
if (nightMode) {
mainWebView.setVisibility(View.INVISIBLE);
}
// Hide the keyboard. `0` indicates no additional flags.
inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
- // Check to see if we are waiting on Orbot.
+ // 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.
formattedUrlString = url;
MenuItem toggleFirstPartyCookiesMenuItem = menu.findItem(R.id.toggle_first_party_cookies);
MenuItem toggleThirdPartyCookiesMenuItem = menu.findItem(R.id.toggle_third_party_cookies);
MenuItem toggleDomStorageMenuItem = menu.findItem(R.id.toggle_dom_storage);
- MenuItem toggleSaveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data);
+ MenuItem toggleSaveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data); // Form data can be removed once the minimum API >= 26.
+ MenuItem clearFormDataMenuItem = menu.findItem(R.id.clear_form_data); // Form data can be removed once the minimum API >= 26.
+ MenuItem refreshMenuItem = menu.findItem(R.id.refresh);
+ MenuItem adConsentMenuItem = menu.findItem(R.id.ad_consent);
- // Only display third-party cookies if SDK >= 21
+ // Only display third-party cookies if API >= 21
toggleThirdPartyCookiesMenuItem.setVisible(Build.VERSION.SDK_INT >= 21);
+ // Only display the form data menu items if the API < 26.
+ toggleSaveFormDataMenuItem.setVisible(Build.VERSION.SDK_INT < 26);
+ clearFormDataMenuItem.setVisible(Build.VERSION.SDK_INT < 26);
+
+ // Only show Ad Consent if this is the free flavor.
+ adConsentMenuItem.setVisible(BuildConfig.FLAVOR.contentEquals("free"));
+
// Get the shared preference values. `this` references the current context.
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
- // Set the status of the additional app bar icons. The default is `false`.
+ // Set the status of the additional app bar icons. Setting the refresh menu item to `SHOW_AS_ACTION_ALWAYS` makes it appear even on small devices like phones.
if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
toggleDomStorageMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- toggleSaveFormDataMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ refreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
} else { //Do not display the additional icons.
toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
toggleDomStorageMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- toggleSaveFormDataMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ refreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
}
return true;
MenuItem toggleFirstPartyCookiesMenuItem = menu.findItem(R.id.toggle_first_party_cookies);
MenuItem toggleThirdPartyCookiesMenuItem = menu.findItem(R.id.toggle_third_party_cookies);
MenuItem toggleDomStorageMenuItem = menu.findItem(R.id.toggle_dom_storage);
- MenuItem toggleSaveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data);
+ MenuItem toggleSaveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data); // Form data can be removed once the minimum API >= 26.
MenuItem clearDataMenuItem = menu.findItem(R.id.clear_data);
MenuItem clearCookiesMenuItem = menu.findItem(R.id.clear_cookies);
MenuItem clearDOMStorageMenuItem = menu.findItem(R.id.clear_dom_storage);
- MenuItem clearFormDataMenuItem = menu.findItem(R.id.clear_form_data);
+ MenuItem clearFormDataMenuItem = menu.findItem(R.id.clear_form_data); // Form data can be removed once the minimum API >= 26.
+ MenuItem easyListMenuItem = menu.findItem(R.id.easylist);
+ 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 fontSizeMenuItem = menu.findItem(R.id.font_size);
MenuItem swipeToRefreshMenuItem = menu.findItem(R.id.swipe_to_refresh);
MenuItem displayImagesMenuItem = menu.findItem(R.id.display_images);
- MenuItem adConsentMenuItem = menu.findItem(R.id.ad_consent);
// Set the text for the domain menu item.
if (domainSettingsApplied) {
toggleFirstPartyCookiesMenuItem.setChecked(firstPartyCookiesEnabled);
toggleThirdPartyCookiesMenuItem.setChecked(thirdPartyCookiesEnabled);
toggleDomStorageMenuItem.setChecked(domStorageEnabled);
- toggleSaveFormDataMenuItem.setChecked(saveFormDataEnabled);
+ toggleSaveFormDataMenuItem.setChecked(saveFormDataEnabled); // Form data can be removed once the minimum API >= 26.
+ easyListMenuItem.setChecked(easyListEnabled);
+ easyPrivacyMenuItem.setChecked(easyPrivacyEnabled);
+ fanboysAnnoyanceListMenuItem.setChecked(fanboysAnnoyanceListEnabled);
+ fanboysSocialBlockingListMenuItem.setChecked(fanboysSocialBlockingListEnabled);
swipeToRefreshMenuItem.setChecked(swipeRefreshLayout.isEnabled());
displayImagesMenuItem.setChecked(mainWebView.getSettings().getLoadsImagesAutomatically());
// Enable third-party cookies if first-party cookies are enabled.
toggleThirdPartyCookiesMenuItem.setEnabled(firstPartyCookiesEnabled);
- // Enable `DOM Storage` if JavaScript is enabled.
+ // Enable DOM Storage if JavaScript is enabled.
toggleDomStorageMenuItem.setEnabled(javaScriptEnabled);
- // Enable `Clear Cookies` if there are any.
+ // Enable Clear Cookies if there are any.
clearCookiesMenuItem.setEnabled(cookieManager.hasCookies());
- // Get a count of the number of files in the `Local Storage` directory.
+ // Get a count of the number of files in the Local Storage directory.
File localStorageDirectory = new File (privateDataDirectoryString + "/app_webview/Local Storage/");
int localStorageDirectoryNumberOfFiles = 0;
if (localStorageDirectory.exists()) {
localStorageDirectoryNumberOfFiles = localStorageDirectory.list().length;
}
- // Get a count of the number of files in the `IndexedDB` directory.
+ // Get a count of the number of files in the IndexedDB directory.
File indexedDBDirectory = new File (privateDataDirectoryString + "/app_webview/IndexedDB");
int indexedDBDirectoryNumberOfFiles = 0;
if (indexedDBDirectory.exists()) {
indexedDBDirectoryNumberOfFiles = indexedDBDirectory.list().length;
}
- // Enable `Clear DOM Storage` if there is any.
+ // Enable Clear DOM Storage if there is any.
clearDOMStorageMenuItem.setEnabled(localStorageDirectoryNumberOfFiles > 0 || indexedDBDirectoryNumberOfFiles > 0);
- // Enable `Clear Form Data` is there is any.
- WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this);
- clearFormDataMenuItem.setEnabled(mainWebViewDatabase.hasFormData());
+ // Enable Clear Form Data is there is any. This can be removed once the minimum API >= 26.
+ if (Build.VERSION.SDK_INT < 26) {
+ WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this);
+ clearFormDataMenuItem.setEnabled(mainWebViewDatabase.hasFormData());
+ }
- // Enable `Clear Data` if any of the submenu items are enabled.
+ // Enable Clear Data if any of the submenu items are enabled.
clearDataMenuItem.setEnabled(clearCookiesMenuItem.isEnabled() || clearDOMStorageMenuItem.isEnabled() || clearFormDataMenuItem.isEnabled());
+ // Disable Fanboy's Social Blocking List if Fanboy's Annoyance List is checked.
+ fanboysSocialBlockingListMenuItem.setEnabled(!fanboysAnnoyanceListEnabled);
+
// Initialize font size variables.
int fontSize = mainWebView.getSettings().getTextZoom();
String fontSizeTitle;
fontSizeMenuItem.setTitle(fontSizeTitle);
selectedFontSizeMenuItem.setChecked(true);
- // Only show Ad Consent if this is the free flavor.
- adConsentMenuItem.setVisible(BuildConfig.FLAVOR.contentEquals("free"));
-
// Run all the other default commands.
super.onPrepareOptionsMenu(menu);
mainWebView.reload();
return true;
+ // Form data can be removed once the minimum API >= 26.
case R.id.toggle_save_form_data:
// Switch the status of saveFormDataEnabled.
saveFormDataEnabled = !saveFormDataEnabled;
.show();
return true;
+ // Form data can be remove once the minimum API >= 26.
case R.id.clear_form_data:
Snackbar.make(findViewById(R.id.main_webview), R.string.form_data_deleted, Snackbar.LENGTH_LONG)
.setAction(R.string.undo, v -> {
startActivity(viewSourceIntent);
return true;
+ case R.id.easylist:
+ // Toggle the EasyList status.
+ easyListEnabled = !easyListEnabled;
+
+ // Update the menu checkbox.
+ menuItem.setChecked(easyListEnabled);
+
+ // Reload the main WebView.
+ mainWebView.reload();
+ return true;
+
+ case R.id.easyprivacy:
+ // Toggle the EasyPrivacy status.
+ easyPrivacyEnabled = !easyPrivacyEnabled;
+
+ // Update the menu checkbox.
+ menuItem.setChecked(easyPrivacyEnabled);
+
+ // Reload the main WebView.
+ mainWebView.reload();
+ return true;
+
+ case R.id.fanboys_annoyance_list:
+ // Toggle Fanboy's Annoyance List status.
+ fanboysAnnoyanceListEnabled = !fanboysAnnoyanceListEnabled;
+
+ // Update the menu checkbox.
+ menuItem.setChecked(fanboysAnnoyanceListEnabled);
+
+ // Update the staus of Fanboy's Social Blocking List.
+ MenuItem fanboysSocialBlockingListMenuItem = mainMenu.findItem(R.id.fanboys_social_blocking_list);
+ fanboysSocialBlockingListMenuItem.setEnabled(!fanboysAnnoyanceListEnabled);
+
+ // Reload the main WebView.
+ mainWebView.reload();
+ return true;
+
+ case R.id.fanboys_social_blocking_list:
+ // Toggle Fanboy's Social Blocking List status.
+ fanboysSocialBlockingListEnabled = !fanboysSocialBlockingListEnabled;
+
+ // Update teh menu checkbox.
+ menuItem.setChecked(fanboysSocialBlockingListEnabled);
+
+ // Reload the main WebView.
+ mainWebView.reload();
+ return true;
+
case R.id.share:
// Setup the share string.
String shareString = webViewTitle + " – " + urlTextBox.getText().toString();
urlHistoryDialogFragment.show(getSupportFragmentManager(), getString(R.string.history));
break;
+ case R.id.requests:
+ // Launch the requests activity.
+ Intent requestsIntent = new Intent(this, RequestsActivity.class);
+ startActivity(requestsIntent);
+ break;
+
case R.id.downloads:
// Launch the system Download Manager.
Intent downloadManagerIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
reapplyDomainSettingsOnRestart = true;
currentDomainName = "";
- // Launch `DomainsActivity`.
+ // Launch the domains activity.
Intent domainsIntent = new Intent(this, DomainsActivity.class);
startActivity(domainsIntent);
break;
reapplyDomainSettingsOnRestart = true;
currentDomainName = "";
- // Launch `SettingsActivity`.
+ // Launch the settings activity.
Intent settingsIntent = new Intent(this, SettingsActivity.class);
startActivity(settingsIntent);
break;
}
}
- // Clear form data.
- if (clearEverything || sharedPreferences.getBoolean("clear_form_data", true)) {
+ // Clear form data if the API < 26.
+ if ((Build.VERSION.SDK_INT < 26) && (clearEverything || sharedPreferences.getBoolean("clear_form_data", true))) {
WebViewDatabase webViewDatabase = WebViewDatabase.getInstance(this);
webViewDatabase.clearFormData();
// Decode `formattedUri` as a `String` in `UTF-8`.
formattedUrlString = URLDecoder.decode(formattedUri.build().toString(), "UTF-8");
- } else {
+ } else if (unformattedUrlString.isEmpty()){ // Load a blank web site.
+ // Load a blank string.
+ formattedUrlString = "";
+ } else { // Search for the contents of the URL box.
// Sanitize the search input and convert it to a search.
final String encodedUrlString = URLEncoder.encode(unformattedUrlString, "UTF-8");
// Clear the focus from the URL text box. Otherwise, proximate typing in the box will retain the colorized formatting instead of being reset during refocus.
urlTextBox.clearFocus();
+ // Make it so.
loadUrl(formattedUrlString);
}
-
- private void loadUrl(String url) {
- // Apply any custom domain settings.
+ private void loadUrl(String url) {// Apply any custom domain settings.
applyDomainSettings(url, true, false);
- // Load the URL.
- mainWebView.loadUrl(url, customHeaders);
-
// Set `urlIsLoading` to prevent changes in the user agent on websites with redirects from reloading the current website.
urlIsLoading = true;
+
+ // Load the URL.
+ mainWebView.loadUrl(url, customHeaders);
}
public void findPreviousOnPage(View view) {
loadingNewDomainName = !hostName.equals(currentDomainName);
}
+ // Strings don't like to be null.
+ if (hostName == null) {
+ hostName = "";
+ }
+
// Only apply the domain settings if a new domain is being loaded. This allows the user to set temporary settings for JavaScript, cookies, DOM storage, etc.
if (loadingNewDomainName) {
// Set the new `hostname` as the `currentDomainName`.
domainNameInDatabase = hostName;
}
- // If `hostName` is not `null`, check all the subdomains of `hostName` against wildcard domains in `domainCursor`.
- if (hostName != null) {
- while (hostName.contains(".") && !domainSettingsApplied) { // Stop checking if we run out of `.` or if we already know that `domainSettingsApplied` is `true`.
- if (domainSettingsSet.contains("*." + hostName)) { // Check the host name prepended by `*.`.
- domainSettingsApplied = true;
- domainNameInDatabase = "*." + hostName;
- }
+ // Check all the subdomains of the host name against wildcard domains in the domain cursor.
+ while (!domainSettingsApplied && hostName.contains(".")) { // Stop checking if domain settings are already applied or there are no more `.` in the host name.
+ if (domainSettingsSet.contains("*." + hostName)) { // Check the host name prepended by `*.`.
+ // Apply the domain settings.
+ domainSettingsApplied = true;
- // Strip out the lowest subdomain of `host`.
- hostName = hostName.substring(hostName.indexOf(".") + 1);
+ // Store the applied domain names as it appears in the database.
+ domainNameInDatabase = "*." + hostName;
}
+
+ // Strip out the lowest subdomain of of the host name.
+ hostName = hostName.substring(hostName.indexOf(".") + 1);
}
- // Get a handle for the shared preference. `this` references the current context.
+
+ // Get a handle for the shared preference.
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// Store the general preference information.
firstPartyCookiesEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES)) == 1);
thirdPartyCookiesEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES)) == 1);
domStorageEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
+ // Form data can be removed once the minimum API >= 26.
saveFormDataEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);
easyListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);
easyPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);
mainWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
cookieManager.setAcceptCookie(firstPartyCookiesEnabled);
mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
- mainWebView.getSettings().setSaveFormData(saveFormDataEnabled);
+
+ // Apply the form data setting if the API < 26.
+ if (Build.VERSION.SDK_INT < 26) {
+ mainWebView.getSettings().setSaveFormData(saveFormDataEnabled);
+ }
// Apply the font size.
if (fontSize == 0) { // Apply the default font size.
} else {
urlAppBarRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_light_green));
}
- } else { // The URL we are loading does not have custom domain settings. Load the defaults.
+ } else { // The new URL does not have custom domain settings. Load the defaults.
// Store the values from `sharedPreferences` in variables.
javaScriptEnabled = sharedPreferences.getBoolean("javascript_enabled", false);
firstPartyCookiesEnabled = sharedPreferences.getBoolean("first_party_cookies_enabled", false);
thirdPartyCookiesEnabled = sharedPreferences.getBoolean("third_party_cookies_enabled", false);
domStorageEnabled = sharedPreferences.getBoolean("dom_storage_enabled", false);
- saveFormDataEnabled = sharedPreferences.getBoolean("save_form_data_enabled", false);
+ saveFormDataEnabled = sharedPreferences.getBoolean("save_form_data_enabled", false); // Form data can be removed once the minimum API >= 26.
easyListEnabled = sharedPreferences.getBoolean("easylist", true);
easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true);
fanboysAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboy_annoyance_list", true);
mainWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
cookieManager.setAcceptCookie(firstPartyCookiesEnabled);
mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
- mainWebView.getSettings().setSaveFormData(saveFormDataEnabled);
mainWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString));
swipeRefreshLayout.setEnabled(defaultSwipeToRefresh);
+ // Apply the form data setting if the API < 26.
+ if (Build.VERSION.SDK_INT < 26) {
+ mainWebView.getSettings().setSaveFormData(saveFormDataEnabled);
+ }
+
// Reset the pinned SSL certificate information.
domainSettingsDatabaseId = -1;
pinnedDomainSslCertificate = false;
if (mainMenu != null) {
updatePrivacyIcons(true);
}
+ }
- // Reload the website if returning from the Domains activity.
- if (reloadWebsite) {
- mainWebView.reload();
- }
+ // Reload the website if returning from the Domains activity.
+ if (reloadWebsite) {
+ mainWebView.reload();
}
}
}
private void updatePrivacyIcons(boolean runInvalidateOptionsMenu) {
- // Get handles for the icons.
- MenuItem privacyIconMenuItem = mainMenu.findItem(R.id.toggle_javascript);
- MenuItem firstPartyCookiesIconMenuItem = mainMenu.findItem(R.id.toggle_first_party_cookies);
- MenuItem domStorageIconMenuItem = mainMenu.findItem(R.id.toggle_dom_storage);
- MenuItem formDataIconMenuItem = mainMenu.findItem(R.id.toggle_save_form_data);
+ // Get handles for the menu items.
+ MenuItem privacyMenuItem = mainMenu.findItem(R.id.toggle_javascript);
+ MenuItem firstPartyCookiesMenuItem = mainMenu.findItem(R.id.toggle_first_party_cookies);
+ MenuItem domStorageMenuItem = mainMenu.findItem(R.id.toggle_dom_storage);
+ MenuItem refreshMenuItem = mainMenu.findItem(R.id.refresh);
- // Update `privacyIcon`.
+ // Update the privacy icon.
if (javaScriptEnabled) { // JavaScript is enabled.
- privacyIconMenuItem.setIcon(R.drawable.javascript_enabled);
+ privacyMenuItem.setIcon(R.drawable.javascript_enabled);
} else if (firstPartyCookiesEnabled) { // JavaScript is disabled but cookies are enabled.
- privacyIconMenuItem.setIcon(R.drawable.warning);
+ privacyMenuItem.setIcon(R.drawable.warning);
} else { // All the dangerous features are disabled.
- privacyIconMenuItem.setIcon(R.drawable.privacy_mode);
+ privacyMenuItem.setIcon(R.drawable.privacy_mode);
}
- // Update `firstPartyCookiesIcon`.
+ // Update the first-party cookies icon.
if (firstPartyCookiesEnabled) { // First-party cookies are enabled.
- firstPartyCookiesIconMenuItem.setIcon(R.drawable.cookies_enabled);
+ firstPartyCookiesMenuItem.setIcon(R.drawable.cookies_enabled);
} else { // First-party cookies are disabled.
if (darkTheme) {
- firstPartyCookiesIconMenuItem.setIcon(R.drawable.cookies_disabled_dark);
+ firstPartyCookiesMenuItem.setIcon(R.drawable.cookies_disabled_dark);
} else {
- firstPartyCookiesIconMenuItem.setIcon(R.drawable.cookies_disabled_light);
+ firstPartyCookiesMenuItem.setIcon(R.drawable.cookies_disabled_light);
}
}
- // Update `domStorageIcon`.
+ // Update the DOM storage icon.
if (javaScriptEnabled && domStorageEnabled) { // Both JavaScript and DOM storage are enabled.
- domStorageIconMenuItem.setIcon(R.drawable.dom_storage_enabled);
+ domStorageMenuItem.setIcon(R.drawable.dom_storage_enabled);
} else if (javaScriptEnabled) { // JavaScript is enabled but DOM storage is disabled.
if (darkTheme) {
- domStorageIconMenuItem.setIcon(R.drawable.dom_storage_disabled_dark);
+ domStorageMenuItem.setIcon(R.drawable.dom_storage_disabled_dark);
} else {
- domStorageIconMenuItem.setIcon(R.drawable.dom_storage_disabled_light);
+ domStorageMenuItem.setIcon(R.drawable.dom_storage_disabled_light);
}
} else { // JavaScript is disabled, so DOM storage is ghosted.
if (darkTheme) {
- domStorageIconMenuItem.setIcon(R.drawable.dom_storage_ghosted_dark);
+ domStorageMenuItem.setIcon(R.drawable.dom_storage_ghosted_dark);
} else {
- domStorageIconMenuItem.setIcon(R.drawable.dom_storage_ghosted_light);
+ domStorageMenuItem.setIcon(R.drawable.dom_storage_ghosted_light);
}
}
- // Update `formDataIcon`.
- if (saveFormDataEnabled) { // Form data is enabled.
- formDataIconMenuItem.setIcon(R.drawable.form_data_enabled);
- } else { // Form data is disabled.
- if (darkTheme) {
- formDataIconMenuItem.setIcon(R.drawable.form_data_disabled_dark);
- } else {
- formDataIconMenuItem.setIcon(R.drawable.form_data_disabled_light);
- }
+ // Update the refresh icon.
+ if (darkTheme) {
+ refreshMenuItem.setIcon(R.drawable.refresh_enabled_dark);
+ } else {
+ refreshMenuItem.setIcon(R.drawable.refresh_enabled_light);
}
// `invalidateOptionsMenu` calls `onPrepareOptionsMenu()` and redraws the icons in the `AppBar`.