Create UltraList. https://redmine.stoutner.com/issues/450
authorSoren Stoutner <soren@stoutner.com>
Thu, 11 Jul 2019 22:32:57 +0000 (15:32 -0700)
committerSoren Stoutner <soren@stoutner.com>
Thu, 11 Jul 2019 22:32:57 +0000 (15:32 -0700)
29 files changed:
.idea/dictionaries/soren.xml
app/src/main/assets/blocklists/ultralist.txt [new file with mode: 0644]
app/src/main/assets/de/guide_requests_dark.html
app/src/main/assets/de/guide_requests_light.html
app/src/main/assets/en/guide_requests_dark.html
app/src/main/assets/en/guide_requests_light.html
app/src/main/assets/es/guide_requests_dark.html
app/src/main/assets/es/guide_requests_light.html
app/src/main/assets/it/guide_requests_dark.html
app/src/main/assets/it/guide_requests_light.html
app/src/main/assets/ru/guide_requests_dark.html
app/src/main/assets/ru/guide_requests_light.html
app/src/main/assets/tr/guide_requests_dark.html
app/src/main/assets/tr/guide_requests_light.html
app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/asynctasks/PopulateBlocklists.java
app/src/main/java/com/stoutner/privacybrowser/fragments/AboutTabFragment.java
app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java
app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java
app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.java
app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.java
app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.java
app/src/main/res/layout/about_tab_version.xml
app/src/main/res/layout/domain_settings_fragment.xml
app/src/main/res/menu/webview_options_menu.xml
app/src/main/res/values/strings.xml
app/src/main/res/xml/preferences.xml
build.gradle

index 26f04bc..0826846 100644 (file)
       <w>torproject</w>
       <w>uidh</w>
       <w>uids</w>
+      <w>ultralist</w>
       <w>ultraprivacy</w>
       <w>uname</w>
       <w>uncheck</w>
diff --git a/app/src/main/assets/blocklists/ultralist.txt b/app/src/main/assets/blocklists/ultralist.txt
new file mode 100644 (file)
index 0000000..bde7621
--- /dev/null
@@ -0,0 +1,10 @@
+[Adblock Plus 2.0]
+! Version: 1
+! Title: UltraList
+! Last modified: 9 July 2019 18:11 UTC
+! Expires: 90 days (update frequency)
+! Homepage: https://www.stoutner.com/privacy-browser/blocklists/ultralist/
+! Licence: GPLv3+ http://www.gnu.org/licenses/gpl-3.0.html
+!
+! There should be no `adservice` on my system.  <https://redmine.stoutner.com/issues/450>
+adservice
index d081c8f..1083b6e 100644 (file)
@@ -73,8 +73,9 @@
                        Dies kann manchmal zu "false positives" führen, bei denen Ressourcen erlaubt oder blockiert werden, die in den originalen Einträgen anders intendiert wären.
                        Eine detailiertere Beschreibung, wie die Listen-Einträge abgearbeitet werden, ist unter <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a> verfügbar.</p>
 
-               <p>Privacy Browser hat zwei weitere Sperrlisten: <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>, welche Tracker blockiert, die EasyPrivacy erlaubt,
-            und eine andere, die alle Drittanbieter-Anfragen blockiert.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
                        Eine Anfrage wird dabei nur als Drittanbieter-Anfrage gewertet, wenn die Basis-Domain der Anfrage eine andere ist als die Basis-Domain der angefragten URL.
                        Lädt zum Beispiel die Seite <code>www.website.com</code> ein Bild von <code>images.website.com</code>, wird diese Anfrage nicht als Drittanbieter-Anfrage gewertet,
             da die beiden Anfragen dieselbe Basis-Domain <code>website.com</code> haben.
index d8f5057..6e509a2 100644 (file)
@@ -73,8 +73,9 @@
             Dies kann manchmal zu "false positives" führen, bei denen Ressourcen erlaubt oder blockiert werden, die in den originalen Einträgen anders intendiert wären.
             Eine detailiertere Beschreibung, wie die Listen-Einträge abgearbeitet werden, ist unter <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a> verfügbar.</p>
 
-        <p>Privacy Browser hat zwei weitere Sperrlisten: <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>, welche Tracker blockiert, die EasyPrivacy erlaubt,
-            und eine andere, die alle Drittanbieter-Anfragen blockiert.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
             Eine Anfrage wird dabei nur als Drittanbieter-Anfrage gewertet, wenn die Basis-Domain der Anfrage eine andere ist als die Basis-Domain der angefragten URL.
             Lädt zum Beispiel die Seite <code>www.website.com</code> ein Bild von <code>images.website.com</code>, wird diese Anfrage nicht als Drittanbieter-Anfrage gewertet,
             da die beiden Anfragen dieselbe Basis-Domain <code>website.com</code> haben.
index 6e531f2..0f5c33c 100644 (file)
@@ -69,9 +69,9 @@
             This can sometimes lead to false positives, where resources are allowed or blocked in ways that weren’t intended by the original entry.
             A more detailed description of how the blocklist entries are processed is available at <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a>.</p>
 
-        <p>Privacy Browser has two additional blocklists,
-            one called <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a> that blocks trackers that EasyPrivacy allows,
-            and the other that blocks all third-party requests.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
             A request is only considered third-party if the base domain of the request is different than the base domain of the URL.
             For example, if <code>www.website.com</code> loads a picture from <code>images.website.com</code>,
             this is not blocked as a third-party request because they both share the same base domain of <code>website.com</code>.
index bde2af7..87ac5ad 100644 (file)
@@ -69,9 +69,9 @@
             This can sometimes lead to false positives, where resources are allowed or blocked in ways that weren’t intended by the original entry.
             A more detailed description of how the blocklist entries are processed is available at <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a>.</p>
 
-        <p>Privacy Browser has two additional blocklists,
-            one called <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a> that blocks trackers that EasyPrivacy allows,
-            and the other that blocks all third-party requests.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
             A request is only considered third-party if the base domain of the request is different than the base domain of the URL.
             For example, if <code>www.website.com</code> loads a picture from <code>images.website.com</code>,
             this is not blocked as a third-party request because they both share the same base domain of <code>website.com</code>.
index 297fc1e..c289343 100644 (file)
             Esto puede conducir a veces a falsos positivos, en los que los recursos se permiten o bloquean de formas que no estaban previstas en la entrada original.
             Una descripción más detallada de cómo se procesan las entradas de la lista de bloqueo está disponible en <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a>.</p>
 
-        <p>Navegador Privado tiene 2 listas de bloqueo adicionales,
-            una llamada <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">Ultra Privacidad</a> que bloquea rastreadores que permite EasyPrivacy,
-            y otra que bloquea todas las solicitudes de terceras partes. Una solicitud sólo se considera de terceras partes si el dominio base de la solicitud es diferente del dominio base de la URL.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
+            Una solicitud sólo se considera de terceras partes si el dominio base de la solicitud es diferente del dominio base de la URL.
             Por ejemplo, si <code>www.website.com</code> carga una imagen de <code>images.website.com</code>,
             esto no se bloquea como petición de una tercera parte porque ambos comparten el mismo dominio base de <code>website.com</code>.
             El bloqueo de todas las solicitudes de terceras partes aumenta la privacidad, pero esta lista de bloqueo está desactivada por defecto porque rompe un gran número de páginas web.</p>
index 4344a5e..f400818 100644 (file)
             Esto puede conducir a veces a falsos positivos, en los que los recursos se permiten o bloquean de formas que no estaban previstas en la entrada original.
             Una descripción más detallada de cómo se procesan las entradas de la lista de bloqueo está disponible en <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a>.</p>
 
-        <p>Navegador Privado tiene 2 listas de bloqueo adicionales,
-            una llamada <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">Ultra Privacidad</a> que bloquea rastreadores que permite EasyPrivacy,
-            y otra que bloquea todas las solicitudes de terceras partes. Una solicitud sólo se considera de terceras partes si el dominio base de la solicitud es diferente del dominio base de la URL.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
+            Una solicitud sólo se considera de terceras partes si el dominio base de la solicitud es diferente del dominio base de la URL.
             Por ejemplo, si <code>www.website.com</code> carga una imagen de <code>images.website.com</code>,
             esto no se bloquea como petición de una tercera parte porque ambos comparten el mismo dominio base de <code>website.com</code>.
             El bloqueo de todas las solicitudes de terceras partes aumenta la privacidad, pero esta lista de bloqueo está desactivada por defecto porque rompe un gran número de páginas web.</p>
index a7ccebe..8e69863 100644 (file)
@@ -74,9 +74,9 @@
             Questo approccio potrebbe a volte portare ad avere falsi positivi, nel caso in cui le risorse siano bloccate o permesse in modi che non erano previsti dall'elemento originale.
             Una descrizione più dettagliata su come sono processati gli elementi delle liste di blocco è disponibile su <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a>.</p>
 
-        <p>Privacy Browser ha due liste di blocco addizionali,
-            una chiamata <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a> che blocca i tracciamenti permessi da EasyPrivacy,
-            e l'altra che blocca tutte le richieste di terze parti.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
             Una richiesta è considerata di terze parti solo se il dominio di base della richiesta è diverso dal dominio di base della URL.
             Ad esempio se <code>www.website.com</code> carica un'immagine da <code>images.website.com</code>,
             questa non è bloccata come richiesta di terze parti, perchè il dominio di base è lo stesso: <code>website.com</code>.
index 3d8eaf5..7eaa309 100644 (file)
@@ -74,9 +74,9 @@
             Questo approccio potrebbe a volte portare ad avere falsi positivi, nel caso in cui le risorse siano bloccate o permesse in modi che non erano previsti dall'elemento originale.
             Una descrizione più dettagliata su come sono processati gli elementi delle liste di blocco è disponibile su <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a>.</p>
 
-        <p>Privacy Browser ha due liste di blocco addizionali,
-            una chiamata <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a> che blocca i tracciamenti permessi da EasyPrivacy,
-            e l'altra che blocca tutte le richieste di terze parti.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
             Una richiesta è considerata di terze parti solo se il dominio di base della richiesta è diverso dal dominio di base della URL.
             Ad esempio se <code>www.website.com</code> carica un'immagine da <code>images.website.com</code>,
             questa non è bloccata come richiesta di terze parti, perchè il dominio di base è lo stesso: <code>website.com</code>.
index 4ec554d..72bdf4e 100644 (file)
@@ -71,8 +71,9 @@
             Иногда это может привести к ложным срабатываниям, когда ресурсы разрешаются или блокируются способами, которые не были предназначены для исходной записи.
             Более подробное описание способа обработки записей списка блокировки доступно на <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a>.</p>
 
