implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.viewpager:viewpager:1.0.0'
- implementation 'androidx.webkit:webkit:1.2.0'
+ implementation 'androidx.webkit:webkit:1.3.0'
// Include the Kotlin standard libraries
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72"
import android.net.Uri;
import android.net.http.SslCertificate;
import android.net.http.SslError;
+import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
PinnedMismatchDialog.PinnedMismatchListener, PopulateBlocklists.PopulateBlocklistsListener, SaveDialog.SaveWebpageListener, StoragePermissionDialog.StoragePermissionDialogListener,
UrlHistoryDialog.NavigateHistoryListener, WebViewTabFragment.NewTabListener {
- // The executor service handles background tasks. It is accessed from `ViewSourceActivity`. TODO. Change the number of threads, or create a single thread executor.
+ // The executor service handles background tasks. It is accessed from `ViewSourceActivity`.
public static ExecutorService executorService = Executors.newFixedThreadPool(4);
// `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`. It is also used in `onCreate()`, `onResume()`, and `applyProxy()`.
private TabLayout tabLayout;
private ViewPager webViewPager;
+ // Define the class variables.
+ @SuppressWarnings("rawtypes")
+ AsyncTask populateBlocklists;
+
// The current WebView is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, `onCreateContextMenu()`, `findPreviousOnPage()`,
// `findNextOnPage()`, `closeFindOnPage()`, `loadUrlFromTextBox()`, `onSslMismatchBack()`, `applyProxy()`, and `applyDomainSettings()`.
private NestedScrollWebView currentWebView;
applyAppSettings();
// Populate the blocklists.
- new PopulateBlocklists(this, this).execute();
+ populateBlocklists = new PopulateBlocklists(this, this).execute();
}
@Override
bookmarksDatabaseHelper.close();
}
+ // Stop populating the blocklists if the AsyncTask is running in the background.
+ if (populateBlocklists != null) {
+ populateBlocklists.cancel(true);
+ }
+
// Run the default commands.
super.onDestroy();
}
tab.select();
};
- // Select the tab layout after 150 milliseconds, which leaves enough time for a new tab to be inflated.
+ // Select the tab layout after 150 milliseconds, which leaves enough time for a new tab to be inflated. TODO.
selectTabHandler.postDelayed(selectTabRunnable, 150);
}
}
String defaultFontSizeString = sharedPreferences.getString("font_size", getString(R.string.font_size_default_value));
String defaultUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
boolean defaultSwipeToRefresh = sharedPreferences.getBoolean("swipe_to_refresh", true);
+ String webViewTheme = sharedPreferences.getString("webview_theme", getString(R.string.webview_theme_default_value));
boolean wideViewport = sharedPreferences.getBoolean("wide_viewport", true);
boolean displayWebpageImages = sharedPreferences.getBoolean("display_webpage_images", true);
+ // Get the WebView theme entry values string array.
+ String[] webViewThemeEntryValuesStringArray = getResources().getStringArray(R.array.webview_theme_entry_values);
+
// Get a handle for the cookie manager.
CookieManager cookieManager = CookieManager.getInstance();
// Set the WebView theme.
switch (webViewThemeInt) {
case DomainsDatabaseHelper.SYSTEM_DEFAULT:
- // // Ge the current system theme status.
- int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
-
- // Set the WebView theme according to the current system theme status.
- if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) { // The system is in day mode.
+ // Set the WebView theme. A switch statement cannot be used because the WebView theme entry values string array is not a compile time constant.
+ if (webViewTheme.equals(webViewThemeEntryValuesStringArray[1])) { // The light theme is selected.
// Turn off the WebView dark mode.
WebSettingsCompat.setForceDark(nestedScrollWebView.getSettings(), WebSettingsCompat.FORCE_DARK_OFF);
- } else { // The system is in night mode.
+ } else if (webViewTheme.equals(webViewThemeEntryValuesStringArray[2])) { // The dark theme is selected.
// Turn on the WebView dark mode.
WebSettingsCompat.setForceDark(nestedScrollWebView.getSettings(), WebSettingsCompat.FORCE_DARK_ON);
+ } else { // The system default theme is selected.
+ // Get the current system theme status.
+ int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+
+ // Set the WebView theme according to the current system theme status.
+ if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) { // The system is in day mode.
+ // Turn off the WebView dark mode.
+ WebSettingsCompat.setForceDark(nestedScrollWebView.getSettings(), WebSettingsCompat.FORCE_DARK_OFF);
+ } else { // The system is in night mode.
+ // Turn on the WebView dark mode.
+ WebSettingsCompat.setForceDark(nestedScrollWebView.getSettings(), WebSettingsCompat.FORCE_DARK_ON);
+ }
}
break;
nestedScrollWebView.enableBlocklist(NestedScrollWebView.ULTRALIST, sharedPreferences.getBoolean("ultralist", true));
nestedScrollWebView.enableBlocklist(NestedScrollWebView.ULTRAPRIVACY, sharedPreferences.getBoolean("ultraprivacy", true));
nestedScrollWebView.enableBlocklist(NestedScrollWebView.THIRD_PARTY_REQUESTS, sharedPreferences.getBoolean("block_all_third_party_requests", false));
- String webViewTheme = sharedPreferences.getString("webview_theme", getString(R.string.webview_theme_default_value));
// Apply the default first-party cookie setting.
cookieManager.setAcceptCookie(nestedScrollWebView.getAcceptFirstPartyCookies());
nestedScrollWebView.getSettings().setUserAgentString(userAgentDataArray[userAgentArrayPosition]);
}
- // Get the WebView theme entry values string array.
- String[] webViewThemeEntryValuesStringArray = getResources().getStringArray(R.array.webview_theme_entry_values);
-
// Apply the WebView theme if supported by the installed WebView.
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
// Set the WebView theme. A switch statement cannot be used because the WebView theme entry values string array is not a compile time constant.
Spinner appBarSpinner = findViewById(R.id.spinner);
appBarSpinner.setAdapter(spinnerCursorAdapter);
+ // Get a handle for the context.
+ Context context = this;
+
// Handle clicks on the spinner dropdown.
appBarSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
switch ((int) id) {
case 0: // All requests.
// Get an adapter for all the request.
- ArrayAdapter<String[]> allResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), allResourceRequests);
+ ArrayAdapter<String[]> allResourceRequestsArrayAdapter = new RequestsArrayAdapter(context, allResourceRequests);
// Display the adapter in the list view.
requestsListView.setAdapter(allResourceRequestsArrayAdapter);
case 1: // Default requests.
// Get an adapter for the default requests.
- ArrayAdapter<String[]> defaultResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), defaultResourceRequests);
+ ArrayAdapter<String[]> defaultResourceRequestsArrayAdapter = new RequestsArrayAdapter(context, defaultResourceRequests);
// Display the adapter in the list view.
requestsListView.setAdapter(defaultResourceRequestsArrayAdapter);
case 2: // Allowed requests.
// Get an adapter for the allowed requests.
- ArrayAdapter<String[]> allowedResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), allowedResourceRequests);
+ ArrayAdapter<String[]> allowedResourceRequestsArrayAdapter = new RequestsArrayAdapter(context, allowedResourceRequests);
// Display the adapter in the list view.
requestsListView.setAdapter(allowedResourceRequestsArrayAdapter);
case 3: // Third-party requests.
// Get an adapter for the third-party requests.
- ArrayAdapter<String[]> thirdPartyResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), thirdPartyResourceRequests);
+ ArrayAdapter<String[]> thirdPartyResourceRequestsArrayAdapter = new RequestsArrayAdapter(context, thirdPartyResourceRequests);
//Display the adapter in the list view.
requestsListView.setAdapter(thirdPartyResourceRequestsArrayAdapter);
case 4: // Blocked requests.
// Get an adapter fo the blocked requests.
- ArrayAdapter<String[]> blockedResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), blockedResourceRequests);
+ ArrayAdapter<String[]> blockedResourceRequestsArrayAdapter = new RequestsArrayAdapter(context, blockedResourceRequests);
// Display the adapter in the list view.
requestsListView.setAdapter(blockedResourceRequestsArrayAdapter);
});
// Create an array adapter with the list of the resource requests.
- ArrayAdapter<String[]> resourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), allResourceRequests);
+ ArrayAdapter<String[]> resourceRequestsArrayAdapter = new RequestsArrayAdapter(context, allResourceRequests);
// Populate the list view with the resource requests adapter.
requestsListView.setAdapter(resourceRequestsArrayAdapter);
dispositionTextView.setText(requestAllowed);
// Set the background color.
- if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
- linearLayout.setBackgroundColor(context.getResources().getColor(R.color.blue_700_50));
- } else {
+ if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
linearLayout.setBackgroundColor(context.getResources().getColor(R.color.blue_100));
+ } else {
+ linearLayout.setBackgroundColor(context.getResources().getColor(R.color.blue_700_50));
}
break;
dispositionTextView.setText(requestThirdParty);
// Set the background color.
- if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
- linearLayout.setBackgroundColor(context.getResources().getColor(R.color.yellow_700_50));
- } else {
+ if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
linearLayout.setBackgroundColor(context.getResources().getColor(R.color.yellow_100));
+ } else {
+ linearLayout.setBackgroundColor(context.getResources().getColor(R.color.yellow_700_50));
}
break;
dispositionTextView.setText(requestBlocked);
// Set the background color.
- if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
- linearLayout.setBackgroundColor(context.getResources().getColor(R.color.red_700_40));
- } else {
+ if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
linearLayout.setBackgroundColor(context.getResources().getColor(R.color.red_100));
+ } else {
+ linearLayout.setBackgroundColor(context.getResources().getColor(R.color.red_700_40));
}
break;
}
// Set the URL text.
urlTextView.setText(entryStringArray[1]);
- // Set the text color. For some unexplained reason, `android:textColor="?android:textColorPrimary"` doesn't work in the layout file. Probably some bug relating to array adapters.
- if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
- dispositionTextView.setTextColor(context.getResources().getColor(R.color.gray_200));
- urlTextView.setTextColor(context.getResources().getColor(R.color.gray_200));
- } else {
- dispositionTextView.setTextColor(context.getResources().getColor(R.color.black));
- urlTextView.setTextColor(context.getResources().getColor(R.color.black));
- }
-
// Return the modified view.
return view;
}
@Override
protected ArrayList<ArrayList<List<String[]>>> doInBackground(Void... none) {
+ // Exit the AsyncTask if the app has been restarted.
+ if (isCancelled()) {
+ return null;
+ }
+
// Get a handle for the context.
Context context = contextWeakReference.get();
// Populate EasyList.
ArrayList<List<String[]>> easyList = blocklistHelper.parseBlocklist(context.getAssets(), "blocklists/easylist.txt");
+ // Exit the AsyncTask if the app has been restarted.
+ if (isCancelled()) {
+ return null;
+ }
+
// Update the progress.
publishProgress(context.getString(R.string.loading_easyprivacy));
// Populate EasyPrivacy.
ArrayList<List<String[]>> easyPrivacy = blocklistHelper.parseBlocklist(context.getAssets(), "blocklists/easyprivacy.txt");
+ // Exit the AsyncTask if the app has been restarted.
+ if (isCancelled()) {
+ return null;
+ }
+
+
// Update the progress.
publishProgress(context.getString(R.string.loading_fanboys_annoyance_list));
// Populate Fanboy's Annoyance List.
ArrayList<List<String[]>> fanboysAnnoyanceList = blocklistHelper.parseBlocklist(context.getAssets(), "blocklists/fanboy-annoyance.txt");
+ // Exit the AsyncTask if the app has been restarted.
+ if (isCancelled()) {
+ return null;
+ }
+
+
// Update the progress.
publishProgress(context.getString(R.string.loading_fanboys_social_blocking_list));
// Populate Fanboy's Social Blocking List.
ArrayList<List<String[]>> fanboysSocialList = blocklistHelper.parseBlocklist(context.getAssets(), "blocklists/fanboy-social.txt");
+ // Exit the AsyncTask if the app has been restarted.
+ if (isCancelled()) {
+ return null;
+ }
+
+
// Update the progress.
publishProgress(context.getString(R.string.loading_ultralist));
// Populate UltraList.
ArrayList<List<String[]>> ultraList = blocklistHelper.parseBlocklist(context.getAssets(), "blocklists/ultralist.txt");
+ // Exit the AsyncTask if the app has been restarted.
+ if (isCancelled()) {
+ return null;
+ }
+
+
+
// Update the progress.
publishProgress(context.getString(R.string.loading_ultraprivacy));
// Populate UltraPrivacy.
ArrayList<List<String[]>> ultraPrivacy = blocklistHelper.parseBlocklist(context.getAssets(), "blocklists/ultraprivacy.txt");
+ // Exit the AsyncTask if the app has been restarted.
+ if (isCancelled()) {
+ return null;
+ }
+
+
// Populate the combined array list.
combinedBlocklists.add(easyList);
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_margin="10dp"
+ android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp" />
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_margin="10dp"
+ android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
android:lines="1"
android:ellipsize="end" />
-• Implement Android’s relatively new Day/Night theme.
-• Switch to using WebView relatively new built-in dark theme.
-• Save and restore the state if Privacy Browser is restarted in the background by the OS.
-• Use the Content-Disposition header to get file names for downloads.
-• Fix uploading files to some sites.
-• Add Mojeek and remove Qwant and Searx from the list of search engines.
-• Fix a bug that sometimes caused swipe-to-refresh to operate even when disabled.
-• Reorder the context menus.
-• Apply custom headers to links loaded from the WebView.
+• Implementazione del relativamente nuovo tema Giorno e Notte di Android.
+• Passaggio all'utilizzo del relativamente nuovo tema scuro nativo di Webview.
+• Salvataggio e ripristino dello stato nel caso in cui Privacy Browser venga riavviato in background dal sistema operativo.
+• Utilizzo del "Content-Disposition header" per ottenere i nomi dei file nei download.
+• Sistemazione dell'upload dei file verso alcuni siti web.
+• Aggiunta di Mojeek ed eliminazione di Qwant e Searx dalla lista dei motori di ricerca.
+• Correzione di un baco che talvolta provocava il funzionamento dello swipe per aggiornare la pagina anche se disabilitato.
+• Riordino dei menu contestuali.
+• Applicazione di intestazioni personalizzate ai collegamenti caricati da Webview.
• Aggiornamento della traduzione Italiana fornita da Francesco Buratti.
• Aggiornamento della traduzione Francese fornita da Kévin LE FLOHIC.
• Aggiornamento della traduzione in Russo.