]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/commitdiff
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 26f04bc79fd4b2f44c1f7e78f7c357dd1855fe94..082684678722288322964f46995ec6cf4809a4c9 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 d081c8f7857d153f1a86bb8da63cc07f589f5ca8..1083b6e95a1ceec3f349839d1d2341f9214971b6 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 d8f50572404de093d0df0f000d7a886f1d757e52..6e509a210befb282d7fcd876b0d313c94ed870ec 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 6e531f262e673e8145ed123f18411ed25ca2a16b..0f5c33c3150f0b608b9b197ae24ad62ce859f0af 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 bde2af73f4a6c3a3472706a03a38f85986efd2c3..87ac5ad4a601a5adb63dd1ff1e71871269fe5198 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 297fc1ed8040b965a46c12face08a85e5405b407..c28934362ee26f9b43cbe6822ce47b81b6bf2446 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 4344a5e0f12a3a5a349a7f2a5d56a27a65c2fe51..f400818208e8ce046d4522ea21b887b0f2d276d8 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 a7ccebe312f39f39a9b6241f9cdd8af0ff639c7d..8e69863e3c7b9aaaaa410c877d8442315bd9ccb8 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 3d8eaf583909751ae32038132f7f4afb2fd1c346..7eaa309cbe8827d8168cfbcd50901fd881fe54f8 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 4ec554dbe78c0a4792c07136d60597cbbe1b5de6..72bdf4ef39e6141b9f42134e5ad3ba1b7373166f 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 f2d036ab86ebbbd488ae25e9e32eb77f13b9a077..63f38783c54f81cf5dcbdbc5a003762e06fcb59d 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 59b43a8b4d15dab2da0a41c037f7e7d4af472d72..533a4199249766cd598de25b8e61320283525048 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 2c55a623e72b8ac3c9dbe63dbfa68af16707a5e9..3039f39ccb987cef00beaf49ec353075e8f4c3b5 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 e73b94e0425846b2cdc89db1bbb1f6c8746c8f74..037ed592f8cf056977defb4d7963f225cf1a82f0 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 4d3a4da0e8d1ac17111cb26b3e69f8d160e0c010..097c8af9b883b443710a0fd3375af767829ece81 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 7a7fc4da126af15f92cad38ee273dff90b5e5a51..75306368addbffd4e508ba2865430fbcf73383d9 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 27db5d1ada689cd0344d351332c861b9dc4ca4b6..8496d00fdf1b94f995878a65ea35d1b1f7fc1ec5 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 5386b77dbb2135b9f7e76d469d700df9af7a9d37..4007dbf097899f54cf8087adbd893d59c431c0f7 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 7dab898e383cb203bd84609b33cd6943cffc22ba..1746f71875778ec41465bef8299080995a9b6de1 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 d7f92af6f8d9d7c88e6956c099ab6a35aac13b81..1e40f9705244d454e82a8d4145e7788222f5de56 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 f0262d12b755fd9775f4ebde0173e9c63b3dbac3..35d8fe87f0b304eb087bc950c0665f5a9f49f013 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 ddb1533bcd7cd59711a11dd42c74aacdd2491004..c7a2227802391dd10cbb7a2ed6bee2d663df3605 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 8dc5e677cc48700732d94d71e6b2442310490246..df489fedeef704638414f5e7b2df2891563840c0 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 6673bbed9fdd6958cfd918125f5d0aac56b4a372..8c28398c907e8a674aae8b8550bc32748b564628 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 81f47f99c8dec31ecc28e2204ed40aebf0e86d60..78f0ea3390f761ff925b6bf92eca5dd434413074 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 fdc58f4aa76d57672968d4a52a2596be4977d63d..4d545469907e7dd94a7c81cfc90acbf6683d52ef 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 cef3f575f2510e6ca65fb5f49adfc2bf24ecf9ca..4c266c273d7f67f350299df1cfb01976d18682f8 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 4e17295e75eb3d5c493a957f90b4b5758446b84e..711cbe79fce93277293d2e824c6a99be98a164ff 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