-        <p>Privacy Browser имеет два дополнительных списка блокировки, один из которых <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>,
-            предназначеный для блокировки трекеров, которые EasyPrivacy разрешает, а другой блокирует все сторонние запросы.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
             Например, если <code>www.website.com</code> загружает изображение с сайта <code>images.website.com</code>,
             запрос не будет считаться сторонним и не будет заблокирован, так как они оба используют один и тот же базовый домен <code>website.com</code>.
             Блокировка всех сторонних запросов увеличивает конфиденциальность, но этот список блокировки по умолчанию отключен, поскольку он ломает большое количество веб-сайтов.</p>
index f2d036a..63f3878 100644 (file)
@@ -71,8 +71,9 @@
             Иногда это может привести к ложным срабатываниям, когда ресурсы разрешаются или блокируются способами, которые не были предназначены для исходной записи.
             Более подробное описание способа обработки записей списка блокировки доступно на <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a>.</p>
 
-        <p>Privacy Browser имеет два дополнительных списка блокировки, один из которых <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>,
-            предназначеный для блокировки трекеров, которые EasyPrivacy разрешает, а другой блокирует все сторонние запросы.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
             Например, если <code>www.website.com</code> загружает изображение с сайта <code>images.website.com</code>,
             запрос не будет считаться сторонним и не будет заблокирован, так как они оба используют один и тот же базовый домен <code>website.com</code>.
             Блокировка всех сторонних запросов увеличивает конфиденциальность, но этот список блокировки по умолчанию отключен, поскольку он ломает большое количество веб-сайтов.</p>
index 59b43a8..533a419 100644 (file)
@@ -71,8 +71,9 @@
             Bu durum, bazen, kaynakların orijinal girdi tarafından amaçlanmayan şekillerde izin verildiği veya engellendiği yanlış pozitif (false positive) durumuna yol açabilir.
             Engel listesi girdilerinin nasıl işlendiğine dair daha ayrıntılı bir açıklama <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a> adresinde bulunabilir.</p>
 
-        <p>Privacy Browser, EasyPrivacy’nin izin verdiği izleyicileri engelleyen <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
-            adında ve tüm üçüncü taraf istekleri engelleyen başka bir tane olmak üzere 2 tane ek engel listesi içerir.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
             Bir istek yalnızca, isteğin temel domaini bağlantının temel domaininden farklıysa üçüncü taraf olarak kabul edilir.
             Örneğin, <code>www.website.com</code> adresi <code>images.website.com</code> adresinden bir resim yüklüyorsa,
             her ikisi de aynı temel domaini (<code>website.com</code>) paylaştığı için bu üçüncü taraf isteği olarak engellenmez.
index 2c55a62..3039f39 100644 (file)
@@ -71,8 +71,9 @@
             Bu durum, bazen, kaynakların orijinal girdi tarafından amaçlanmayan şekillerde izin verildiği veya engellendiği yanlış pozitif (false positive) durumuna yol açabilir.
             Engel listesi girdilerinin nasıl işlendiğine dair daha ayrıntılı bir açıklama <a href="https://www.stoutner.com/privacy-browser/blocklists/">stoutner.com</a> adresinde bulunabilir.</p>
 
-        <p>Privacy Browser, EasyPrivacy’nin izin verdiği izleyicileri engelleyen <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
-            adında ve tüm üçüncü taraf istekleri engelleyen başka bir tane olmak üzere 2 tane ek engel listesi içerir.
+        <p>Privacy Browser has three additional blocklists.
+            <a href="https://www.stoutner.com/privacy-browser/blocklists/ultralist/">UltraList</a> and <a href="https://www.stoutner.com/privacy-browser/blocklists/ultraprivacy/">UltraPrivacy</a>
+            block ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
             Bir istek yalnızca, isteğin temel domaini bağlantının temel domaininden farklıysa üçüncü taraf olarak kabul edilir.
             Örneğin, <code>www.website.com</code> adresi <code>images.website.com</code> adresinden bir resim yüklüyorsa,
             her ikisi de aynı temel domaini (<code>website.com</code>) paylaştığı için bu üçüncü taraf isteği olarak engellenmez.
index e73b94e..037ed59 100644 (file)
@@ -687,6 +687,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
         Switch easyPrivacySwitch = view.findViewById(R.id.easyprivacy_switch);
         Switch fanboysAnnoyanceSwitch = view.findViewById(R.id.fanboys_annoyance_list_switch);
         Switch fanboysSocialBlockingSwitch = view.findViewById(R.id.fanboys_social_blocking_list_switch);
+        Switch ultraListSwitch = view.findViewById(R.id.ultralist_switch);
         Switch ultraPrivacySwitch = view.findViewById(R.id.ultraprivacy_switch);
         Switch blockAllThirdPartyRequestsSwitch = view.findViewById(R.id.block_all_third_party_requests_switch);
         Spinner userAgentSpinner = view.findViewById(R.id.user_agent_spinner);
@@ -703,16 +704,17 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
 
         // Extract the data for the domain settings.
         String domainNameString = domainNameEditText.getText().toString();
-        boolean javaScriptEnabled = javaScriptSwitch.isChecked();
-        boolean firstPartyCookiesEnabled = firstPartyCookiesSwitch.isChecked();
-        boolean thirdPartyCookiesEnabled = thirdPartyCookiesSwitch.isChecked();
-        boolean domStorageEnabled  = domStorageSwitch.isChecked();
-        boolean formDataEnabled = formDataSwitch.isChecked();  // Form data can be removed once the minimum API >= 26.
-        boolean easyListEnabled = easyListSwitch.isChecked();
-        boolean easyPrivacyEnabled = easyPrivacySwitch.isChecked();
-        boolean fanboysAnnoyanceEnabled = fanboysAnnoyanceSwitch.isChecked();
-        boolean fanboysSocialBlockingEnabled = fanboysSocialBlockingSwitch.isChecked();
-        boolean ultraPrivacyEnabled = ultraPrivacySwitch.isChecked();
+        boolean javaScript = javaScriptSwitch.isChecked();
+        boolean firstPartyCookies = firstPartyCookiesSwitch.isChecked();
+        boolean thirdPartyCookies = thirdPartyCookiesSwitch.isChecked();
+        boolean domStorage  = domStorageSwitch.isChecked();
+        boolean formData = formDataSwitch.isChecked();  // Form data can be removed once the minimum API >= 26.
+        boolean easyList = easyListSwitch.isChecked();
+        boolean easyPrivacy = easyPrivacySwitch.isChecked();
+        boolean fanboysAnnoyance = fanboysAnnoyanceSwitch.isChecked();
+        boolean fanboysSocialBlocking = fanboysSocialBlockingSwitch.isChecked();
+        boolean ultraList = ultraListSwitch.isChecked();
+        boolean ultraPrivacy = ultraPrivacySwitch.isChecked();
         boolean blockAllThirdPartyRequests = blockAllThirdPartyRequestsSwitch.isChecked();
         int userAgentPosition = userAgentSpinner.getSelectedItemPosition();
         int fontSizePosition = fontSizeSpinner.getSelectedItemPosition();
@@ -750,9 +752,9 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
         int fontSizeInt = Integer.parseInt(resources.getStringArray(R.array.domain_settings_font_size_entry_values)[fontSizePosition]);
 
         // Save the domain settings.
-        domainsDatabaseHelper.updateDomain(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled,
-                    domStorageEnabled, formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, ultraPrivacyEnabled, blockAllThirdPartyRequests,
-                    userAgentName, fontSizeInt, swipeToRefreshInt, nightModeInt, wideViewportInt, displayWebpageImagesInt, pinnedSslCertificate, pinnedIpAddress);
+        domainsDatabaseHelper.updateDomain(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScript, firstPartyCookies, thirdPartyCookies, domStorage, formData, easyList, easyPrivacy,
+                fanboysAnnoyance, fanboysSocialBlocking, ultraList, ultraPrivacy, blockAllThirdPartyRequests, userAgentName, fontSizeInt, swipeToRefreshInt, nightModeInt, wideViewportInt,
+                displayWebpageImagesInt, pinnedSslCertificate, pinnedIpAddress);
 
         // Update the pinned SSL certificate if a new one is checked.
         if (currentWebsiteCertificateRadioButton.isChecked()) {
@@ -792,7 +794,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
             }
         };
 
-        // Update the `ListView`.
+        // Update the list view.
         domainsListView.setAdapter(domainsCursorAdapter);
 
         // Display the domain settings in the second pane if operating in two pane mode and the database contains at least one domain.
index 4d3a4da..097c8af 100644 (file)
@@ -215,6 +215,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private ArrayList<List<String[]>> easyPrivacy;
     private ArrayList<List<String[]>> fanboysAnnoyanceList;
     private ArrayList<List<String[]>> fanboysSocialList;
+    private ArrayList<List<String[]>> ultraList;
     private ArrayList<List<String[]>> ultraPrivacy;
 
     // `webViewDefaultUserAgent` is used in `onCreate()` and `onPrepareOptionsMenu()`.
@@ -725,6 +726,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         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 ultraListMenuItem = menu.findItem(R.id.ultralist);
         MenuItem ultraPrivacyMenuItem = menu.findItem(R.id.ultraprivacy);
         MenuItem blockAllThirdPartyRequestsMenuItem = menu.findItem(R.id.block_all_third_party_requests);
         MenuItem fontSizeMenuItem = menu.findItem(R.id.font_size);
@@ -759,11 +761,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Set the status of the menu item checkboxes.
             domStorageMenuItem.setChecked(currentWebView.getSettings().getDomStorageEnabled());
             saveFormDataMenuItem.setChecked(currentWebView.getSettings().getSaveFormData());  // Form data can be removed once the minimum API >= 26.
-            easyListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_LIST));
-            easyPrivacyMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_PRIVACY));
+            easyListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASYLIST));
+            easyPrivacyMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASYPRIVACY));
             fanboysAnnoyanceListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST));
             fanboysSocialBlockingListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST));
-            ultraPrivacyMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRA_PRIVACY));
+            ultraListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRALIST));
+            ultraPrivacyMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRAPRIVACY));
             blockAllThirdPartyRequestsMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.THIRD_PARTY_REQUESTS));
             swipeToRefreshMenuItem.setChecked(currentWebView.getSwipeToRefresh());
             wideViewportMenuItem.setChecked(currentWebView.getSettings().getUseWideViewPort());
@@ -772,11 +775,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             // Initialize the display names for the blocklists with the number of blocked requests.
             blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + currentWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-            easyListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASY_LIST) + " - " + getString(R.string.easylist));
-            easyPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASY_PRIVACY) + " - " + getString(R.string.easyprivacy));
+            easyListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASYLIST) + " - " + getString(R.string.easylist));
+            easyPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASYPRIVACY) + " - " + getString(R.string.easyprivacy));
             fanboysAnnoyanceListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST) + " - " + getString(R.string.fanboys_annoyance_list));
             fanboysSocialBlockingListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST) + " - " + getString(R.string.fanboys_social_blocking_list));
-            ultraPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.ULTRA_PRIVACY) + " - " + getString(R.string.ultraprivacy));
+            ultraListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.ULTRALIST) + " - " + getString(R.string.ultralist));
+            ultraPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.ULTRAPRIVACY) + " - " + getString(R.string.ultraprivacy));
             blockAllThirdPartyRequestsMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.THIRD_PARTY_REQUESTS) + " - " + getString(R.string.block_all_third_party_requests));
 
             // Only modify third-party cookies if the API >= 21.
@@ -1273,10 +1277,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.easylist:
                 // Toggle the EasyList status.
-                currentWebView.enableBlocklist(NestedScrollWebView.EASY_LIST, !currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_LIST));
+                currentWebView.enableBlocklist(NestedScrollWebView.EASYLIST, !currentWebView.isBlocklistEnabled(NestedScrollWebView.EASYLIST));
 
                 // Update the menu checkbox.
-                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_LIST));
+                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASYLIST));
 
                 // Reload the current WebView.
                 currentWebView.reload();
@@ -1286,10 +1290,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.easyprivacy:
                 // Toggle the EasyPrivacy status.
-                currentWebView.enableBlocklist(NestedScrollWebView.EASY_PRIVACY, !currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_PRIVACY));
+                currentWebView.enableBlocklist(NestedScrollWebView.EASYPRIVACY, !currentWebView.isBlocklistEnabled(NestedScrollWebView.EASYPRIVACY));
 
                 // Update the menu checkbox.
-                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_PRIVACY));
+                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASYPRIVACY));
 
                 // Reload the current WebView.
                 currentWebView.reload();
@@ -1327,12 +1331,25 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Consume the event.
                 return true;
 
+            case R.id.ultralist:
+                // Toggle the UltraList status.
+                currentWebView.enableBlocklist(NestedScrollWebView.ULTRALIST, !currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRALIST));
+
+                // Update the menu checkbox.
+                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRALIST));
+
+                // Reload the current WebView.
+                currentWebView.reload();
+
+                // Consume the event.
+                return true;
+
             case R.id.ultraprivacy:
                 // Toggle the UltraPrivacy status.
-                currentWebView.enableBlocklist(NestedScrollWebView.ULTRA_PRIVACY, !currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRA_PRIVACY));
+                currentWebView.enableBlocklist(NestedScrollWebView.ULTRAPRIVACY, !currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRAPRIVACY));
 
                 // Update the menu checkbox.
-                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRA_PRIVACY));
+                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRAPRIVACY));
 
                 // Reload the current WebView.
                 currentWebView.reload();
@@ -1924,7 +1941,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // Create a string array for the blocklist versions.
                 String[] blocklistVersions = new String[] {easyList.get(0).get(0)[0], easyPrivacy.get(0).get(0)[0], fanboysAnnoyanceList.get(0).get(0)[0], fanboysSocialList.get(0).get(0)[0],
-                        ultraPrivacy.get(0).get(0)[0]};
+                        ultraList.get(0).get(0)[0], ultraPrivacy.get(0).get(0)[0]};
 
                 // Add the blocklist versions to the intent.
                 aboutIntent.putExtra("blocklist_versions", blocklistVersions);
@@ -3720,15 +3737,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 nestedScrollWebView.getSettings().setDomStorageEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
                 // Form data can be removed once the minimum API >= 26.
                 boolean saveFormData = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);
-                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_LIST,
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASYLIST,
                         currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);
-                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_PRIVACY,
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASYPRIVACY,
                         currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);
                 nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST,
                         currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);
                 nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST,
                         currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1);
-                nestedScrollWebView.enableBlocklist(NestedScrollWebView.ULTRA_PRIVACY,
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.ULTRALIST, currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST)) == 1);
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.ULTRAPRIVACY,
                         currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1);
                 nestedScrollWebView.enableBlocklist(NestedScrollWebView.THIRD_PARTY_REQUESTS,
                         currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1);
@@ -3942,11 +3960,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 boolean defaultThirdPartyCookiesEnabled = sharedPreferences.getBoolean("third_party_cookies", false);
                 nestedScrollWebView.getSettings().setDomStorageEnabled(sharedPreferences.getBoolean("dom_storage", false));
                 boolean saveFormData = sharedPreferences.getBoolean("save_form_data", false);  // Form data can be removed once the minimum API >= 26.
-                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_LIST, sharedPreferences.getBoolean("easylist", true));
-                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_PRIVACY, sharedPreferences.getBoolean("easyprivacy", true));
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASYLIST, sharedPreferences.getBoolean("easylist", true));
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASYPRIVACY, sharedPreferences.getBoolean("easyprivacy", true));
                 nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST, sharedPreferences.getBoolean("fanboys_annoyance_list", true));
                 nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST, sharedPreferences.getBoolean("fanboys_social_blocking_list", true));
-                nestedScrollWebView.enableBlocklist(NestedScrollWebView.ULTRA_PRIVACY, sharedPreferences.getBoolean("ultraprivacy", true));
+                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));
                 nestedScrollWebView.setNightMode(sharedPreferences.getBoolean("night_mode", false));
 
@@ -4408,7 +4427,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         easyPrivacy = combinedBlocklists.get(1);
         fanboysAnnoyanceList = combinedBlocklists.get(2);
         fanboysSocialList = combinedBlocklists.get(3);
-        ultraPrivacy = combinedBlocklists.get(4);
+        ultraList = combinedBlocklists.get(4);
+        ultraPrivacy = combinedBlocklists.get(5);
 
         // Add the first tab.
         addNewTab("");
@@ -5426,8 +5446,48 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     return emptyWebResourceResponse;
                 }
 
+                // Check UltraList if it is enabled.
+                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.ULTRALIST)) {
+                    // Check the URL against UltraList.
+                    String[] ultraListResults = blocklistHelper.checkBlocklist(currentDomain, url, isThirdPartyRequest, ultraList);
+
+                    // Process the UltraList results.
+                    if (ultraListResults[0].equals(BlocklistHelper.REQUEST_BLOCKED)) {  // The resource request matched UltraLists's blacklist.
+                        // Add the result to the resource requests.
+                        nestedScrollWebView.addResourceRequest(new String[] {ultraListResults[0], ultraListResults[1], ultraListResults[2], ultraListResults[3], ultraListResults[4], ultraListResults[5]});
+
+                        // Increment the blocked requests counters.
+                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
+                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.ULTRALIST);
+
+                        // Update the titles of the blocklist menu items if the WebView is currently displayed.
+                        if (webViewDisplayed) {
+                            // Updating the UI must be run from the UI thread.
+                            activity.runOnUiThread(() -> {
+                                // Update the menu item titles.
+                                navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
+
+                                // Update the options menu if it has been populated.
+                                if (optionsMenu != null) {
+                                    optionsMenu.findItem(R.id.blocklists).setTitle(getString(R.string.blocklists) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
+                                    optionsMenu.findItem(R.id.ultralist).setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.ULTRALIST) + " - " + getString(R.string.ultralist));
+                                }
+                            });
+                        }
+
+                        // The resource request was blocked.  Return an empty web resource response.
+                        return emptyWebResourceResponse;
+                    } else if (ultraListResults[0].equals(BlocklistHelper.REQUEST_ALLOWED)) {  // The resource request matched UltraList's whitelist.
+                        // Add a whitelist entry to the resource requests array.
+                        nestedScrollWebView.addResourceRequest(new String[] {ultraListResults[0], ultraListResults[1], ultraListResults[2], ultraListResults[3], ultraListResults[4], ultraListResults[5]});
+
+                        // The resource request has been allowed by UltraPrivacy.  `return null` loads the requested resource.
+                        return null;
+                    }
+                }
+
                 // Check UltraPrivacy if it is enabled.
-                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.ULTRA_PRIVACY)) {
+                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.ULTRAPRIVACY)) {
                     // Check the URL against UltraPrivacy.
                     String[] ultraPrivacyResults = blocklistHelper.checkBlocklist(currentDomain, url, isThirdPartyRequest, ultraPrivacy);
 
@@ -5439,7 +5499,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Increment the blocked requests counters.
                         nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
-                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.ULTRA_PRIVACY);
+                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.ULTRAPRIVACY);
 
                         // Update the titles of the blocklist menu items if the WebView is currently displayed.
                         if (webViewDisplayed) {
@@ -5451,7 +5511,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                                 // Update the options menu if it has been populated.
                                 if (optionsMenu != null) {
                                     optionsMenu.findItem(R.id.blocklists).setTitle(getString(R.string.blocklists) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-                                    optionsMenu.findItem(R.id.ultraprivacy).setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.ULTRA_PRIVACY) + " - " + getString(R.string.ultraprivacy));
+                                    optionsMenu.findItem(R.id.ultraprivacy).setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.ULTRAPRIVACY) + " - " + getString(R.string.ultraprivacy));
                                 }
                             });
                         }
@@ -5469,7 +5529,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
 
                 // Check EasyList if it is enabled.
-                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.EASY_LIST)) {
+                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.EASYLIST)) {
                     // Check the URL against EasyList.
                     String[] easyListResults = blocklistHelper.checkBlocklist(currentDomain, url, isThirdPartyRequest, easyList);
 
@@ -5480,7 +5540,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Increment the blocked requests counters.
                         nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
-                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.EASY_LIST);
+                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.EASYLIST);
 
                         // Update the titles of the blocklist menu items if the WebView is currently displayed.
                         if (webViewDisplayed) {
@@ -5492,7 +5552,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                                 // Update the options menu if it has been populated.
                                 if (optionsMenu != null) {
                                     optionsMenu.findItem(R.id.blocklists).setTitle(getString(R.string.blocklists) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-                                    optionsMenu.findItem(R.id.easylist).setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.EASY_LIST) + " - " + getString(R.string.easylist));
+                                    optionsMenu.findItem(R.id.easylist).setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.EASYLIST) + " - " + getString(R.string.easylist));
                                 }
                             });
                         }
@@ -5506,7 +5566,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
 
                 // Check EasyPrivacy if it is enabled.
-                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.EASY_PRIVACY)) {
+                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.EASYPRIVACY)) {
                     // Check the URL against EasyPrivacy.
                     String[] easyPrivacyResults = blocklistHelper.checkBlocklist(currentDomain, url, isThirdPartyRequest, easyPrivacy);
 
@@ -5518,7 +5578,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Increment the blocked requests counters.
                         nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
-                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.EASY_PRIVACY);
+                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.EASYPRIVACY);
 
                         // Update the titles of the blocklist menu items if the WebView is currently displayed.
                         if (webViewDisplayed) {
@@ -5530,7 +5590,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                                 // Update the options menu if it has been populated.
                                 if (optionsMenu != null) {
                                     optionsMenu.findItem(R.id.blocklists).setTitle(getString(R.string.blocklists) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-                                    optionsMenu.findItem(R.id.easyprivacy).setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.EASY_PRIVACY) + " - " + getString(R.string.easyprivacy));
+                                    optionsMenu.findItem(R.id.easyprivacy).setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.EASYPRIVACY) + " - " + getString(R.string.easyprivacy));
                                 }
                             });
                         }
index 7a7fc4d..7530636 100644 (file)
@@ -127,6 +127,12 @@ public class PopulateBlocklists extends AsyncTask<Void, String, ArrayList<ArrayL
             ArrayList<List<String[]>> fanboysSocialList = blocklistHelper.parseBlocklist(context.getAssets(), "blocklists/fanboy-social.txt");
 
 
+            // Update the progress.
+            publishProgress(context.getString(R.string.loading_ultralist));
+
+            // Populate UltraList.
+            ArrayList<List<String[]>> ultraList = blocklistHelper.parseBlocklist(context.getAssets(), "blocklists/ultralist.txt");
+
             // Update the progress.
             publishProgress(context.getString(R.string.loading_ultraprivacy));
 
@@ -139,6 +145,7 @@ public class PopulateBlocklists extends AsyncTask<Void, String, ArrayList<ArrayL
             combinedBlocklists.add(easyPrivacy);
             combinedBlocklists.add(fanboysAnnoyanceList);
             combinedBlocklists.add(fanboysSocialList);
+            combinedBlocklists.add(ultraList);
             combinedBlocklists.add(ultraPrivacy);
         }
 
index 27db5d1..8496d00 100644 (file)
@@ -112,7 +112,7 @@ public class AboutTabFragment extends Fragment {
             // Setting false at the end of inflater.inflate does not attach the inflated layout as a child of container.  The fragment will take care of attaching the root automatically.
             tabLayout = layoutInflater.inflate(R.layout.about_tab_version, container, false);
 
-            // Get handles for the `TextViews`.
+            // Get handles for the text views.
             TextView versionTextView = tabLayout.findViewById(R.id.version);
             TextView brandTextView = tabLayout.findViewById(R.id.brand);
             TextView manufacturerTextView = tabLayout.findViewById(R.id.manufacturer);
@@ -131,6 +131,7 @@ public class AboutTabFragment extends Fragment {
             TextView easyPrivacyTextView = tabLayout.findViewById(R.id.easyprivacy);
             TextView fanboyAnnoyanceTextView = tabLayout.findViewById(R.id.fanboy_annoyance);
             TextView fanboySocialTextView = tabLayout.findViewById(R.id.fanboy_social);
+            TextView ultraListTextView = tabLayout.findViewById(R.id.ultralist);
             TextView ultraPrivacyTextView = tabLayout.findViewById(R.id.ultraprivacy);
             TextView certificateIssuerDNTextView = tabLayout.findViewById(R.id.certificate_issuer_dn);
             TextView certificateSubjectDNTextView = tabLayout.findViewById(R.id.certificate_subject_dn);
@@ -154,6 +155,7 @@ public class AboutTabFragment extends Fragment {
             String easyPrivacyLabel = getString(R.string.easyprivacy_label) + "  ";
             String fanboyAnnoyanceLabel = getString(R.string.fanboy_annoyance_label) + "  ";
             String fanboySocialLabel = getString(R.string.fanboy_social_label) + "  ";
+            String ultraListLabel = getString(R.string.ultralist_label) + "  ";
             String ultraPrivacyLabel = getString(R.string.ultraprivacy_label) + "  ";
             String issuerDNLabel = getString(R.string.issuer_dn) + "  ";
             String subjectDNLabel = getString(R.string.subject_dn) + "  ";
@@ -163,7 +165,7 @@ public class AboutTabFragment extends Fragment {
             String serialNumberLabel = getString(R.string.serial_number) + "  ";
             String signatureAlgorithmLabel = getString(R.string.signature_algorithm) + "  ";
 
-            // `webViewLayout` is only used to get the default user agent from `bare_webview`.  It is not used to render content on the screen.
+            // The WebView layout is only used to get the default user agent from `bare_webview`.  It is not used to render content on the screen.
             // Once the minimum API >= 26 this can be accomplished with the WebView package info.
             View webViewLayout = layoutInflater.inflate(R.layout.bare_webview, container, false);
             WebView tabLayoutWebView = webViewLayout.findViewById(R.id.bare_webview);
@@ -212,7 +214,8 @@ public class AboutTabFragment extends Fragment {
             SpannableStringBuilder easyPrivacyStringBuilder = new SpannableStringBuilder(easyPrivacyLabel + blocklistVersions[1]);
             SpannableStringBuilder fanboyAnnoyanceStringBuilder = new SpannableStringBuilder(fanboyAnnoyanceLabel + blocklistVersions[2]);
             SpannableStringBuilder fanboySocialStringBuilder = new SpannableStringBuilder(fanboySocialLabel + blocklistVersions[3]);
-            SpannableStringBuilder ultraPrivacyStringBuilder = new SpannableStringBuilder(ultraPrivacyLabel + blocklistVersions[4]);
+            SpannableStringBuilder ultraListStringBuilder = new SpannableStringBuilder(ultraListLabel + blocklistVersions[4]);
+            SpannableStringBuilder ultraPrivacyStringBuilder = new SpannableStringBuilder(ultraPrivacyLabel + blocklistVersions[5]);
 
             // Create the `blueColorSpan` variable.
             ForegroundColorSpan blueColorSpan;
@@ -237,6 +240,7 @@ public class AboutTabFragment extends Fragment {
             easyPrivacyStringBuilder.setSpan(blueColorSpan, easyPrivacyLabel.length(), easyPrivacyStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
             fanboyAnnoyanceStringBuilder.setSpan(blueColorSpan, fanboyAnnoyanceLabel.length(), fanboyAnnoyanceStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
             fanboySocialStringBuilder.setSpan(blueColorSpan, fanboySocialLabel.length(), fanboySocialStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+            ultraListStringBuilder.setSpan(blueColorSpan, ultraListLabel.length(), ultraListStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
             ultraPrivacyStringBuilder.setSpan(blueColorSpan, ultraPrivacyLabel.length(), ultraPrivacyStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
 
             // Display the strings in the text boxes.
@@ -253,6 +257,7 @@ public class AboutTabFragment extends Fragment {
             easyPrivacyTextView.setText(easyPrivacyStringBuilder);
             fanboyAnnoyanceTextView.setText(fanboyAnnoyanceStringBuilder);
             fanboySocialTextView.setText(fanboySocialStringBuilder);
+            ultraListTextView.setText(ultraListStringBuilder);
             ultraPrivacyTextView.setText(ultraPrivacyStringBuilder);
 
             // Only populate the radio text view if there is a radio in the device.
@@ -327,9 +332,10 @@ public class AboutTabFragment extends Fragment {
             // Display the package signature.
             try {
                 // Get the first package signature.  Suppress the lint warning about the need to be careful in implementing comparison of certificates for security purposes.
-                @SuppressLint("PackageManagerGetSignatures") Signature packageSignature = getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), PackageManager.GET_SIGNATURES).signatures[0];
+                @SuppressLint("PackageManagerGetSignatures") Signature packageSignature = getContext().getPackageManager().getPackageInfo(getContext().getPackageName(),
+                        PackageManager.GET_SIGNATURES).signatures[0];
 
-                // Convert the signature to a `byte[]` `InputStream`.
+                // Convert the signature to a byte array input stream.
                 InputStream certificateByteArrayInputStream = new ByteArrayInputStream(packageSignature.toByteArray());
 
                 // Display the certificate information on the screen.
@@ -381,7 +387,7 @@ public class AboutTabFragment extends Fragment {
             } catch (PackageManager.NameNotFoundException e) {
                 // Do nothing if `PackageManager` says Privacy Browser isn't installed.
             }
-        } else { // load a `WebView` for all the other tabs.  Tab numbers start at 0.
+        } else { // load a WebView for all the other tabs.  Tab numbers start at 0.
             // Setting false at the end of inflater.inflate does not attach the inflated layout as a child of container.  The fragment will take care of attaching the root automatically.
             tabLayout = layoutInflater.inflate(R.layout.bare_webview, container, false);
 
index 5386b77..4007dbf 100644 (file)
@@ -107,29 +107,31 @@ public class DomainSettingsFragment extends Fragment {
 
         // Get handles for the views in the fragment.
         EditText domainNameEditText = domainSettingsView.findViewById(R.id.domain_settings_name_edittext);
-        Switch javaScriptEnabledSwitch = domainSettingsView.findViewById(R.id.javascript_switch);
         ImageView javaScriptImageView = domainSettingsView.findViewById(R.id.javascript_imageview);
-        Switch firstPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.first_party_cookies_switch);
+        Switch javaScriptSwitch = domainSettingsView.findViewById(R.id.javascript_switch);
         ImageView firstPartyCookiesImageView = domainSettingsView.findViewById(R.id.first_party_cookies_imageview);
+        Switch firstPartyCookiesSwitch = domainSettingsView.findViewById(R.id.first_party_cookies_switch);
         LinearLayout thirdPartyCookiesLinearLayout = domainSettingsView.findViewById(R.id.third_party_cookies_linearlayout);
-        Switch thirdPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.third_party_cookies_switch);
         ImageView thirdPartyCookiesImageView = domainSettingsView.findViewById(R.id.third_party_cookies_imageview);
-        Switch domStorageEnabledSwitch = domainSettingsView.findViewById(R.id.dom_storage_switch);
+        Switch thirdPartyCookiesSwitch = domainSettingsView.findViewById(R.id.third_party_cookies_switch);
         ImageView domStorageImageView = domainSettingsView.findViewById(R.id.dom_storage_imageview);
-        Switch formDataEnabledSwitch = domainSettingsView.findViewById(R.id.form_data_switch);  // The form data views can be remove once the minimum API >= 26.
+        Switch domStorageSwitch = domainSettingsView.findViewById(R.id.dom_storage_switch);
         ImageView formDataImageView = domainSettingsView.findViewById(R.id.form_data_imageview);  // The form data views can be remove once the minimum API >= 26.
-        Switch easyListSwitch = domainSettingsView.findViewById(R.id.easylist_switch);
+        Switch formDataSwitch = domainSettingsView.findViewById(R.id.form_data_switch);  // The form data views can be remove once the minimum API >= 26.
         ImageView easyListImageView = domainSettingsView.findViewById(R.id.easylist_imageview);
-        Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.easyprivacy_switch);
+        Switch easyListSwitch = domainSettingsView.findViewById(R.id.easylist_switch);
         ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.easyprivacy_imageview);
-        Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_switch);
+        Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.easyprivacy_switch);
         ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_imageview);
-        Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_switch);
+        Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_switch);
         ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_imageview);
-        Switch ultraPrivacySwitch = domainSettingsView.findViewById(R.id.ultraprivacy_switch);
+        Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_switch);
+        ImageView ultraListImageView = domainSettingsView.findViewById(R.id.ultralist_imageview);
+        Switch ultraListSwitch = domainSettingsView.findViewById(R.id.ultralist_switch);
         ImageView ultraPrivacyImageView = domainSettingsView.findViewById(R.id.ultraprivacy_imageview);
-        Switch blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.block_all_third_party_requests_switch);
+        Switch ultraPrivacySwitch = domainSettingsView.findViewById(R.id.ultraprivacy_switch);
         ImageView blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.block_all_third_party_requests_imageview);
+        Switch blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.block_all_third_party_requests_switch);
         Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.user_agent_spinner);
         TextView userAgentTextView = domainSettingsView.findViewById(R.id.user_agent_textview);
         EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.custom_user_agent_edittext);
@@ -199,16 +201,17 @@ public class DomainSettingsFragment extends Fragment {
 
         // Save the cursor entries as variables.
         String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
-        int javaScriptEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
-        int firstPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
-        int thirdPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
-        int domStorageEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
-        int formDataEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA));  // Form data can be remove once the minimum API >= 26.
-        int easyListEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
-        int easyPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
+        int javaScriptInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
+        int firstPartyCookiesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
+        int thirdPartyCookiesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
+        int domStorageInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
+        int formDataInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA));  // Form data can be remove once the minimum API >= 26.
+        int easyListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
+        int easyPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
         int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
         int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
-        int ultraPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
+        int ultraListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST));
+        int ultraPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
         int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
         String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
         int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
@@ -364,31 +367,31 @@ public class DomainSettingsFragment extends Fragment {
 
         // Disable the JavaScript switch if night mode is enabled.
         if (nightModeEnabled) {
-            javaScriptEnabledSwitch.setEnabled(false);
+            javaScriptSwitch.setEnabled(false);
         } else {
-            javaScriptEnabledSwitch.setEnabled(true);
+            javaScriptSwitch.setEnabled(true);
         }
 
         // Set the JavaScript icon.
-        if ((javaScriptEnabledInt == 1) || nightModeEnabled) {
+        if ((javaScriptInt == 1) || nightModeEnabled) {
             javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
         } else {
             javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
         }
 
         // Set the JavaScript switch status.
-        if (javaScriptEnabledInt == 1) {  // JavaScript is enabled.
-            javaScriptEnabledSwitch.setChecked(true);
+        if (javaScriptInt == 1) {  // JavaScript is enabled.
+            javaScriptSwitch.setChecked(true);
         } else {  // JavaScript is disabled.
-            javaScriptEnabledSwitch.setChecked(false);
+            javaScriptSwitch.setChecked(false);
         }
 
         // Set the first-party cookies status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
-        if (firstPartyCookiesEnabledInt == 1) {  // First-party cookies are enabled.
-            firstPartyCookiesEnabledSwitch.setChecked(true);
+        if (firstPartyCookiesInt == 1) {  // First-party cookies are enabled.
+            firstPartyCookiesSwitch.setChecked(true);
             firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
         } else {  // First-party cookies are disabled.
-            firstPartyCookiesEnabledSwitch.setChecked(false);
+            firstPartyCookiesSwitch.setChecked(false);
 
             // Set the icon according to the theme.
             if (darkTheme) {
@@ -401,13 +404,13 @@ public class DomainSettingsFragment extends Fragment {
         // Only display third-party cookies if SDK_INT >= 21.
         if (Build.VERSION.SDK_INT >= 21) {  // Third-party cookies can be configured for API >= 21.
             // Only enable third-party-cookies if first-party cookies are enabled.
-            if (firstPartyCookiesEnabledInt == 1) {  // First-party cookies are enabled.
+            if (firstPartyCookiesInt == 1) {  // First-party cookies are enabled.
                 // Set the third-party cookies status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
-                if (thirdPartyCookiesEnabledInt == 1) {  // Both first-party and third-party cookies are enabled.
-                    thirdPartyCookiesEnabledSwitch.setChecked(true);
+                if (thirdPartyCookiesInt == 1) {  // Both first-party and third-party cookies are enabled.
+                    thirdPartyCookiesSwitch.setChecked(true);
                     thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
                 } else {  // First party cookies are enabled but third-party cookies are disabled.
-                    thirdPartyCookiesEnabledSwitch.setChecked(false);
+                    thirdPartyCookiesSwitch.setChecked(false);
 
                     // Set the icon according to the theme.
                     if (darkTheme) {
@@ -418,14 +421,14 @@ public class DomainSettingsFragment extends Fragment {
                 }
             } else {  // First-party cookies are disabled.
                 // Set the status of third-party cookies.
-                if (thirdPartyCookiesEnabledInt == 1) {
-                    thirdPartyCookiesEnabledSwitch.setChecked(true);
+                if (thirdPartyCookiesInt == 1) {
+                    thirdPartyCookiesSwitch.setChecked(true);
                 } else {
-                    thirdPartyCookiesEnabledSwitch.setChecked(false);
+                    thirdPartyCookiesSwitch.setChecked(false);
                 }
 
                 // Disable the third-party cookies switch.
-                thirdPartyCookiesEnabledSwitch.setEnabled(false);
+                thirdPartyCookiesSwitch.setEnabled(false);
 
                 // Set the icon according to the theme.
                 if (darkTheme) {
@@ -440,17 +443,17 @@ public class DomainSettingsFragment extends Fragment {
         }
 
         // Only enable DOM storage if JavaScript is enabled.
-        if ((javaScriptEnabledInt == 1) || nightModeEnabled) {  // JavaScript is enabled.
+        if ((javaScriptInt == 1) || nightModeEnabled) {  // JavaScript is enabled.
             // Enable the DOM storage `Switch`.
-            domStorageEnabledSwitch.setEnabled(true);
+            domStorageSwitch.setEnabled(true);
 
             // Set the DOM storage status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
-            if (domStorageEnabledInt == 1) {  // Both JavaScript and DOM storage are enabled.
-                domStorageEnabledSwitch.setChecked(true);
+            if (domStorageInt == 1) {  // Both JavaScript and DOM storage are enabled.
+                domStorageSwitch.setChecked(true);
                 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
             } else {  // JavaScript is enabled but DOM storage is disabled.
                 // Set the DOM storage switch to off.
-                domStorageEnabledSwitch.setChecked(false);
+                domStorageSwitch.setChecked(false);
 
                 // Set the icon according to the theme.
                 if (darkTheme) {
@@ -461,13 +464,13 @@ public class DomainSettingsFragment extends Fragment {
             }
         } else {  // JavaScript is disabled.
             // Disable the DOM storage `Switch`.
-            domStorageEnabledSwitch.setEnabled(false);
+            domStorageSwitch.setEnabled(false);
 
             // Set the checked status of DOM storage.
-            if (domStorageEnabledInt == 1) {  // DOM storage is enabled but JavaScript is disabled.
-                domStorageEnabledSwitch.setChecked(true);
+            if (domStorageInt == 1) {  // DOM storage is enabled but JavaScript is disabled.
+                domStorageSwitch.setChecked(true);
             } else {  // Both JavaScript and DOM storage are disabled.
-                domStorageEnabledSwitch.setChecked(false);
+                domStorageSwitch.setChecked(false);
             }
 
             // Set the icon according to the theme.
@@ -481,14 +484,14 @@ public class DomainSettingsFragment extends Fragment {
         // Set the form data status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.  Form data can be removed once the minimum API >= 26.
         if (Build.VERSION.SDK_INT >= 26) {  // Form data no longer applies to newer versions of Android.
             // Hide the form data switch.
-            formDataEnabledSwitch.setVisibility(View.GONE);
+            formDataSwitch.setVisibility(View.GONE);
         } else {  // Form data should be displayed because this is an older version of Android.
-            if (formDataEnabledInt == 1) {  // Form data is on.
-                formDataEnabledSwitch.setChecked(true);
+            if (formDataInt == 1) {  // Form data is on.
+                formDataSwitch.setChecked(true);
                 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
             } else {  // Form data is off.
                 // Turn the form data switch to off.
-                formDataEnabledSwitch.setChecked(false);
+                formDataSwitch.setChecked(false);
 
                 // Set the icon according to the theme.
                 if (darkTheme) {
@@ -500,7 +503,7 @@ public class DomainSettingsFragment extends Fragment {
         }
 
         // Set the EasyList status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
-        if (easyListEnabledInt == 1) {  // EasyList is on.
+        if (easyListInt == 1) {  // EasyList is on.
             // Turn the switch on.
             easyListSwitch.setChecked(true);
 
@@ -523,7 +526,7 @@ public class DomainSettingsFragment extends Fragment {
         }
 
         // Set the EasyPrivacy status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
-        if (easyPrivacyEnabledInt == 1) {  // EasyPrivacy is on.
+        if (easyPrivacyInt == 1) {  // EasyPrivacy is on.
             // Turn the switch on.
             easyPrivacySwitch.setChecked(true);
 
@@ -614,8 +617,31 @@ public class DomainSettingsFragment extends Fragment {
             }
         }
 
+        // Set the UltraList status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
+        if (ultraListInt == 1) {  // UltraList is on.
+            // Turn the switch on.
+            ultraListSwitch.setChecked(true);
+
+            // Set the icon according to the theme.
+            if (darkTheme) {
+                ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
+            } else {
+                ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
+            }
+        } else {  // UltraList is off.
+            // Turn the switch off.
+            ultraListSwitch.setChecked(false);
+
+            // Set the icon according to the theme.
+            if (darkTheme) {
+                ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
+            } else {
+                ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
+            }
+        }
+
         // Set the UltraPrivacy status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
-        if (ultraPrivacyEnabledInt == 1) {  // UltraPrivacy is on.
+        if (ultraPrivacyInt == 1) {  // UltraPrivacy is on.
             // Turn the switch on.
             ultraPrivacySwitch.setChecked(true);
 
@@ -1269,16 +1295,16 @@ public class DomainSettingsFragment extends Fragment {
 
 
         // Set the JavaScript switch listener.
-        javaScriptEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+        javaScriptSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
             if (isChecked) {  // JavaScript is enabled.
                 // Update the JavaScript icon.
                 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
 
                 // Enable the DOM storage `Switch`.
-                domStorageEnabledSwitch.setEnabled(true);
+                domStorageSwitch.setEnabled(true);
 
                 // Update the DOM storage icon.
-                if (domStorageEnabledSwitch.isChecked()) {  // DOM storage is enabled.
+                if (domStorageSwitch.isChecked()) {  // DOM storage is enabled.
                     domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
                 } else {  // DOM storage is disabled.
                     // Set the icon according to the theme.
@@ -1293,7 +1319,7 @@ public class DomainSettingsFragment extends Fragment {
                 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
 
                 // Disable the DOM storage `Switch`.
-                domStorageEnabledSwitch.setEnabled(false);
+                domStorageSwitch.setEnabled(false);
 
                 // Set the DOM storage icon according to the theme.
                 if (darkTheme) {
@@ -1305,16 +1331,16 @@ public class DomainSettingsFragment extends Fragment {
         });
 
         // Set the first-party cookies switch listener.
-        firstPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+        firstPartyCookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
             if (isChecked) {  // First-party cookies are enabled.
                 // Update the first-party cookies icon.
                 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
 
                 // Enable the third-party cookies switch.
-                thirdPartyCookiesEnabledSwitch.setEnabled(true);
+                thirdPartyCookiesSwitch.setEnabled(true);
 
                 // Update the third-party cookies icon.
-                if (thirdPartyCookiesEnabledSwitch.isChecked()) {  // Third-party cookies are enabled.
+                if (thirdPartyCookiesSwitch.isChecked()) {  // Third-party cookies are enabled.
                     thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
                 } else {  // Third-party cookies are disabled.
                     // Set the third-party cookies icon according to the theme.
@@ -1333,7 +1359,7 @@ public class DomainSettingsFragment extends Fragment {
                 }
 
                 // Disable the third-party cookies switch.
-                thirdPartyCookiesEnabledSwitch.setEnabled(false);
+                thirdPartyCookiesSwitch.setEnabled(false);
 
                 // Set the third-party cookies icon according to the theme.
                 if (darkTheme) {
@@ -1345,7 +1371,7 @@ public class DomainSettingsFragment extends Fragment {
         });
 
         // Set the third-party cookies switch listener.
-        thirdPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+        thirdPartyCookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
             // Update the icon.
             if (isChecked) {
                 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
@@ -1360,7 +1386,7 @@ public class DomainSettingsFragment extends Fragment {
         });
 
         // Set the DOM Storage switch listener.
-        domStorageEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+        domStorageSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
             // Update the icon.
             if (isChecked) {
                 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
@@ -1376,7 +1402,7 @@ public class DomainSettingsFragment extends Fragment {
 
         // Set the form data switch listener.  It can be removed once the minimum API >= 26.
         if (Build.VERSION.SDK_INT < 26) {
-            formDataEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+            formDataSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
                 // Update the icon.
                 if (isChecked) {
                     formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
@@ -1502,6 +1528,26 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
+        // Set the UltraList switch listener.
+        ultraListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+            // Update the icon.
+            if (isChecked) {  // UltraList is on.
+                // Set the icon according to the theme.
+                if (darkTheme) {
+                    ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
+                } else {
+                    ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
+                }
+            } else {  // UltraList is off.
+                // Set the icon according to the theme.
+                if (darkTheme) {
+                    ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
+                } else {
+                    ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
+                }
+            }
+        });
+
         // Set the UltraPrivacy switch listener.
         ultraPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
             // Update the icon.
@@ -1740,35 +1786,35 @@ public class DomainSettingsFragment extends Fragment {
                         break;
                 }
 
-                // Create a `boolean` to store the current night mode setting.
+                // Create a boolean to store the current night mode setting.
                 boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.ENABLED) || ((position == DomainsDatabaseHelper.SYSTEM_DEFAULT) && defaultNightMode);
 
-                // Disable the JavaScript `Switch` if night mode is enabled.
+                // Disable the JavaScript switch if night mode is enabled.
                 if (currentNightModeEnabled) {
-                    javaScriptEnabledSwitch.setEnabled(false);
+                    javaScriptSwitch.setEnabled(false);
                 } else {
-                    javaScriptEnabledSwitch.setEnabled(true);
+                    javaScriptSwitch.setEnabled(true);
                 }
 
                 // Update the JavaScript icon.
-                if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) {
+                if ((javaScriptInt == 1) || currentNightModeEnabled) {
                     javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
                 } else {
                     javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
                 }
 
                 // Update the DOM storage status.
-                if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) {  // JavaScript is enabled.
+                if ((javaScriptInt == 1) || currentNightModeEnabled) {  // JavaScript is enabled.
                     // Enable the DOM storage `Switch`.
-                    domStorageEnabledSwitch.setEnabled(true);
+                    domStorageSwitch.setEnabled(true);
 
                     // Set the DOM storage status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
-                    if (domStorageEnabledInt == 1) {  // Both JavaScript and DOM storage are enabled.
-                        domStorageEnabledSwitch.setChecked(true);
+                    if (domStorageInt == 1) {  // Both JavaScript and DOM storage are enabled.
+                        domStorageSwitch.setChecked(true);
                         domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
                     } else {  // JavaScript is enabled but DOM storage is disabled.
                         // Set the DOM storage switch to off.
-                        domStorageEnabledSwitch.setChecked(false);
+                        domStorageSwitch.setChecked(false);
 
                         // Set the icon according to the theme.
                         if (darkTheme) {
@@ -1779,13 +1825,13 @@ public class DomainSettingsFragment extends Fragment {
                     }
                 } else {  // JavaScript is disabled.
                     // Disable the DOM storage `Switch`.
-                    domStorageEnabledSwitch.setEnabled(false);
+                    domStorageSwitch.setEnabled(false);
 
                     // Set the checked status of DOM storage.
-                    if (domStorageEnabledInt == 1) {  // DOM storage is enabled but JavaScript is disabled.
-                        domStorageEnabledSwitch.setChecked(true);
+                    if (domStorageInt == 1) {  // DOM storage is enabled but JavaScript is disabled.
+                        domStorageSwitch.setChecked(true);
                     } else {  // Both JavaScript and DOM storage are disabled.
-                        domStorageEnabledSwitch.setChecked(false);
+                        domStorageSwitch.setChecked(false);
                     }
 
                     // Set the icon according to the theme.
index 7dab898..1746f71 100644 (file)
@@ -70,6 +70,7 @@ public class SettingsFragment extends PreferenceFragment {
         Preference easyPrivacyPreference = findPreference("easyprivacy");
         Preference fanboyAnnoyanceListPreference = findPreference("fanboys_annoyance_list");
         Preference fanboySocialBlockingListPreference = findPreference("fanboys_social_blocking_list");
+        Preference ultraListPreference = findPreference("ultralist");
         Preference ultraPrivacyPreference = findPreference("ultraprivacy");
         Preference blockAllThirdPartyRequestsPreference = findPreference("block_all_third_party_requests");
         Preference googleAnalyticsPreference = findPreference("google_analytics");
@@ -431,6 +432,21 @@ public class SettingsFragment extends PreferenceFragment {
             }
         }
 
+        // Set the UltraList icon.
+        if (savedPreferences.getBoolean("ultralist", true)){
+            if (darkTheme) {
+                ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
+            } else {
+                ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
+            }
+        } else {
+            if (darkTheme) {
+                ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
+            } else {
+                ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
+            }
+        }
+
         // Set the UltraPrivacy icon.
         if (savedPreferences.getBoolean("ultraprivacy", true)) {
             if (darkTheme) {
@@ -1140,6 +1156,23 @@ public class SettingsFragment extends PreferenceFragment {
                     }
                     break;
 
+                case "ultralist":
+                    // Update the icon.
+                    if (sharedPreferences.getBoolean("ultralist", true)) {
+                        if (darkTheme) {
+                            ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
+                        } else {
+                            ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
+                        }
+                    } else {
+                        if (darkTheme) {
+                            ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
+                        } else {
+                            ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
+                        }
+                    }
+                    break;
+
                 case "ultraprivacy":
                     // Update the icon.
                     if (sharedPreferences.getBoolean("ultraprivacy", true)) {
index d7f92af..1e40f97 100644 (file)
@@ -28,7 +28,7 @@ import android.database.sqlite.SQLiteOpenHelper;
 import android.preference.PreferenceManager;
 
 public class DomainsDatabaseHelper extends SQLiteOpenHelper {
-    private static final int SCHEMA_VERSION = 10;
+    private static final int SCHEMA_VERSION = 11;
     static final String DOMAINS_DATABASE = "domains.db";
     static final String DOMAINS_TABLE = "domains";
 
@@ -43,6 +43,7 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
     public static final String ENABLE_EASYPRIVACY = "enableeasyprivacy";
     public static final String ENABLE_FANBOYS_ANNOYANCE_LIST = "enablefanboysannoyancelist";
     public static final String ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = "enablefanboyssocialblockinglist";
+    public static final String ULTRALIST = "ultralist";
     public static final String ENABLE_ULTRAPRIVACY = "enableultraprivacy";
     public static final String BLOCK_ALL_THIRD_PARTY_REQUESTS = "blockallthirdpartyrequests";
     public static final String USER_AGENT = "useragent";
@@ -80,6 +81,7 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
             ENABLE_EASYPRIVACY + " BOOLEAN, " +
             ENABLE_FANBOYS_ANNOYANCE_LIST + " BOOLEAN, " +
             ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST + " BOOLEAN, " +
+            ULTRALIST + " BOOLEAN, " +
             ENABLE_ULTRAPRIVACY + " BOOLEAN, " +
             BLOCK_ALL_THIRD_PARTY_REQUESTS + " BOOLEAN, " +
             USER_AGENT + " TEXT, " +
@@ -216,6 +218,14 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
             case 9:
                 // Add the Wide Viewport column.
                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + WIDE_VIEWPORT + " INTEGER");
+
+            // Upgrade from schema version 10.
+            case 10:
+                // Add the UltraList column.
+                domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ULTRALIST + " BOOLEAN");
+
+                // Enable it for all existing rows.
+                domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ULTRALIST + " = " + 1);
         }
     }
 
@@ -283,30 +293,32 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext);
 
         // Get the default settings.
-        boolean javaScriptEnabled = sharedPreferences.getBoolean("javascript", false);
-        boolean firstPartyCookiesEnabled = sharedPreferences.getBoolean("first_party_cookies", false);
-        boolean thirdPartyCookiesEnabled = sharedPreferences.getBoolean("third_party_cookies", false);
-        boolean domStorageEnabled = sharedPreferences.getBoolean("dom_storage", false);
-        boolean saveFormDataEnabled = sharedPreferences.getBoolean("save_form_data", false);  // Form data can be removed once the minimum API >= 26.
-        boolean easyListEnabled = sharedPreferences.getBoolean("easylist", true);
-        boolean easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true);
-        boolean fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
-        boolean fanboySocialBlockingListEnabled = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
-        boolean ultraPrivacyEnabled = sharedPreferences.getBoolean("ultraprivacy", true);
+        boolean javaScript = sharedPreferences.getBoolean("javascript", false);
+        boolean firstPartyCookies = sharedPreferences.getBoolean("first_party_cookies", false);
+        boolean thirdPartyCookies = sharedPreferences.getBoolean("third_party_cookies", false);
+        boolean domStorage = sharedPreferences.getBoolean("dom_storage", false);
+        boolean saveFormData = sharedPreferences.getBoolean("save_form_data", false);  // Form data can be removed once the minimum API >= 26.
+        boolean easyList = sharedPreferences.getBoolean("easylist", true);
+        boolean easyPrivacy = sharedPreferences.getBoolean("easyprivacy", true);
+        boolean fanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
+        boolean fanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
+        boolean ultraList = sharedPreferences.getBoolean("ultralist", true);
+        boolean ultraPrivacy = sharedPreferences.getBoolean("ultraprivacy", true);
         boolean blockAllThirdPartyRequests = sharedPreferences.getBoolean("block_all_third_party_requests", false);
 
         // Create entries for the database fields.  The ID is created automatically.  The pinned SSL certificate information is not created unless added by the user.
         domainContentValues.put(DOMAIN_NAME, domainName);
-        domainContentValues.put(ENABLE_JAVASCRIPT, javaScriptEnabled);
-        domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, firstPartyCookiesEnabled);
-        domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, thirdPartyCookiesEnabled);
-        domainContentValues.put(ENABLE_DOM_STORAGE, domStorageEnabled);
-        domainContentValues.put(ENABLE_FORM_DATA, saveFormDataEnabled);  // Form data can be removed once the minimum API >= 26.
-        domainContentValues.put(ENABLE_EASYLIST, easyListEnabled);
-        domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacyEnabled);
-        domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboyAnnoyanceListEnabled);
-        domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboySocialBlockingListEnabled);
-        domainContentValues.put(ENABLE_ULTRAPRIVACY, ultraPrivacyEnabled);
+        domainContentValues.put(ENABLE_JAVASCRIPT, javaScript);
+        domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, firstPartyCookies);
+        domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, thirdPartyCookies);
+        domainContentValues.put(ENABLE_DOM_STORAGE, domStorage);
+        domainContentValues.put(ENABLE_FORM_DATA, saveFormData);  // Form data can be removed once the minimum API >= 26.
+        domainContentValues.put(ENABLE_EASYLIST, easyList);
+        domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacy);
+        domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboyAnnoyanceList);
+        domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboySocialBlockingList);
+        domainContentValues.put(ULTRALIST, ultraList);
+        domainContentValues.put(ENABLE_ULTRAPRIVACY, ultraPrivacy);
         domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests);
         domainContentValues.put(USER_AGENT, "System default user agent");
         domainContentValues.put(FONT_SIZE, 0);
@@ -339,26 +351,26 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
         domainsDatabase.close();
     }
 
-    public void updateDomain(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled, boolean formDataEnabled,
-                             boolean easyListEnabled, boolean easyPrivacyEnabled, boolean fanboysAnnoyanceEnabled, boolean fanboysSocialBlockingEnabled, boolean ultraPrivacyEnabled,
-                             boolean blockAllThirdPartyRequests, String userAgent, int fontSize, int swipeToRefresh, int nightMode, int wideViewport, int displayImages, boolean pinnedSslCertificate,
-                             boolean pinnedIpAddresses) {
+    public void updateDomain(int databaseId, String domainName, boolean javaScript, boolean firstPartyCookies, boolean thirdPartyCookies, boolean domStorage, boolean formData, boolean easyList,
+                             boolean easyPrivacy, boolean fanboysAnnoyance, boolean fanboysSocialBlocking, boolean ultraList, boolean ultraPrivacy, boolean blockAllThirdPartyRequests, String userAgent,
+                             int fontSize, int swipeToRefresh, int nightMode, int wideViewport, int displayImages, boolean pinnedSslCertificate, boolean pinnedIpAddresses) {
 
         // Store the domain data in a `ContentValues`.
         ContentValues domainContentValues = new ContentValues();
 
         // Add entries for each field in the database.
         domainContentValues.put(DOMAIN_NAME, domainName);
-        domainContentValues.put(ENABLE_JAVASCRIPT, javaScriptEnabled);
-        domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, firstPartyCookiesEnabled);
-        domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, thirdPartyCookiesEnabled);
-        domainContentValues.put(ENABLE_DOM_STORAGE, domStorageEnabled);
-        domainContentValues.put(ENABLE_FORM_DATA, formDataEnabled);  // Form data can be removed once the minimum API >= 26.
-        domainContentValues.put(ENABLE_EASYLIST, easyListEnabled);
-        domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacyEnabled);
-        domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboysAnnoyanceEnabled);
-        domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboysSocialBlockingEnabled);
-        domainContentValues.put(ENABLE_ULTRAPRIVACY, ultraPrivacyEnabled);
+        domainContentValues.put(ENABLE_JAVASCRIPT, javaScript);
+        domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, firstPartyCookies);
+        domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, thirdPartyCookies);
+        domainContentValues.put(ENABLE_DOM_STORAGE, domStorage);
+        domainContentValues.put(ENABLE_FORM_DATA, formData);  // Form data can be removed once the minimum API >= 26.
+        domainContentValues.put(ENABLE_EASYLIST, easyList);
+        domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacy);
+        domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboysAnnoyance);
+        domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboysSocialBlocking);
+        domainContentValues.put(ULTRALIST, ultraList);
+        domainContentValues.put(ENABLE_ULTRAPRIVACY, ultraPrivacy);
         domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests);
         domainContentValues.put(USER_AGENT, userAgent);
         domainContentValues.put(FONT_SIZE, fontSize);
index f0262d1..35d8fe8 100644 (file)
@@ -38,7 +38,7 @@ public class ImportExportDatabaseHelper {
     public static final String EXPORT_SUCCESSFUL = "Export Successful";
     public static final String IMPORT_SUCCESSFUL = "Import Successful";
 
-    private static final int SCHEMA_VERSION = 7;
+    private static final int SCHEMA_VERSION = 8;
     private static final String PREFERENCES_TABLE = "preferences";
 
     // The preferences constants.
@@ -57,6 +57,7 @@ public class ImportExportDatabaseHelper {
     private static final String EASYPRIVACY = "easyprivacy";
     private static final String FANBOYS_ANNOYANCE_LIST = "fanboys_annoyance_list";
     private static final String FANBOYS_SOCIAL_BLOCKING_LIST = "fanboys_social_blocking_list";
+    private static final String ULTRALIST = "ultralist";
     private static final String ULTRAPRIVACY = "ultraprivacy";
     private static final String BLOCK_ALL_THIRD_PARTY_REQUESTS = "block_all_third_party_requests";
     private static final String GOOGLE_ANALYTICS = "google_analytics";
@@ -127,6 +128,7 @@ public class ImportExportDatabaseHelper {
                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)));
                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)));
                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)));
+                domainsContentValues.put(DomainsDatabaseHelper.ULTRALIST, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST)));
                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)));
                 domainsContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)));
                 domainsContentValues.put(DomainsDatabaseHelper.USER_AGENT, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)));
@@ -211,6 +213,7 @@ public class ImportExportDatabaseHelper {
                     EASYPRIVACY + " BOOLEAN, " +
                     FANBOYS_ANNOYANCE_LIST + " BOOLEAN, " +
                     FANBOYS_SOCIAL_BLOCKING_LIST + " BOOLEAN, " +
+                    ULTRALIST + " BOOLEAN, " +
                     ULTRAPRIVACY + " BOOLEAN, " +
                     BLOCK_ALL_THIRD_PARTY_REQUESTS + " BOOLEAN, " +
                     GOOGLE_ANALYTICS + " BOOLEAN, " +
@@ -263,6 +266,7 @@ public class ImportExportDatabaseHelper {
             preferencesContentValues.put(EASYPRIVACY, sharedPreferences.getBoolean(EASYPRIVACY, true));
             preferencesContentValues.put(FANBOYS_ANNOYANCE_LIST, sharedPreferences.getBoolean(FANBOYS_ANNOYANCE_LIST, true));
             preferencesContentValues.put(FANBOYS_SOCIAL_BLOCKING_LIST, sharedPreferences.getBoolean(FANBOYS_SOCIAL_BLOCKING_LIST, true));
+            preferencesContentValues.put(ULTRALIST, sharedPreferences.getBoolean(ULTRALIST, true));
             preferencesContentValues.put(ULTRAPRIVACY, sharedPreferences.getBoolean(ULTRAPRIVACY, true));
             preferencesContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, sharedPreferences.getBoolean(BLOCK_ALL_THIRD_PARTY_REQUESTS, false));
             preferencesContentValues.put(GOOGLE_ANALYTICS, sharedPreferences.getBoolean(GOOGLE_ANALYTICS, true));
@@ -495,6 +499,26 @@ public class ImportExportDatabaseHelper {
                         } else {
                             importDatabase.execSQL("UPDATE " + PREFERENCES_TABLE + " SET " + WIDE_VIEWPORT + " = " + 0);
                         }
+
+                    // Upgrade from schema version 7.
+                    case 7:
+                        // Add the UltraList column to the domains table.
+                        importDatabase.execSQL("ALTER TABLE " + DomainsDatabaseHelper.DOMAINS_TABLE + " ADD COLUMN " + DomainsDatabaseHelper.ULTRALIST + " BOOLEAN");
+
+                        // Add the UltraList column to the preferences table.
+                        importDatabase.execSQL("ALTER TABLE " + PREFERENCES_TABLE + " ADD COLUMN " + ULTRALIST + " BOOLEAN");
+
+                        // Get the current preference values.
+                        boolean ultraList = sharedPreferences.getBoolean(ULTRALIST, true);
+
+                        // Populate the tables with the current UltraList value.
+                        if (ultraList) {
+                            importDatabase.execSQL("UPDATE " + DomainsDatabaseHelper.DOMAINS_TABLE + " SET " + DomainsDatabaseHelper.ULTRALIST + " = " + 1);
+                            importDatabase.execSQL("UPDATE " + PREFERENCES_TABLE + " SET " + ULTRALIST + " = " + 1);
+                        } else {
+                            importDatabase.execSQL("UPDATE " + DomainsDatabaseHelper.DOMAINS_TABLE + " SET " + DomainsDatabaseHelper.ULTRALIST + " = " + 0);
+                            importDatabase.execSQL("UPDATE " + PREFERENCES_TABLE + " SET " + ULTRALIST + " = " + 0);
+                        }
                 }
             }
 
@@ -526,6 +550,7 @@ public class ImportExportDatabaseHelper {
                         importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)));
                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST,
                         importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)));
+                domainsContentValues.put(DomainsDatabaseHelper.ULTRALIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST)));
                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)));
                 domainsContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS,
                         importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)));
@@ -623,6 +648,7 @@ public class ImportExportDatabaseHelper {
                     .putBoolean(EASYPRIVACY, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(EASYPRIVACY)) == 1)
                     .putBoolean(FANBOYS_ANNOYANCE_LIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(FANBOYS_ANNOYANCE_LIST)) == 1)
                     .putBoolean(FANBOYS_SOCIAL_BLOCKING_LIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(FANBOYS_SOCIAL_BLOCKING_LIST)) == 1)
+                    .putBoolean(ULTRALIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(ULTRALIST)) == 1)
                     .putBoolean(ULTRAPRIVACY, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(ULTRAPRIVACY)) == 1)
                     .putBoolean(BLOCK_ALL_THIRD_PARTY_REQUESTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1)
                     .putBoolean(GOOGLE_ANALYTICS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(GOOGLE_ANALYTICS)) == 1)
index ddb1533..c7a2227 100644 (file)
@@ -46,12 +46,13 @@ import java.util.List;
 public class NestedScrollWebView extends WebView implements NestedScrollingChild2 {
     // These constants identify the blocklists.
     public final static int BLOCKED_REQUESTS = 0;
-    public final static int EASY_LIST = 1;
-    public final static int EASY_PRIVACY = 2;
+    public final static int EASYLIST = 1;
+    public final static int EASYPRIVACY = 2;
     public final static int FANBOYS_ANNOYANCE_LIST = 3;
     public final static int FANBOYS_SOCIAL_BLOCKING_LIST = 4;
-    public final static int ULTRA_PRIVACY = 5;
-    public final static int THIRD_PARTY_REQUESTS = 6;
+    public final static int ULTRALIST = 5;
+    public final static int ULTRAPRIVACY = 6;
+    public final static int THIRD_PARTY_REQUESTS = 7;
 
     // Keep a copy of the WebView fragment ID.
     private long webViewFragmentId;
@@ -79,6 +80,7 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
     private boolean easyPrivacyEnabled;
     private boolean fanboysAnnoyanceListEnabled;
     private boolean fanboysSocialBlockingListEnabled;
+    private boolean ultraListEnabled;
     private boolean ultraPrivacyEnabled;
     private boolean blockAllThirdPartyRequests;
     private int blockedRequests;
@@ -86,6 +88,7 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
     private int easyPrivacyBlockedRequests;
     private int fanboysAnnoyanceListBlockedRequests;
     private int fanboysSocialBlockingListBlockedRequests;
+    private int ultraListBlockedRequests;
     private int ultraPrivacyBlockedRequests;
     private int thirdPartyBlockedRequests;
 
@@ -289,12 +292,12 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
     public void enableBlocklist(int blocklist, boolean status) {
         // Update the status of the indicated blocklist.
         switch (blocklist) {
-            case EASY_LIST:
+            case EASYLIST:
                 // Update the status of the blocklist.
                 easyListEnabled = status;
                 break;
 
-            case EASY_PRIVACY:
+            case EASYPRIVACY:
                 // Update the status of the blocklist.
                 easyPrivacyEnabled = status;
                 break;
@@ -309,7 +312,12 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
                 fanboysSocialBlockingListEnabled = status;
                 break;
 
-            case ULTRA_PRIVACY:
+            case ULTRALIST:
+                // Update the status of the blocklist.
+                ultraListEnabled = status;
+                break;
+
+            case ULTRAPRIVACY:
                 // Update the status of the blocklist.
                 ultraPrivacyEnabled = status;
                 break;
@@ -324,11 +332,11 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
     public boolean isBlocklistEnabled(int blocklist) {
         // Get the status of the indicated blocklist.
         switch (blocklist) {
-            case EASY_LIST:
+            case EASYLIST:
                 // Return the status of the blocklist.
                 return easyListEnabled;
 
-            case EASY_PRIVACY:
+            case EASYPRIVACY:
                 // Return the status of the blocklist.
                 return easyPrivacyEnabled;
 
@@ -340,7 +348,11 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
                 // Return the status of the blocklist.
                 return fanboysSocialBlockingListEnabled;
 
-            case ULTRA_PRIVACY:
+            case ULTRALIST:
+                // Return the status of the blocklist.
+                return ultraListEnabled;
+
+            case ULTRAPRIVACY:
                 // Return the status of the blocklist.
                 return ultraPrivacyEnabled;
 
@@ -363,6 +375,7 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
         easyPrivacyBlockedRequests = 0;
         fanboysAnnoyanceListBlockedRequests = 0;
         fanboysSocialBlockingListBlockedRequests = 0;
+        ultraListBlockedRequests = 0;
         ultraPrivacyBlockedRequests = 0;
         thirdPartyBlockedRequests = 0;
     }
@@ -375,12 +388,12 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
                 blockedRequests++;
                 break;
 
-            case EASY_LIST:
+            case EASYLIST:
                 // Increment the EasyList blocked requests count.
                 easyListBlockedRequests++;
                 break;
 
-            case EASY_PRIVACY:
+            case EASYPRIVACY:
                 // Increment the EasyPrivacy blocked requests count.
                 easyPrivacyBlockedRequests++;
                 break;
@@ -395,7 +408,12 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
                 fanboysSocialBlockingListBlockedRequests++;
                 break;
 
-            case ULTRA_PRIVACY:
+            case ULTRALIST:
+                // Increment the UltraList blocked requests count.
+                ultraListBlockedRequests++;
+                break;
+
+            case ULTRAPRIVACY:
                 // Increment the UltraPrivacy blocked requests count.
                 ultraPrivacyBlockedRequests++;
                 break;
@@ -414,11 +432,11 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
                 // Return the blocked requests count.
                 return blockedRequests;
 
-            case EASY_LIST:
+            case EASYLIST:
                 // Return the EasyList blocked requests count.
                 return easyListBlockedRequests;
 
-            case EASY_PRIVACY:
+            case EASYPRIVACY:
                 // Return the EasyPrivacy blocked requests count.
                 return easyPrivacyBlockedRequests;
 
@@ -430,7 +448,11 @@ public class NestedScrollWebView extends WebView implements NestedScrollingChild
                 // Return the Fanboy's Social Blocking List blocked requests count.
                 return fanboysSocialBlockingListBlockedRequests;
 
-            case ULTRA_PRIVACY:
+            case ULTRALIST:
+                // Return the UltraList blocked requests count.
+                return ultraListBlockedRequests;
+
+            case ULTRAPRIVACY:
                 // Return the UltraPrivacy blocked requests count.
                 return ultraPrivacyBlockedRequests;
 
index 8dc5e67..df489fe 100644 (file)
                 android:layout_width="wrap_content"
                 android:textIsSelectable="true" />
 
+            <TextView
+                android:id="@+id/ultralist"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:textIsSelectable="true" />
+
             <TextView
                 android:id="@+id/ultraprivacy"
                 android:layout_height="wrap_content"
index 6673bbe..8c28398 100644 (file)
                 android:textSize="18sp" />
         </LinearLayout>
 
+        <!-- UltraList. -->
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:orientation="horizontal" >
+
+            <ImageView
+                android:id="@+id/ultralist_imageview"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_marginTop="1dp"
+                android:layout_marginEnd="10dp"
+                android:layout_gravity="center_vertical"
+                tools:ignore="contentDescription" />
+
+            <Switch
+                android:id="@+id/ultralist_switch"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:layout_marginStart="8dp"
+                android:layout_marginTop="14dp"
+                android:layout_marginBottom="14dp"
+                android:text="@string/ultralist"
+                android:textColor="?android:textColorPrimary"
+                android:textSize="18sp" />
+        </LinearLayout>
+
         <!-- UltraPrivacy. -->
         <LinearLayout
             android:layout_height="wrap_content"
index 81f47f9..78f0ea3 100644 (file)
                 android:checkable="true"
                 app:showAsAction="never" />
 
+            <item
+                android:id="@+id/ultralist"
+                android:title="@string/ultralist"
+                android:orderInCategory="850"
+                android:checkable="true"
+                app:showAsAction="never" />
+
             <item
                 android:id="@+id/ultraprivacy"
                 android:title="@string/ultraprivacy"
-                android:orderInCategory="850"
+                android:orderInCategory="860"
                 android:checkable="true"
                 app:showAsAction="never" />
 
             <item
                 android:id="@+id/block_all_third_party_requests"
                 android:title="@string/options_block_all_third_party_requests"
-                android:orderInCategory="860"
+                android:orderInCategory="870"
                 android:checkable="true"
                 app:showAsAction="never" />
         </menu>
index fdc58f4..4d54546 100644 (file)
@@ -62,6 +62,7 @@
     <string name="loading_easyprivacy">Loading EasyPrivacy</string>
     <string name="loading_fanboys_annoyance_list">Loading Fanboy’s Annoyance List</string>
     <string name="loading_fanboys_social_blocking_list">Loading Fanboy’s Social Blocking List</string>
+    <string name="loading_ultralist">Loading UltraList</string>
     <string name="loading_ultraprivacy">Loading UltraPrivacy</string>
 
     <!-- Save As. -->
     <string name="easyprivacy_label">EasyPrivacy:</string>
     <string name="fanboy_annoyance_label">Fanboy’s Annoyance List:</string>
     <string name="fanboy_social_label">Fanboy’s Social Blocking List:</string>
+    <string name="ultralist_label">UltraList:</string>
     <string name="ultraprivacy_label">UltraPrivacy:</string>
     <string name="package_signature">Package Signature</string>
     <string name="issuer_dn">Issuer DN:</string>
         <string name="fanboys_annoyance_list_summary">Block annoying popups and links.  Includes Fanboy’s social blocking lists.</string>
         <string name="fanboys_social_blocking_list">Fanboy’s social blocking list</string>
         <string name="fanboys_social_blocking_list_summary">Blocks third-party social media content.</string>
+        <string name="ultralist">UltraList</string>
+        <string name="ultralist_summary">UltraList blocks ads that EasyList doesn’t because doing so can break websites.</string>
         <string name="ultraprivacy">UltraPrivacy</string>
         <string name="ultraprivacy_summary">UltraPrivacy blocks trackers that EasyPrivacy doesn’t because doing so can break websites.</string>
         <string name="block_all_third_party_requests">Block all third-party requests</string>
index cef3f57..4c266c2 100644 (file)
             android:summary="@string/fanboys_social_blocking_list_summary"
             android:defaultValue="true" />
 
+        <SwitchPreference
+            android:key="ultralist"
+            android:title="@string/ultralist"
+            android:summary="@string/ultralist_summary"
+            android:defaultValue="true" />
+
         <SwitchPreference
             android:key="ultraprivacy"
             android:title="@string/ultraprivacy"
index 4e17295..711cbe7 100644 (file)
@@ -25,7 +25,7 @@ buildscript {
         google()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.4.1'
+        classpath 'com.android.tools.build:gradle:3.4.2'
 
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files